diff --git a/lib/synapse/haproxy.rb b/lib/synapse/haproxy.rb index 03cc84e0..51dc56a2 100644 --- a/lib/synapse/haproxy.rb +++ b/lib/synapse/haproxy.rb @@ -631,7 +631,7 @@ def generate_backend_stanza(watcher, config) config.map {|c| "\t#{c}"}, watcher.backends.shuffle.map {|backend| backend_name = construct_name(backend) - "\tserver #{backend_name} #{backend['host']}:#{backend['port']} #{watcher.haproxy['server_options']}" } + "\tserver #{backend_name} #{backend['host']}:#{backend['port']} #{watcher.haproxy['server_options']}#{' backup' if backend['backup']}" } ] end diff --git a/lib/synapse/service_watcher/base.rb b/lib/synapse/service_watcher/base.rb index 63e19028..7a9b7296 100644 --- a/lib/synapse/service_watcher/base.rb +++ b/lib/synapse/service_watcher/base.rb @@ -14,6 +14,7 @@ def initialize(opts={}, synapse) @name = opts['name'] @discovery = opts['discovery'] + @leader_election = opts['leader_election'] || false # the haproxy config @haproxy = opts['haproxy'] diff --git a/lib/synapse/service_watcher/zookeeper.rb b/lib/synapse/service_watcher/zookeeper.rb index 70994b0a..c792b2d6 100644 --- a/lib/synapse/service_watcher/zookeeper.rb +++ b/lib/synapse/service_watcher/zookeeper.rb @@ -53,7 +53,7 @@ def discover server_port = @server_port_override ? @server_port_override : port log.debug "synapse: discovered backend #{name} at #{host}:#{server_port} for service #{@name}" - new_backends << { 'name' => name, 'host' => host, 'port' => server_port} + new_backends << { 'name' => name, 'host' => host, 'port' => server_port, 'backup' => @leader_election } end end rescue ZK::Exceptions::NoNode @@ -72,6 +72,26 @@ def discover else log.info "synapse: discovered #{new_backends.length} backends for service #{@name}" @backends = new_backends + + if @leader_election + log.info "synapse: electing a leader from the discovered backends" + leader_election + end + end + end + + #sort the list of servers based on their sequence, and the server with lowest sequence will be the leader + def leader_election + begin + #Integer parsing added to check that a sequence has been appended to the node key + @backends = @backends.sort { |x, y| Integer(x['name'].gsub(/^.*-(0)*/, '')) <=> Integer(y['name'].gsub(/^.*-(0)*/, '')) } + @backends[0]['backup'] = false + log.debug "synapse: electing leader, updated backends #{@backends}" + rescue ArgumentError, NoMethodError + raise "'sequential' should be enabled in nerve configuration for service " \ + "#{@name} to perform leader election, please enable 'sequential' in nerve" \ + " configuration for all servers of #{@name} service, or disable " \ + "'leader_election' in synapse configuration" end end