zoo-service-discovery 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/lib/zoo-service-discovery.rb +1 -0
- data/lib/zoo_service/discovery.rb +27 -30
- data/lib/zoo_service/publication.rb +48 -40
- data/spec/features/complex_discovery_spec.rb +8 -20
- data/spec/features/discovery_spec.rb +2 -2
- data/spec/features/passenger_spec.rb +57 -0
- data/spec/support/zookeeper_runner.rb +6 -19
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MzEyY2YzNDY0ZWI5ODY1OTkzYjVlMzgyMmM1NjJiZGY5Y2NiNjk1ZA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZTY1YjJkMzc2ZjA0NmQzMjgwZmQ4NGM2ZWVjYjkyNWIyOTgzYTg2NA==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
OGU3NmM0ODYwNGQ4N2VjNzAyMDY5ZjhiNzdlOWZjZWFkNjliN2FkYzMyM2Rj
|
10
|
+
MWU5ZDllYzBlMGJlYTZlNzZkOTdlZjAxMTkwODY2MDYwMGRhMWIzNmI1MzYz
|
11
|
+
YTAzZDY1MDI0ZmE5NjY2NTFjMWU1NjFmN2I5YjMzM2FjMGI0NDE=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MGZlZGM5NmZjMDU4M2NkYTIzODkyYzZjMDQ3OGU5OTZjZTI3NGY2MzlmM2Rk
|
14
|
+
YjViOGRkZjk4N2NjMzBhMDFhNmExMzFjZDYyOTM1YTcyMDRhZGFhM2NiYzUw
|
15
|
+
NTdjNDQ2Nzg0ZjJmOTQ2MjM4OGY3NzQyNDBhM2IwYzMxMzZmYzc=
|
@@ -4,42 +4,39 @@ require 'zk'
|
|
4
4
|
module ZooService
|
5
5
|
|
6
6
|
# Performs service discovery for a HTTP service consumer.
|
7
|
-
class
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
protected
|
20
|
-
|
21
|
-
# Gets published URLs of _service_name_.
|
22
|
-
def get_published_urls(service_name)
|
23
|
-
service_path = "/services/#{service_name}"
|
24
|
-
publications = zk.children(service_path, ignore: :no_node) || [ ]
|
7
|
+
class DiscoveryImpl
|
8
|
+
|
9
|
+
# :call-seq:
|
10
|
+
# get_service_url(name) => String
|
11
|
+
#
|
12
|
+
# Gets service URL by _name_.
|
13
|
+
#
|
14
|
+
# Returns service URL, if everything went OK, +nil+ otherwise.
|
15
|
+
def get_service_url(name)
|
16
|
+
get_published_urls(name).first
|
17
|
+
end
|
25
18
|
|
26
|
-
|
27
|
-
zk.get("#{service_path}/#{publications.last}", ignore: :no_node)
|
28
|
-
else
|
29
|
-
[ ]
|
30
|
-
end
|
31
|
-
end
|
19
|
+
protected
|
32
20
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
end
|
21
|
+
# Gets published URLs of _service_name_.
|
22
|
+
def get_published_urls(service_name)
|
23
|
+
service_path = "/services/#{service_name}"
|
24
|
+
publications = zk.children(service_path, ignore: :no_node) || [ ]
|
38
25
|
|
39
|
-
|
26
|
+
unless publications.empty?
|
27
|
+
zk.get("#{service_path}/#{publications.last}", ignore: :no_node)
|
28
|
+
else
|
29
|
+
[ ]
|
40
30
|
end
|
31
|
+
end
|
41
32
|
|
33
|
+
# Returns a working instance of a ZooKeeper client.
|
34
|
+
def zk
|
35
|
+
@zk ||= ZK.new(ENV['SERVICE_DISCOVERY_WELLKNOWN_ADDRESS'] || 'localhost:2181')
|
42
36
|
end
|
37
|
+
|
43
38
|
end
|
44
39
|
|
40
|
+
Discovery = DiscoveryImpl.new
|
41
|
+
|
45
42
|
end
|
@@ -4,56 +4,64 @@ require 'zk'
|
|
4
4
|
module ZooService
|
5
5
|
|
6
6
|
# Performs service publication for a HTTP service provider.
|
7
|
-
class
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
def register_service(name, url)
|
16
|
-
registration_block = create_registration_block(name, url)
|
17
|
-
service_registration_blocks << registration_block
|
18
|
-
registration_block.(zk)
|
7
|
+
class PublicationImpl
|
8
|
+
|
9
|
+
def initialize(phusion_passenger = nil)
|
10
|
+
return unless phusion_passenger
|
11
|
+
phusion_passenger.on_event(:starting_worker_process) do |forked|
|
12
|
+
if forked
|
13
|
+
reconnect
|
14
|
+
end
|
19
15
|
end
|
16
|
+
end
|
20
17
|
|
21
|
-
|
18
|
+
# :call-seq:
|
19
|
+
# register_service(name, url) => Boolean
|
20
|
+
#
|
21
|
+
# Registers a well-known service with _name_ at _url_.
|
22
|
+
#
|
23
|
+
# Returns +true+, if everything went OK, +false+ otherwise.
|
24
|
+
def register_service(name, url)
|
25
|
+
registration_block = create_registration_block(name, url)
|
26
|
+
service_registration_blocks << registration_block
|
27
|
+
registration_block.(zk)
|
28
|
+
end
|
22
29
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
zk.mkdir_p(service_path) unless zk.exists?(service_path)
|
28
|
-
zk.create("#{service_path}/node-", url, mode: :ephemeral_sequential)
|
29
|
-
}
|
30
|
-
end
|
30
|
+
def reconnect
|
31
|
+
@zk = nil
|
32
|
+
zk
|
33
|
+
end
|
31
34
|
|
32
|
-
|
33
|
-
# the ZooKeeper.
|
34
|
-
def service_registration_blocks
|
35
|
-
@service_registration_blocks ||= [ ]
|
36
|
-
end
|
35
|
+
protected
|
37
36
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
37
|
+
# Creates a lambda that once called registeres the service on the URL.
|
38
|
+
def create_registration_block(name, url)
|
39
|
+
-> zk {
|
40
|
+
service_path = "/services/#{name}"
|
41
|
+
zk.mkdir_p(service_path) unless zk.exists?(service_path)
|
42
|
+
zk.create("#{service_path}/node-", url, mode: :ephemeral_sequential)
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
# Stores the registration blocks that are rerun after reconnection to
|
47
|
+
# the ZooKeeper.
|
48
|
+
def service_registration_blocks
|
49
|
+
@service_registration_blocks ||= [ ]
|
50
|
+
end
|
43
51
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
52
|
+
# Returns a working instance of a ZooKeeper client.
|
53
|
+
def zk
|
54
|
+
@zk ||= ZK.new(ENV['SERVICE_DISCOVERY_WELLKNOWN_ADDRESS'] || 'localhost:2181') do |zk|
|
55
|
+
zk.on_connected do
|
56
|
+
# Rerun all the registrations upon reconnection
|
57
|
+
service_registration_blocks.each do |registration_block|
|
58
|
+
registration_block.(zk)
|
50
59
|
end
|
51
60
|
end
|
52
|
-
|
53
|
-
Thread.current[:service_publication_zk_client] = zk_client
|
54
61
|
end
|
55
|
-
|
56
62
|
end
|
63
|
+
|
57
64
|
end
|
58
65
|
|
66
|
+
Publication = defined?(PhusionPassenger) ? PublicationImpl.new(PhusionPassenger) : PublicationImpl.new
|
59
67
|
end
|
@@ -4,41 +4,30 @@ describe "Discovered service URL (registered in a separate process)" do
|
|
4
4
|
|
5
5
|
def kill_server_process
|
6
6
|
begin
|
7
|
-
Process.kill("
|
7
|
+
Process.kill("KILL", server_process)
|
8
8
|
Process.wait(server_process)
|
9
9
|
rescue Errno::ESRCH
|
10
10
|
# ignore
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
before {
|
15
|
-
if Thread.current[:service_discovery_zk_client]
|
16
|
-
Thread.current[:service_discovery_zk_client].close
|
17
|
-
Thread.current[:service_discovery_zk_client] = nil
|
18
|
-
end
|
19
|
-
|
20
|
-
if Thread.current[:service_publication_zk_client]
|
21
|
-
Thread.current[:service_publication_zk_client].close
|
22
|
-
Thread.current[:service_publication_zk_client] = nil
|
23
|
-
end
|
24
|
-
}
|
25
|
-
|
26
14
|
subject {
|
27
|
-
ZooService::
|
15
|
+
ZooService::DiscoveryImpl.new.get_service_url(service)
|
28
16
|
}
|
29
17
|
|
30
18
|
let(:real_service_url) {
|
31
19
|
"http://sample.dev/"
|
32
20
|
}
|
33
21
|
|
34
|
-
let(:service) {
|
35
|
-
"service"
|
22
|
+
let!(:service) {
|
23
|
+
"service%4.4d%4.4d" % [ rand(9999), rand(9999) ]
|
36
24
|
}
|
37
25
|
|
38
26
|
let!(:server_process) {
|
39
27
|
pid = fork do |variable|
|
40
|
-
ZooService::
|
41
|
-
sleep
|
28
|
+
ZooService::PublicationImpl.new.register_service(service, real_service_url)
|
29
|
+
sleep 60 # fail safely after 60 secs
|
30
|
+
exit
|
42
31
|
end
|
43
32
|
sleep 0.5
|
44
33
|
return pid
|
@@ -57,11 +46,10 @@ describe "Discovered service URL (registered in a separate process)" do
|
|
57
46
|
end
|
58
47
|
|
59
48
|
it "retains value when ZooKeeper fails and restarts with an empty DB" do
|
60
|
-
should == real_service_url
|
61
|
-
|
62
49
|
ZookeeperRunner.clean
|
63
50
|
ZookeeperRunner.stop
|
64
51
|
ZookeeperRunner.start
|
52
|
+
sleep 10
|
65
53
|
|
66
54
|
should == real_service_url
|
67
55
|
end
|
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
describe "Discovered service URL" do
|
4
4
|
|
5
5
|
subject {
|
6
|
-
ZooService::
|
6
|
+
ZooService::DiscoveryImpl.new.get_service_url(service)
|
7
7
|
}
|
8
8
|
|
9
9
|
let(:real_service_url) {
|
@@ -13,7 +13,7 @@ describe "Discovered service URL" do
|
|
13
13
|
context "when service is registered" do
|
14
14
|
|
15
15
|
let!(:service) {
|
16
|
-
ZooService::
|
16
|
+
ZooService::PublicationImpl.new.register_service("service", real_service_url)
|
17
17
|
"service"
|
18
18
|
}
|
19
19
|
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class PhusionPassenger
|
4
|
+
class << self
|
5
|
+
def on_event(event, &block)
|
6
|
+
@events ||= {}
|
7
|
+
@events[event] = block
|
8
|
+
end
|
9
|
+
|
10
|
+
def start
|
11
|
+
fork do
|
12
|
+
# Phusion Passenger user request handler
|
13
|
+
@events[:starting_worker_process].call(true)
|
14
|
+
sleep 10
|
15
|
+
exit
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "Publication service" do
|
22
|
+
|
23
|
+
describe "when started on Passenger" do
|
24
|
+
let!(:service) {
|
25
|
+
"service%4.4d%4.4d" % [ rand(9999), rand(9999) ]
|
26
|
+
}
|
27
|
+
|
28
|
+
let(:url) {
|
29
|
+
"http://pornhub.com/"
|
30
|
+
}
|
31
|
+
|
32
|
+
subject {
|
33
|
+
ZooService::DiscoveryImpl.new.get_service_url(service)
|
34
|
+
}
|
35
|
+
|
36
|
+
before do
|
37
|
+
fork do
|
38
|
+
# Phusion Passenger starter
|
39
|
+
ZooService::PublicationImpl.new(PhusionPassenger).register_service(service, url)
|
40
|
+
PhusionPassenger.start
|
41
|
+
exit
|
42
|
+
end
|
43
|
+
|
44
|
+
sleep 1 # we love sleeping in these tests
|
45
|
+
end
|
46
|
+
|
47
|
+
it { should == url }
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
describe "when started on other(non-Passenger) server" do
|
52
|
+
it "should not reconnect" do
|
53
|
+
expect(ZooService::PublicationImpl.new).not_to receive(:reconnect)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -2,13 +2,15 @@ class ZookeeperRunner
|
|
2
2
|
class << self
|
3
3
|
|
4
4
|
def start
|
5
|
-
|
6
|
-
|
5
|
+
until `zkServer start 2>&1`.include?("already running")
|
6
|
+
sleep 1
|
7
|
+
end
|
7
8
|
end
|
8
9
|
|
9
10
|
def stop
|
10
|
-
|
11
|
-
|
11
|
+
until `zkServer stop 2>&1`.include?("no zookeeper to stop")
|
12
|
+
sleep 1
|
13
|
+
end
|
12
14
|
end
|
13
15
|
|
14
16
|
def clean
|
@@ -17,20 +19,5 @@ class ZookeeperRunner
|
|
17
19
|
end
|
18
20
|
end
|
19
21
|
|
20
|
-
protected
|
21
|
-
|
22
|
-
def wait_zookeeper_start
|
23
|
-
sleep 1 while zookeeper_pid == 0
|
24
|
-
end
|
25
|
-
|
26
|
-
def wait_zookeeper_stop
|
27
|
-
sleep 0.125 while zookeeper_pid > 0
|
28
|
-
end
|
29
|
-
|
30
|
-
def zookeeper_pid
|
31
|
-
`ps aux | grep zookeeper | grep java | grep -v grep | awk '{ print $2; }'`.to_i
|
32
|
-
end
|
33
|
-
|
34
|
-
|
35
22
|
end
|
36
23
|
end
|
metadata
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zoo-service-discovery
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Druzhinin <andrey.druginin@gmail.com>
|
8
|
+
- Ramil Gilmanov <ramil1985@mail.ru>
|
8
9
|
- Ivan Kasatenko <sky@uniqsystems.ru>
|
9
10
|
autorequire:
|
10
11
|
bindir: bin
|
11
12
|
cert_chain: []
|
12
|
-
date: 2013-
|
13
|
+
date: 2013-12-27 00:00:00.000000000 Z
|
13
14
|
dependencies:
|
14
15
|
- !ruby/object:Gem::Dependency
|
15
16
|
name: zk
|
@@ -36,6 +37,7 @@ files:
|
|
36
37
|
- lib/zoo_service/publication.rb
|
37
38
|
- spec/features/complex_discovery_spec.rb
|
38
39
|
- spec/features/discovery_spec.rb
|
40
|
+
- spec/features/passenger_spec.rb
|
39
41
|
- spec/spec_helper.rb
|
40
42
|
- spec/support/zookeeper_runner.rb
|
41
43
|
- README.md
|