zoo-service-discovery 1.0.1 → 1.1.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.
- 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
|