Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow registrations to be manifested on the file system and add 'use_previous_backends' option #115

Closed
wants to merge 28 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d5d061a
Add 'use_previous_backends' option.
jnb Sep 27, 2014
b855bff
Merge pull request #1 from jnb/use_previous_backends
jolynch Feb 27, 2015
35f1f8f
Allow registrations to be manifested on the file system
jolynch Feb 27, 2015
c3d862c
Merge pull request #2 from jolynch/add_flat_file_output
jolynch Mar 5, 2015
01826a0
Merge remote-tracking branch 'upstream/master'
jolynch Mar 5, 2015
1fdd57e
Explicitly deduplicate registrations
jolynch Mar 16, 2015
6eb5850
Allow the option allredisp option to haproxy.
jolynch Mar 16, 2015
e5411b0
Merge pull request #5 from jolynch/allow_allredisp_option
jnb Mar 16, 2015
c6c37fa
Merge pull request #4 from jolynch/dedup_ignore_ids
jolynch Mar 17, 2015
136d1fe
Add rate limiter.
jnb May 20, 2015
e057dbf
Merge pull request #8 from Yelp/rate_limiter
jnb May 26, 2015
e6d03c2
Revert "Add rate limiter."
jnb May 27, 2015
a3e84d2
Increase HAProxy restart interval.
jnb May 27, 2015
d0c1161
Merge pull request #9 from Yelp/restart_interval
jolynch May 27, 2015
5928c2b
ZooKeeper connection pooling.
jnb May 28, 2015
e96b2a9
Merge pull request #11 from Yelp/zk_pool
jolynch May 28, 2015
4eab7e0
Rate limit restarts but not stats socket updates
jolynch May 28, 2015
7de6a59
Merge pull request #10 from jolynch/jlynch_separate_stats_from_restart
jnb May 28, 2015
030ccfe
Add state file.
jnb May 29, 2015
235fa85
Merge pull request #12 from Yelp/state_file
jnb May 29, 2015
36f2a94
Fix bug in caching logic.
jnb Jun 17, 2015
e90cf85
Merge pull request #13 from Yelp/fix_cache
jolynch Jun 17, 2015
86d7f9d
Add support for the weight key added in nerve
bobtfish Jun 29, 2015
e49afdf
Merge pull request #14 from bobtfish/add_weight
jolynch Jul 6, 2015
a6a48e3
Try out :per_callback threads and get more debug information
jolynch Jul 13, 2015
29f3197
Merge pull request #15 from jolynch/work_on_watcher_slowness
jnb Jul 14, 2015
420440f
Turns out it's important to handle session disconnects correctly
Jul 15, 2015
429a20a
Merge pull request #16 from jolynch/fix_zk_session_bug
jnb Jul 15, 2015
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ GEM
slyphon-zookeeper_jar (3.3.5-java)
spoon (0.0.4)
ffi
zk (1.9.4)
zk (1.9.5)
logging (~> 1.8.2)
zookeeper (~> 1.4.0)
zookeeper (1.4.8)
zookeeper (1.4.8-java)
zookeeper (1.4.10)
zookeeper (1.4.10-java)
slyphon-log4j (= 1.2.15)
slyphon-zookeeper_jar (= 3.3.5)

Expand Down
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,10 @@ If you do not list any default servers, no proxy will be created. The
`default_servers` will also be used in addition to discovered servers if the
`keep_default_servers` option is set.

If you do not list any `default_servers`, and all backends for a service
disappear then the previous known backends will be used. Disable this behavior
by unsetting `use_previous_backends`.

#### The `haproxy` Section ####

This section is its own hash, which should contain the following keys:
Expand All @@ -218,6 +222,7 @@ The `haproxy` section of the config file has the following options:
* `config_file_path`: where Synapse will write the HAProxy config file
* `do_writes`: whether or not the config file will be written (default to `true`)
* `do_reloads`: whether or not Synapse will reload HAProxy (default to `true`)
* `do_socket`: whether or not Synapse will use the HAProxy socket commands to prevent reloads (default to `true`)
* `global`: options listed here will be written into the `global` section of the HAProxy config
* `defaults`: options listed here will be written into the `defaults` section of the HAProxy config
* `extra_sections`: additional, manually-configured `frontend`, `backend`, or `listen` stanzas
Expand Down Expand Up @@ -335,5 +340,5 @@ end
3. Implement the `start` and `validate_discovery_opts` methods
4. Implement whatever additional methods your discovery requires

When your watcher detects a list of new backends, they should be written to `@backends`.
You should then call `@synapse.configure` to force synapse to update the HAProxy config.
When your watcher detects a list of new backends, you should call `set_backends` to
store the new backends and update the HAProxy config.
26 changes: 20 additions & 6 deletions lib/synapse.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
require "synapse/version"
require "synapse/service_watcher/base"
require "synapse/haproxy"
require "synapse/file_output"
require "synapse/service_watcher"
require "synapse/log"

Expand All @@ -17,9 +18,17 @@ def initialize(opts={})
raise "specify a list of services to connect in the config" unless opts.has_key?('services')
@service_watchers = create_service_watchers(opts['services'])

# create the haproxy object
# create objects that need to be notified of service changes
@config_generators = []
# create the haproxy config generator, this is mandatory
raise "haproxy config section is missing" unless opts.has_key?('haproxy')
@haproxy = Haproxy.new(opts['haproxy'])
@config_generators << Haproxy.new(opts['haproxy'])

# possibly create a file manifestation for services that do not
# want to communicate via haproxy, e.g. cassandra
if opts.has_key?('file_output')
@config_generators << FileOutput.new(opts['file_output'])
end

# configuration is initially enabled to configure on first loop
@config_updated = true
Expand Down Expand Up @@ -47,10 +56,15 @@ def run

if @config_updated
@config_updated = false
log.info "synapse: regenerating haproxy config"
@haproxy.update_config(@service_watchers)
else
sleep 1
@config_generators.each do |config_generator|
log.info "synapse: configuring #{config_generator.name}"
config_generator.update_config(@service_watchers)
end
end

sleep 1
@config_generators.each do |config_generator|
config_generator.tick(@service_watchers)
end

loops += 1
Expand Down
56 changes: 56 additions & 0 deletions lib/synapse/file_output.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
require 'synapse/log'
require 'fileutils'
require 'tempfile'

module Synapse
class FileOutput
include Logging
attr_reader :opts, :name

def initialize(opts)
super()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure what this is calling out to, this class does not inherit from anything

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed it does not, I'll fix that up


unless opts.has_key?("output_directory")
raise ArgumentError, "flat file generation requires an output_directory key"
end

begin
FileUtils.mkdir_p(opts['output_directory'])
rescue SystemCallError => err
raise ArgumentError, "provided output directory #{opts['output_directory']} is not present or creatable"
end

@opts = opts
@name = 'file_output'
end

def tick(watchers)
end

def update_config(watchers)
watchers.each do |watcher|
write_backends_to_file(watcher.name, watcher.backends)
end
end

def write_backends_to_file(service_name, new_backends)
data_path = File.join(@opts['output_directory'], "#{service_name}.json")
begin
old_backends = JSON.load(File.read(data_path))
rescue Errno::ENOENT
old_backends = nil
end

if old_backends == new_backends
return false
else
# Atomically write new sevice configuration file
temp_path = File.join(@opts['output_directory'],
".#{service_name}.json.tmp")
File.open(temp_path, 'w', 0644) {|f| f.write(new_backends.to_json)}
FileUtils.mv(temp_path, data_path)
return true
end
end
end
end
Loading