Skip to content

Commit 06c8433

Browse files
committed
Create an option to stop ignoring weights. By default weights will still
be ignored. This commit is based on: airbnb#131 but does the following things differently: 1. By default weights are ignored. This is to maintain current behavior for safety. 2. HAProxy will reconfigure if weights changes.
1 parent a24aaca commit 06c8433

6 files changed

Lines changed: 51 additions & 3 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ This section is its own hash, which should contain the following keys:
261261
* `listen`: these lines will be parsed and placed in the correct `frontend`/`backend` section as applicable; you can put lines which are the same for the frontend and backend here.
262262
* `backend_order`: optional: how backends should be ordered in the `backend` stanza. (default is shuffling). Setting to `asc` means sorting backends in ascending alphabetical order before generating stanza. `desc` means descending alphabetical order. `no_shuffle` means no shuffling or sorting.
263263
* `shared_frontend`: optional: haproxy configuration directives for a shared http frontend (see below)
264+
* `ignore_weights`: optional: stops haproxy backend 'weight' options being generated, even if the Nerve registrations contain this information. This will cause all backend servers to be treated equally by haproxy. This defaults to true so weights will *NOT* be used by default.
264265

265266
<a name="haproxy"/>
266267
### Configuring HAProxy ###

lib/synapse/haproxy.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,7 @@ def initialize(opts)
535535
@opts['do_writes'] = true unless @opts.key?('do_writes')
536536
@opts['do_socket'] = true unless @opts.key?('do_socket')
537537
@opts['do_reloads'] = true unless @opts.key?('do_reloads')
538+
@opts['ignore_weights'] = true unless @opts.key?('ignore_weights')
538539

539540
# how to restart haproxy
540541
@restart_interval = @opts.fetch('restart_interval', 2).to_i
@@ -741,6 +742,10 @@ def generate_backend_stanza(watcher, config)
741742
backend = backends[backend_name]
742743
b = "\tserver #{backend_name} #{backend['host']}:#{backend['port']}"
743744
b = "#{b} cookie #{backend_name}" unless config.include?('mode tcp')
745+
if !@opts['ignore_weights'] && backend.has_key?('weight')
746+
weight = backend['weight'].to_i
747+
b = "#{b} weight #{weight}"
748+
end
744749
b = "#{b} #{watcher.haproxy['server_options']}" if watcher.haproxy['server_options']
745750
b = "#{b} #{backend['haproxy_server_options']}" if backend['haproxy_server_options']
746751
b = "#{b} disabled" unless backend['enabled']

lib/synapse/service_watcher/base.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ def set_backends(new_backends)
117117
# Aggregate and deduplicate all potential backend service instances.
118118
new_backends = (new_backends + @default_servers) if @keep_default_servers
119119
new_backends = new_backends.uniq {|b|
120-
[b['host'], b['port'], b.fetch('name', '')]
120+
[b['host'], b['port'], b.fetch('name', ''), b.fetch('weight', 1)]
121121
}
122122

123123
if new_backends.to_set == @backends.to_set

spec/lib/synapse/haproxy_spec.rb

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,18 @@ class MockWatcher; end;
55
describe Synapse::Haproxy do
66
subject { Synapse::Haproxy.new(config['haproxy']) }
77

8-
let(:mockwatcher) do
8+
def createmockwatcher(backends)
99
mockWatcher = double(Synapse::ServiceWatcher)
1010
allow(mockWatcher).to receive(:name).and_return('example_service')
11-
backends = [{ 'host' => 'somehost', 'port' => 5555}]
1211
allow(mockWatcher).to receive(:backends).and_return(backends)
1312
allow(mockWatcher).to receive(:haproxy).and_return({'server_options' => "check inter 2000 rise 3 fall 2"})
1413
mockWatcher
1514
end
1615

