kong/spec/02-integration/05-proxy/10-balancer/04-round-robin_spec.lua (304 lines of code) (raw):

local bu = require "spec.fixtures.balancer_utils" local helpers = require "spec.helpers" local https_server = helpers.https_server for _, consistency in ipairs(bu.consistencies) do for _, strategy in helpers.each_strategy() do describe("Balancing with round-robin #" .. consistency, function() local bp lazy_setup(function() bp = bu.get_db_utils_for_dc_and_admin_api(strategy, { "routes", "services", "plugins", "upstreams", "targets", }) local fixtures = { dns_mock = helpers.dns_mock.new() } fixtures.dns_mock:SRV { name = "my.srv.test.com", target = "a.my.srv.test.com", port = 80, -- port should fail to connect } fixtures.dns_mock:A { name = "a.my.srv.test.com", address = "127.0.0.1", } fixtures.dns_mock:A { name = "multiple-ips.test", address = "127.0.0.1", } fixtures.dns_mock:A { name = "multiple-ips.test", address = "127.0.0.2", } fixtures.dns_mock:SRV { name = "srv-changes-port.test", target = "a-changes-port.test", port = 90, -- port should fail to connect } fixtures.dns_mock:A { name = "a-changes-port.test", address = "127.0.0.3", } fixtures.dns_mock:A { name = "another.multiple-ips.test", address = "127.0.0.1", } fixtures.dns_mock:A { name = "another.multiple-ips.test", address = "127.0.0.2", } assert(helpers.start_kong({ database = strategy, nginx_conf = "spec/fixtures/custom_nginx.template", db_update_frequency = 0.1, worker_consistency = consistency, worker_state_update_frequency = bu.CONSISTENCY_FREQ, }, nil, nil, fixtures)) end) lazy_teardown(function() helpers.stop_kong() end) it("over multiple targets", function() bu.begin_testcase_setup(strategy, bp) local upstream_name, upstream_id = bu.add_upstream(bp) local port1 = bu.add_target(bp, upstream_id, "127.0.0.1") local port2 = bu.add_target(bp, upstream_id, "127.0.0.1") local api_host = bu.add_api(bp, upstream_name) bu.end_testcase_setup(strategy, bp, consistency) local requests = bu.SLOTS * 2 -- go round the balancer twice -- setup target servers local server1 = https_server.new(port1, "127.0.0.1") local server2 = https_server.new(port2, "127.0.0.1") server1:start() server2:start() -- Go hit them with our test requests local oks = bu.client_requests(requests, api_host) -- collect server results; hitcount local count1 = server1:shutdown() local count2 = server2:shutdown() -- verify assert.are.equal(requests, oks) assert.are.equal(requests / 2, count1.ok) assert.are.equal(requests / 2, count2.ok) end) it("adding a target", function() bu.begin_testcase_setup(strategy, bp) local upstream_name, upstream_id = bu.add_upstream(bp) local port1 = bu.add_target(bp, upstream_id, "127.0.0.1", nil, { weight = 10 }) local port2 = bu.add_target(bp, upstream_id, "127.0.0.1", nil, { weight = 10 }) local api_host = bu.add_api(bp, upstream_name) bu.end_testcase_setup(strategy, bp, consistency) local requests = bu.SLOTS * 2 -- go round the balancer twice -- setup target servers local server1 = https_server.new(port1, "127.0.0.1") local server2 = https_server.new(port2, "127.0.0.1") server1:start() server2:start() -- Go hit them with our test requests local oks = bu.client_requests(requests, api_host) -- collect server results; hitcount local count1 = server1:shutdown() local count2 = server2:shutdown() assert.are.equal(requests, oks) -- verify assert.are.equal(requests / 2, count1.total) assert.are.equal(requests / 2, count2.total) -- add a new target 3 -- shift proportions from 50/50 to 40/40/20 bu.begin_testcase_setup_update(strategy, bp) local port3 = bu.add_target(bp, upstream_id, "127.0.0.1", nil, { weight = 5 }) bu.end_testcase_setup(strategy, bp, consistency) -- now go and hit the same balancer again ----------------------------------------- -- setup target servers local server3 server1 = https_server.new(port1, "127.0.0.1") server2 = https_server.new(port2, "127.0.0.1") server3 = https_server.new(port3, "127.0.0.1") server1:start() server2:start() server3:start() -- Go hit them with our test requests oks = bu.client_requests(requests, api_host) assert.are.equal(requests, oks) -- collect server results; hitcount count1 = server1:shutdown() count2 = server2:shutdown() local count3 = server3:shutdown() -- verify assert.are.equal(requests * 0.4, count1.total) assert.are.equal(requests * 0.4, count2.total) assert.are.equal(requests * 0.2, count3.total) end) it("removing a target #db", function() local requests = bu.SLOTS * 2 -- go round the balancer twice bu.begin_testcase_setup(strategy, bp) local upstream_name, upstream_id = bu.add_upstream(bp) local port1 = bu.add_target(bp, upstream_id, "127.0.0.1") local port2, target2 = bu.add_target(bp, upstream_id, "127.0.0.1") local api_host = bu.add_api(bp, upstream_name) bu.end_testcase_setup(strategy, bp, consistency) -- setup target servers local server1 = https_server.new(port1, "127.0.0.1") local server2 = https_server.new(port2, "127.0.0.1") server1:start() server2:start() -- Go hit them with our test requests local oks = bu.client_requests(requests, api_host) assert.are.equal(requests, oks) -- collect server results; hitcount local count1 = server1:shutdown() local count2 = server2:shutdown() -- verify assert.are.equal(requests / 2, count1.ok) assert.are.equal(requests / 2, count2.ok) -- modify weight for target 2, set to 0 bu.begin_testcase_setup_update(strategy, bp) bu.update_target(bp, upstream_id, "127.0.0.1", port2, { id = target2.id, weight = 0, -- disable this target }) bu.end_testcase_setup(strategy, bp, consistency) -- now go and hit the same balancer again ----------------------------------------- -- setup target servers server1 = https_server.new(port1, "127.0.0.1") server1:start() -- Go hit them with our test requests oks = bu.client_requests(requests, api_host) assert.are.equal(requests, oks) -- collect server results; hitcount local count1 = server1:shutdown() -- verify all requests hit server 1 assert.are.equal(requests, count1.total) end) it("modifying target weight #db", function() local requests = bu.SLOTS * 2 -- go round the balancer twice bu.begin_testcase_setup(strategy, bp) local upstream_name, upstream_id = bu.add_upstream(bp) local port1 = bu.add_target(bp, upstream_id, "127.0.0.1") local port2 = bu.add_target(bp, upstream_id, "127.0.0.1") local api_host = bu.add_api(bp, upstream_name) bu.end_testcase_setup(strategy, bp, consistency) -- setup target servers local server1 = https_server.new(port1, "127.0.0.1") local server2 = https_server.new(port2, "127.0.0.1") server1:start() server2:start() -- Go hit them with our test requests local oks = bu.client_requests(requests, api_host) assert.are.equal(requests, oks) -- collect server results; hitcount local count1 = server1:shutdown() local count2 = server2:shutdown() -- verify assert.are.equal(requests / 2, count1.total) assert.are.equal(requests / 2, count2.total) -- modify weight for target 2 bu.begin_testcase_setup_update(strategy, bp) bu.update_target(bp, upstream_id, "127.0.0.1", port2, { weight = 15, -- shift proportions from 50/50 to 40/60 }) bu.end_testcase_setup(strategy, bp, consistency) -- now go and hit the same balancer again ----------------------------------------- -- setup target servers server1 = https_server.new(port1, "127.0.0.1") server2 = https_server.new(port2, "127.0.0.1") server1:start() server2:start() -- Go hit them with our test requests oks = bu.client_requests(requests, api_host) assert.are.equal(requests, oks) -- collect server results; hitcount count1 = server1:shutdown() count2 = server2:shutdown() -- verify assert.are.equal(requests * 0.4, count1.total) assert.are.equal(requests * 0.6, count2.total) end) it("failure due to targets all 0 weight #db", function() local requests = bu.SLOTS * 2 -- go round the balancer twice bu.begin_testcase_setup(strategy, bp) local upstream_name, upstream_id = bu.add_upstream(bp) local port1 = bu.add_target(bp, upstream_id, "127.0.0.1") local port2 = bu.add_target(bp, upstream_id, "127.0.0.1") local api_host = bu.add_api(bp, upstream_name) bu.end_testcase_setup(strategy, bp, consistency) -- setup target servers local server1 = https_server.new(port1, "127.0.0.1") local server2 = https_server.new(port2, "127.0.0.1") server1:start() server2:start() -- Go hit them with our test requests local oks = bu.client_requests(requests, api_host) -- collect server results; hitcount local count1 = server1:shutdown() local count2 = server2:shutdown() -- verify assert.are.equal(requests, oks) assert.are.equal(requests / 2, count1.total) assert.are.equal(requests / 2, count2.total) -- modify weight for both targets, set to 0 bu.begin_testcase_setup_update(strategy, bp) bu.update_target(bp, upstream_id, "127.0.0.1", port1, { weight = 0 }) bu.update_target(bp, upstream_id, "127.0.0.1", port2, { weight = 0 }) bu.end_testcase_setup(strategy, bp, consistency) -- now go and hit the same balancer again ----------------------------------------- helpers.wait_until(function() local _, _, status = bu.client_requests(1, api_host) return pcall(function() assert.same(503, status) end) end, 10) end) it("failure due to targets all 0 weight #off", function() bu.begin_testcase_setup(strategy, bp) local upstream_name, upstream_id = bu.add_upstream(bp) local port1 = bu.add_target(bp, upstream_id, "127.0.0.1", nil, { weight = 0 }) local port2 = bu.add_target(bp, upstream_id, "127.0.0.1", nil, { weight = 0 }) local api_host = bu.add_api(bp, upstream_name) bu.end_testcase_setup(strategy, bp, consistency) -- setup target servers local server1 = https_server.new(port1) local server2 = https_server.new(port2) server1:start() server2:start() local _, _, status = bu.client_requests(1, api_host) server1:shutdown() server2:shutdown() assert.same(503, status) end) end) describe("Balancing with no targets #" .. consistency, function() local bp lazy_setup(function() bp = bu.get_db_utils_for_dc_and_admin_api(strategy, { "routes", "services", "plugins", "upstreams", "targets", }) assert(helpers.start_kong({ database = strategy, nginx_conf = "spec/fixtures/custom_nginx.template", db_update_frequency = 0.1, worker_consistency = consistency, worker_state_update_frequency = bu.CONSISTENCY_FREQ, })) end) lazy_teardown(function() helpers.stop_kong() end) it("failure due to no targets", function() bu.begin_testcase_setup(strategy, bp) local upstream_name = bu.add_upstream(bp) local api_host = bu.add_api(bp, upstream_name) bu.end_testcase_setup(strategy, bp, consistency) -- Go hit it with a request helpers.wait_until(function() local _, _, status = bu.client_requests(1, api_host) return pcall(function() assert.same(503, status) end) end, 10) end) for mode, localhost in pairs(bu.localhosts) do it("removing and adding the same target #db #" .. mode, function() bu.begin_testcase_setup(strategy, bp) local upstream_name, upstream_id = bu.add_upstream(bp) local port = bu.add_target(bp, upstream_id, localhost, nil, { weight = 100 }) local api_host = bu.add_api(bp, upstream_name) bu.end_testcase_setup(strategy, bp, consistency) local requests = 20 local server = https_server.new(port, localhost) server:start() local oks = bu.client_requests(requests, api_host) local count = server:shutdown() assert.equal(requests, oks) assert.equal(requests, count.total) -- remove target bu.begin_testcase_setup_update(strategy, bp) bu.update_target(bp, upstream_id, localhost, port, { weight = 0, }) bu.end_testcase_setup(strategy, bp, consistency) server = https_server.new(port, localhost) server:start() oks = bu.client_requests(requests, api_host) count = server:shutdown() assert.equal(0, oks) assert.equal(0, count.total) -- add the target back with same weight as initial weight bu.begin_testcase_setup_update(strategy, bp) bu.update_target(bp, upstream_id, localhost, port, { weight = 100, }) bu.end_testcase_setup(strategy, bp, consistency) server = https_server.new(port, localhost) server:start() oks = bu.client_requests(requests, api_host) count = server:shutdown() assert.equal(requests, oks) assert.equal(requests, count.total) end) end end) end end