synapse 0.2.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +3 -0
- data/.mailmap +3 -0
- data/LICENSE.txt +2 -2
- data/Makefile +6 -0
- data/README.md +42 -13
- data/bin/synapse +29 -21
- data/config/hostheader_test.json +71 -0
- data/config/svcdir_test.json +46 -0
- data/config/synapse.conf.json +26 -32
- data/config/synapse_services/service1.json +24 -0
- data/config/synapse_services/service2.json +24 -0
- data/lib/synapse.rb +39 -24
- data/lib/synapse/base.rb +1 -1
- data/lib/synapse/haproxy.rb +579 -22
- data/lib/synapse/log.rb +24 -0
- data/lib/synapse/service_watcher.rb +10 -6
- data/lib/synapse/service_watcher/base.rb +33 -11
- data/lib/synapse/service_watcher/dns.rb +28 -20
- data/lib/synapse/service_watcher/docker.rb +108 -0
- data/lib/synapse/service_watcher/ec2tag.rb +1 -1
- data/lib/synapse/service_watcher/zookeeper.rb +25 -28
- data/lib/synapse/version.rb +1 -1
- data/spec/spec_helper.rb +2 -2
- data/synapse.gemspec +2 -3
- metadata +15 -25
- data/Vagrantfile +0 -112
- data/chef/converge +0 -4
- data/chef/cookbooks/lxc/recipes/default.rb +0 -2
- data/chef/cookbooks/synapse/attributes/default.rb +0 -1
- data/chef/cookbooks/synapse/recipes/default.rb +0 -6
- data/chef/run.json +0 -8
- data/chef/run.rb +0 -2
- data/client/.RData +0 -0
- data/client/.Rhistory +0 -294
- data/client/bench_rewrite_config.dat +0 -2013
- data/client/benchmark-client.iml +0 -20
- data/client/pom.xml +0 -45
- data/client/src/main/java/ClientArsch.java +0 -68
- data/client/src/main/java/META-INF/MANIFEST.MF +0 -3
- data/haproxy.pid +0 -1
- data/lib/gen-rb/endpoint_types.rb +0 -65
- data/lib/gen-rb/thrift.rb +0 -65
- data/test.sh +0 -3
data/.gitignore
CHANGED
data/.mailmap
ADDED
data/LICENSE.txt
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c)
|
1
|
+
Copyright (c) 2013 Airbnb, Inc.
|
2
2
|
|
3
3
|
MIT License
|
4
4
|
|
@@ -19,4 +19,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
19
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
20
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
21
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Makefile
ADDED
data/README.md
CHANGED
@@ -54,10 +54,7 @@ Add a hash under `services` that looks like this:
|
|
54
54
|
|
55
55
|
```json
|
56
56
|
{"services":
|
57
|
-
{
|
58
|
-
"name": "proddb",
|
59
|
-
"local_port": 3219,
|
60
|
-
"server_options": "check inter 2000 rise 3 fall 2",
|
57
|
+
"proddb": {
|
61
58
|
"default_servers": [
|
62
59
|
{
|
63
60
|
"name": "default-db",
|
@@ -70,8 +67,16 @@ Add a hash under `services` that looks like this:
|
|
70
67
|
"tag": "proddb",
|
71
68
|
"value": "true"
|
72
69
|
},
|
73
|
-
"
|
74
|
-
|
70
|
+
"haproxy": {
|
71
|
+
"port": 3219,
|
72
|
+
"server_options": "check inter 2000 rise 3 fall 2",
|
73
|
+
"frontend": [
|
74
|
+
"mode tcp",
|
75
|
+
],
|
76
|
+
"backend": [
|
77
|
+
"mode tcp",
|
78
|
+
],
|
79
|
+
},
|
75
80
|
},
|
76
81
|
...
|
77
82
|
```
|
@@ -114,15 +119,13 @@ The second is the `haproxy` section, which specifies how to configure and intera
|
|
114
119
|
|
115
120
|
### Configuring a Service ###
|
116
121
|
|
117
|
-
|
122
|
+
The services are a hash, where the keys are the `name` of the service to be configured.
|
123
|
+
The name is just a human-readable string; it will be used in logs and notifications.
|
124
|
+
Each value in the services hash is also a hash, and should contain the following keys:
|
118
125
|
|
119
|
-
* `name`: a human-readable name for the service, this is used in logs and notifications
|
120
|
-
* `local_port`: the port (on localhost) where HAProxy will listen for connections to the serivce
|
121
126
|
* `discovery`: how synapse will discover hosts providing this service (see below)
|
122
127
|
* `default_servers`: the list of default servers providing this service; synapse uses these if none others can be discovered
|
123
|
-
* `
|
124
|
-
* `server_options`: the haproxy options for each `server` line of the service in HAProxy config; may be left out
|
125
|
-
* `listen`: additional lines passed to the HAProxy config in the `listen` stanza of this service
|
128
|
+
* `haproxy`: how will the haproxy section for this service be configured
|
126
129
|
|
127
130
|
#### Service Discovery ####
|
128
131
|
|
@@ -149,6 +152,17 @@ The watcher assumes that each node under `path` represents a service server.
|
|
149
152
|
Synapse attempts to decode the data in each of these nodes using JSON and also using Thrift under the standard Twitter service encoding.
|
150
153
|
We assume that the data contains a hostname and a port for service servers.
|
151
154
|
|
155
|
+
##### Docker #####
|
156
|
+
|
157
|
+
This watcher retrieves a list of [docker](http://www.docker.io/) containers via docker's [HTTP API](http://docs.docker.io/en/latest/api/docker_remote_api/).
|
158
|
+
It takes the following options:
|
159
|
+
|
160
|
+
* `method`: docker
|
161
|
+
* `servers`: a list of servers running docker as a daemon. Format is `{"name":"...", "host": "..."[, port: 4243]}`
|
162
|
+
* `image_name`: find containers running this image
|
163
|
+
* `container_port`: find containers forwarding this port
|
164
|
+
* `check_interval`: how often to poll the docker API on each server. Default is 15s.
|
165
|
+
|
152
166
|
#### Listing Default Servers ####
|
153
167
|
|
154
168
|
You may list a number of default servers providing a service.
|
@@ -162,6 +176,17 @@ The `default_servers` list is used only when service discovery returns no server
|
|
162
176
|
In that case, the service proxy will be created with the servers listed here.
|
163
177
|
If you do not list any default servers, no proxy will be created.
|
164
178
|
|
179
|
+
#### The `haproxy` Section ####
|
180
|
+
|
181
|
+
This section is it's own hash, which should contain the following keys:
|
182
|
+
|
183
|
+
* `port`: the port (on localhost) where HAProxy will listen for connections to the service.
|
184
|
+
* `server_port_override`: the port that discovered servers listen on; you should specify this if your discovery mechanism only discovers names or addresses (like the DNS watcher). If the discovery method discovers a port along with hostnames (like the zookeeper watcher) this option may be left out, but will be used in preference if given.
|
185
|
+
* `server_options`: the haproxy options for each `server` line of the service in HAProxy config; it may be left out.
|
186
|
+
* `frontend`: additional lines passed to the HAProxy config in the `frontend` stanza of this service
|
187
|
+
* `backend`: additional lines passed to the HAProxy config in the `backend` stanza of this service
|
188
|
+
* `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.
|
189
|
+
|
165
190
|
### Configuring HAProxy ###
|
166
191
|
|
167
192
|
The `haproxy` section of the config file has the following options:
|
@@ -172,6 +197,9 @@ The `haproxy` section of the config file has the following options:
|
|
172
197
|
* `do_reloads`: whether or not Synapse will reload HAProxy (default to `true`)
|
173
198
|
* `global`: options listed here will be written into the `global` section of the HAProxy config
|
174
199
|
* `defaults`: options listed here will be written into the `defaults` section of the HAProxy config
|
200
|
+
* `bind_address`: force HAProxy to listen on this address (default is localhost)
|
201
|
+
|
202
|
+
Note that a non-default `bind_address` can be dangerous: it is up to you to ensure that HAProxy will not attempt to bind an address:port combination that is not already in use by one of your services.
|
175
203
|
|
176
204
|
## Contributing
|
177
205
|
|
@@ -188,7 +216,8 @@ If you'd like to create a new service watcher:
|
|
188
216
|
1. Create a file for your watcher in `service_watcher` dir
|
189
217
|
2. Use the following template:
|
190
218
|
```ruby
|
191
|
-
|
219
|
+
require 'synapse/service_watcher/base'
|
220
|
+
|
192
221
|
module Synapse
|
193
222
|
class NewWatcher < BaseWatcher
|
194
223
|
def start
|
data/bin/synapse
CHANGED
@@ -3,18 +3,18 @@
|
|
3
3
|
require 'json'
|
4
4
|
require 'optparse'
|
5
5
|
|
6
|
-
|
6
|
+
require 'synapse'
|
7
7
|
|
8
8
|
options={}
|
9
9
|
|
10
10
|
# set command line options
|
11
11
|
optparse = OptionParser.new do |opts|
|
12
|
-
opts.banner
|
12
|
+
opts.banner =<<-EOB
|
13
13
|
Welcome to synapse
|
14
14
|
|
15
15
|
Usage: synapse --config /path/to/synapse/config
|
16
|
-
EOB
|
17
|
-
|
16
|
+
EOB
|
17
|
+
|
18
18
|
options[:config] = ENV['SYNAPSE_CONFIG']
|
19
19
|
opts.on('-c config','--config config', String, 'path to synapse config') do |key,value|
|
20
20
|
options[:config] = key
|
@@ -24,31 +24,39 @@ EOB
|
|
24
24
|
puts opts
|
25
25
|
exit
|
26
26
|
end
|
27
|
-
|
28
27
|
end
|
29
28
|
|
30
|
-
|
31
29
|
# parse command line arguments
|
32
30
|
optparse.parse!
|
33
31
|
|
34
|
-
|
35
|
-
# parse synapse config file
|
36
|
-
begin
|
37
|
-
|
38
|
-
rescue Errno::ENOENT => e
|
39
|
-
|
40
|
-
rescue Errno::EACCES => e
|
41
|
-
|
42
|
-
rescue JSON::ParserError => e
|
43
|
-
|
32
|
+
def parseconfig(filename)
|
33
|
+
# parse synapse config file
|
34
|
+
begin
|
35
|
+
c = JSON::parse(File.read(filename))
|
36
|
+
rescue Errno::ENOENT => e
|
37
|
+
raise ArgumentError, "config file does not exist:\n#{e.inspect}"
|
38
|
+
rescue Errno::EACCES => e
|
39
|
+
raise ArgumentError, "could not open config file:\n#{e.inspect}"
|
40
|
+
rescue JSON::ParserError => e
|
41
|
+
raise "config file #{filename} is not json:\n#{e.inspect}"
|
42
|
+
end
|
43
|
+
return c
|
44
44
|
end
|
45
45
|
|
46
|
+
config = parseconfig(options[:config])
|
47
|
+
config['services'] ||= {}
|
46
48
|
|
47
|
-
|
48
|
-
|
49
|
+
if config.has_key?('service_conf_dir')
|
50
|
+
cdir = File.expand_path(config['service_conf_dir'])
|
51
|
+
if ! Dir.exists?(cdir)
|
52
|
+
raise "service conf dir does not exist:#{cdir}"
|
53
|
+
end
|
54
|
+
cfiles = Dir.glob(File.join(cdir, '*.json'))
|
55
|
+
cfiles.each { |x| config['services'][File.basename(x[/(.*)\.json$/, 1])] = parseconfig(x) }
|
56
|
+
end
|
49
57
|
|
50
|
-
#
|
58
|
+
# run synapse
|
59
|
+
s = Synapse::Synapse.new(config)
|
51
60
|
s.run
|
52
61
|
|
53
|
-
|
54
|
-
puts "exiting synapse"
|
62
|
+
puts "synapse has exited"
|
@@ -0,0 +1,71 @@
|
|
1
|
+
{
|
2
|
+
"services": {
|
3
|
+
"service1": {
|
4
|
+
"default_servers": [
|
5
|
+
{ "name": "default1", "host": "localhost", "port": 8080 }
|
6
|
+
],
|
7
|
+
"discovery": {
|
8
|
+
"method": "dns",
|
9
|
+
"nameserver": "127.0.0.1",
|
10
|
+
"servers": [
|
11
|
+
"0.www.example.com",
|
12
|
+
"1.www.example.com"
|
13
|
+
]
|
14
|
+
},
|
15
|
+
"haproxy": {
|
16
|
+
"server_options": "check inter 2s rise 3 fall 2",
|
17
|
+
"listen": [
|
18
|
+
"mode http",
|
19
|
+
"option httplog"
|
20
|
+
],
|
21
|
+
"backend": [
|
22
|
+
"mode http",
|
23
|
+
"option httpchk GET /health HTTP/1.0"
|
24
|
+
]
|
25
|
+
}
|
26
|
+
}
|
27
|
+
},
|
28
|
+
"haproxy": {
|
29
|
+
"reload_command": "sudo service haproxy reload",
|
30
|
+
"config_file_path": "/etc/haproxy/haproxy.cfg",
|
31
|
+
"socket_file_path": "/var/haproxy/stats.sock",
|
32
|
+
"do_writes": true,
|
33
|
+
"do_reloads": true,
|
34
|
+
"do_socket": true,
|
35
|
+
"global": [
|
36
|
+
"daemon",
|
37
|
+
"user haproxy",
|
38
|
+
"group haproxy",
|
39
|
+
"maxconn 4096",
|
40
|
+
"log 127.0.0.1 local0",
|
41
|
+
"log 127.0.0.1 local1 notice",
|
42
|
+
"stats socket /var/haproxy/stats.sock mode 666 level admin"
|
43
|
+
],
|
44
|
+
"defaults": [
|
45
|
+
"log global",
|
46
|
+
"option dontlognull",
|
47
|
+
"maxconn 2000",
|
48
|
+
"retries 3",
|
49
|
+
"timeout connect 5s",
|
50
|
+
"timeout client 1m",
|
51
|
+
"timeout server 1m",
|
52
|
+
"option redispatch",
|
53
|
+
"balance roundrobin"
|
54
|
+
],
|
55
|
+
"extra_sections": {
|
56
|
+
"listen stats :3212": [
|
57
|
+
"mode http",
|
58
|
+
"stats enable",
|
59
|
+
"stats uri /",
|
60
|
+
"stats refresh 5s"
|
61
|
+
],
|
62
|
+
"frontend http-generic-in": [
|
63
|
+
"bind 127.0.0.1:80",
|
64
|
+
"acl is_service1 hdr_dom(host) -i service1.lb",
|
65
|
+
"acl is_cache hdr_dom(host) -i cache.lb",
|
66
|
+
"use_backend service1 if is_service1",
|
67
|
+
"use_backend cache if is_cache"
|
68
|
+
]
|
69
|
+
}
|
70
|
+
}
|
71
|
+
}
|
@@ -0,0 +1,46 @@
|
|
1
|
+
{
|
2
|
+
"service_conf_dir": "config/synapse_services",
|
3
|
+
"haproxy": {
|
4
|
+
"reload_command": "sudo service haproxy reload",
|
5
|
+
"config_file_path": "/etc/haproxy/haproxy.cfg",
|
6
|
+
"socket_file_path": "/var/haproxy/stats.sock",
|
7
|
+
"do_writes": true,
|
8
|
+
"do_reloads": true,
|
9
|
+
"do_socket": true,
|
10
|
+
"global": [
|
11
|
+
"daemon",
|
12
|
+
"user haproxy",
|
13
|
+
"group haproxy",
|
14
|
+
"maxconn 4096",
|
15
|
+
"log 127.0.0.1 local0",
|
16
|
+
"log 127.0.0.1 local1 notice",
|
17
|
+
"stats socket /var/haproxy/stats.sock mode 666 level admin"
|
18
|
+
],
|
19
|
+
"defaults": [
|
20
|
+
"log global",
|
21
|
+
"option dontlognull",
|
22
|
+
"maxconn 2000",
|
23
|
+
"retries 3",
|
24
|
+
"timeout connect 5s",
|
25
|
+
"timeout client 1m",
|
26
|
+
"timeout server 1m",
|
27
|
+
"option redispatch",
|
28
|
+
"balance roundrobin"
|
29
|
+
],
|
30
|
+
"extra_sections": {
|
31
|
+
"listen stats :3212": [
|
32
|
+
"mode http",
|
33
|
+
"stats enable",
|
34
|
+
"stats uri /",
|
35
|
+
"stats refresh 5s"
|
36
|
+
],
|
37
|
+
"frontend http-generic-in": [
|
38
|
+
"bind 127.0.0.1:80",
|
39
|
+
"acl is_service1 hdr_dom(host) -i service1.lb",
|
40
|
+
"acl is_cache hdr_dom(host) -i cache.lb",
|
41
|
+
"use_backend service1 if is_service1",
|
42
|
+
"use_backend cache if is_cache"
|
43
|
+
]
|
44
|
+
}
|
45
|
+
}
|
46
|
+
}
|
data/config/synapse.conf.json
CHANGED
@@ -1,9 +1,6 @@
|
|
1
1
|
{
|
2
|
-
"services":
|
3
|
-
{
|
4
|
-
"name": "service1",
|
5
|
-
"local_port": 3213,
|
6
|
-
"server_options": "check inter 2s rise 3 fall 2",
|
2
|
+
"services": {
|
3
|
+
"service1": {
|
7
4
|
"default_servers": [
|
8
5
|
{
|
9
6
|
"name": "default1",
|
@@ -13,22 +10,23 @@
|
|
13
10
|
],
|
14
11
|
"discovery": {
|
15
12
|
"method": "zookeeper",
|
16
|
-
"path": "/
|
13
|
+
"path": "/services/service1",
|
17
14
|
"hosts": [
|
18
|
-
"
|
19
|
-
"zk1.airbnb.com:2181"
|
15
|
+
"localhost:2181"
|
20
16
|
]
|
21
17
|
},
|
22
|
-
"
|
23
|
-
"
|
24
|
-
"
|
25
|
-
"
|
26
|
-
|
18
|
+
"haproxy": {
|
19
|
+
"port": 3213,
|
20
|
+
"server_options": "check inter 2s rise 3 fall 2",
|
21
|
+
"listen": [
|
22
|
+
"mode http",
|
23
|
+
"option httpchk /health",
|
24
|
+
"http-check expect string OK"
|
25
|
+
]
|
26
|
+
}
|
27
|
+
|
27
28
|
},
|
28
|
-
{
|
29
|
-
"name": "service2",
|
30
|
-
"local_port": 3214,
|
31
|
-
"server_options": "check inter 2s rise 3 fall 2",
|
29
|
+
"service2": {
|
32
30
|
"default_servers": [
|
33
31
|
{
|
34
32
|
"name": "default1",
|
@@ -38,18 +36,21 @@
|
|
38
36
|
],
|
39
37
|
"discovery": {
|
40
38
|
"method": "zookeeper",
|
41
|
-
"path": "/
|
39
|
+
"path": "/services/service2",
|
42
40
|
"hosts": [
|
43
|
-
"
|
44
|
-
"zk1.airbnb.com:2181"
|
41
|
+
"localhost:2181"
|
45
42
|
]
|
46
43
|
},
|
47
|
-
"
|
48
|
-
"
|
49
|
-
"
|
50
|
-
|
44
|
+
"haproxy": {
|
45
|
+
"port": 3214,
|
46
|
+
"server_options": "check inter 2s rise 3 fall 2",
|
47
|
+
"listen": [
|
48
|
+
"mode http",
|
49
|
+
"option httpchk /health"
|
50
|
+
]
|
51
|
+
}
|
51
52
|
}
|
52
|
-
|
53
|
+
},
|
53
54
|
"haproxy": {
|
54
55
|
"reload_command": "sudo service haproxy reload",
|
55
56
|
"config_file_path": "/etc/haproxy/haproxy.cfg",
|
@@ -85,12 +86,5 @@
|
|
85
86
|
"stats refresh 5s"
|
86
87
|
]
|
87
88
|
}
|
88
|
-
},
|
89
|
-
"synapse": {
|
90
|
-
"self_check_port": 3210,
|
91
|
-
"self_check_proxy_port": 3211,
|
92
|
-
"zk_servers": [
|
93
|
-
"localhost:2181"
|
94
|
-
]
|
95
89
|
}
|
96
90
|
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
{
|
2
|
+
"default_servers": [
|
3
|
+
{ "name": "default1", "host": "localhost", "port": 8080 }
|
4
|
+
],
|
5
|
+
"discovery": {
|
6
|
+
"method": "dns",
|
7
|
+
"nameserver": "10.10.1.13",
|
8
|
+
"servers": [
|
9
|
+
"0.www.example.com",
|
10
|
+
"1.www.example.com"
|
11
|
+
]
|
12
|
+
},
|
13
|
+
"haproxy": {
|
14
|
+
"server_options": "check inter 2s rise 3 fall 2",
|
15
|
+
"listen": [
|
16
|
+
"mode http",
|
17
|
+
"option httplog"
|
18
|
+
],
|
19
|
+
"backend": [
|
20
|
+
"mode http",
|
21
|
+
"option httpchk GET /health HTTP/1.0"
|
22
|
+
]
|
23
|
+
}
|
24
|
+
}
|