16+
let(:mockwatcher) do
17+
createmockwatcher [{ 'host' => 'somehost', 'port' => '5555'}]
18+
end
19+
1720
let(:mockwatcher_with_server_options) do
1821
mockWatcher = double(Synapse::ServiceWatcher)
1922
allow(mockWatcher).to receive(:name).and_return('example_service')
@@ -96,4 +99,24 @@ class MockWatcher; end;
9699
expect(subject.generate_frontend_stanza(mockwatcher_frontend_with_bind_address, mockConfig)).to eql(["\nfrontend example_service", [], "\tbind 127.0.0.3:2200", "\tdefault_backend example_service"])
97100
end
98101

102+
it 'generates backend stanza with weight' do
103+
mockConfig = []
104+
expect(subject.generate_backend_stanza(createmockwatcher([{ 'weight' => 1, 'host' => 'somehost', 'port' => '5555'}]), mockConfig)).to eql(["\nbackend example_service", [], ["\tserver somehost:5555 somehost:5555 cookie somehost:5555 weight 1 check inter 2000 rise 3 fall 2"]])
105+
end
106+
107+
it 'generates backend stanza with bad weight = 0' do
108+
mockConfig = []
109+
expect(subject.generate_backend_stanza(createmockwatcher([{ 'weight' => 'hi', 'host' => 'somehost', 'port' => '5555'}]), mockConfig)).to eql(["\nbackend example_service", [], ["\tserver somehost:5555 somehost:5555 cookie somehost:5555 weight 0 check inter 2000 rise 3 fall 2"]])
110+
end
111+
112+
it 'generates backend stanza with nil weight = 0' do
113+
mockConfig = []
114+
expect(subject.generate_backend_stanza(createmockwatcher([{ 'weight' => nil, 'host' => 'somehost', 'port' => '5555'}]), mockConfig)).to eql(["\nbackend example_service", [], ["\tserver somehost:5555 somehost:5555 cookie somehost:5555 weight 0 check inter 2000 rise 3 fall 2"]])
115+
end
116+
117+
it 'generates backend stanza without weight' do
118+
mockConfig = []
119+
expect(subject.generate_backend_stanza(createmockwatcher([{ 'host' => 'somehost', 'port' => '5555'}]), mockConfig)).to eql(["\nbackend example_service", [], ["\tserver somehost:5555 somehost:5555 cookie somehost:5555 check inter 2000 rise 3 fall 2"]])
120+
end
121+
99122
end

spec/lib/synapse/service_watcher_base_spec.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,5 +135,23 @@ def remove_arg(name)
135135
expect(subject.backends).to eq(matching_labeled_backends)
136136
end
137137
end
138+
139+
context 'with ignore_weights set to false' do
140+
let(:backends) { [
141+
{ 'name' => 'server1', 'host' => 'server1', 'port' => 1111, 'weight' => 11 },
142+
{ 'name' => 'server2', 'host' => 'server2', 'port' => 2222, 'weight' => 22 },
143+
] }
144+
let(:non_matching_weight_backends) { [
145+
{ 'name' => 'server1', 'host' => 'server1', 'port' => 1111, 'weight' => 33 },
146+
{ 'name' => 'server2', 'host' => 'server2', 'port' => 2222, 'weight' => 22 },
147+
] }
148+
it 'updates backends only when weights change' do
149+
expect(subject).to receive(:'reconfigure!').exactly(:twice)
150+
expect(subject.send(:set_backends, backends)).to equal(true)
151+
expect(subject.backends).to eq(backends)
152+
expect(subject.send(:set_backends, non_matching_weight_backends)).to equal(true)
153+
expect(subject.backends).to eq(non_matching_weight_backends)
154+
end
155+
end
138156
end
139157
end

spec/support/minimum.conf.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ haproxy:
2020
config_file_path: "/etc/haproxy/haproxy.cfg"
2121
do_writes: false
2222
do_reloads: false
23+
ignore_weights: false
2324
global:
2425
- global_test_option
2526

0 commit comments

Comments
 (0)