scales-server 0.0.1.beta.2 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/scales-server-proxy +17 -0
- data/lib/scales-server.rb +1 -0
- data/lib/scales-server/base.rb +8 -6
- data/lib/scales-server/boot/autoload.rb +2 -1
- data/lib/scales-server/boot/initializers/proxy.rb +2 -0
- data/lib/scales-server/dispatch.rb +2 -1
- data/lib/scales-server/dispatch/enqueue.rb +3 -4
- data/lib/scales-server/dispatch/lookup.rb +1 -1
- data/lib/scales-server/dispatch/response.rb +49 -0
- data/lib/scales-server/proxy.rb +31 -0
- data/lib/scales-server/proxy/backend.rb +66 -0
- data/lib/scales-server/proxy/callbacks.rb +31 -0
- data/lib/scales-server/version.rb +1 -1
- metadata +33 -14
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'scales-server'
|
4
|
+
|
5
|
+
Scales.pwd = Dir.pwd
|
6
|
+
|
7
|
+
@port = 3000
|
8
|
+
@servers = []
|
9
|
+
|
10
|
+
arguments = ARGV.dup
|
11
|
+
while !arguments.empty? do
|
12
|
+
argument = arguments.shift
|
13
|
+
if argument == "-p" or argument == "--port" then @port = arguments.shift else @servers << argument end
|
14
|
+
end
|
15
|
+
|
16
|
+
Scales::Server::Proxy::Backend.add(@servers)
|
17
|
+
Scales::Server::Proxy.run!("0.0.0.0", @port)
|
data/lib/scales-server.rb
CHANGED
data/lib/scales-server/base.rb
CHANGED
@@ -6,16 +6,18 @@ module Scales
|
|
6
6
|
ARGV << "--environment" << "#{Scales.env}"
|
7
7
|
|
8
8
|
server = Server.new
|
9
|
-
runner = Goliath::Runner.new(ARGV, server)
|
10
|
-
runner.app = Goliath::Rack::Builder.build(Server, server)
|
11
|
-
runner.load_plugins(Server.plugins)
|
9
|
+
@runner = Goliath::Runner.new(ARGV, server)
|
10
|
+
@runner.app = Goliath::Rack::Builder.build(Server, server)
|
11
|
+
@runner.load_plugins(Server.plugins)
|
12
12
|
|
13
|
-
status = Status.new(runner.address, runner.port)
|
13
|
+
status = Status.new(@runner.address, @runner.port)
|
14
14
|
status.start!
|
15
|
-
at_exit{ status.stop! }
|
16
15
|
Scales::Server.status = status
|
17
16
|
|
18
|
-
|
17
|
+
@pid ||= Process.pid
|
18
|
+
at_exit{ status.stop! if !@runner.daemonize or Process.pid != @pid }
|
19
|
+
|
20
|
+
@runner.run
|
19
21
|
end
|
20
22
|
|
21
23
|
@@status = nil
|
@@ -4,12 +4,13 @@ module Scales
|
|
4
4
|
autoload :Lookup, "scales-server/dispatch/lookup"
|
5
5
|
autoload :Enqueue, "scales-server/dispatch/enqueue"
|
6
6
|
autoload :Request, "scales-server/dispatch/request"
|
7
|
+
autoload :Response, "scales-server/dispatch/response"
|
7
8
|
autoload :Job, "scales-server/dispatch/job"
|
8
9
|
|
9
10
|
class << self
|
10
11
|
|
11
12
|
def request(env)
|
12
|
-
if is_get_request?(env) then Lookup.
|
13
|
+
if is_get_request?(env) then Lookup.resource(env) else Enqueue.request(env) end
|
13
14
|
end
|
14
15
|
|
15
16
|
private
|
@@ -9,10 +9,9 @@ module Scales
|
|
9
9
|
job = Request.to_job(id, env)
|
10
10
|
|
11
11
|
Scales::Server.status.put_request_in_queue!(job)
|
12
|
-
|
12
|
+
Storage::Async.add(Storage::REQUEST_QUEUE, JSON.generate(job))
|
13
13
|
|
14
|
-
response =
|
15
|
-
response = Job.to_response(response)
|
14
|
+
response = Response.subscribe(id)
|
16
15
|
Scales::Server.status.took_response_from_queue!(response)
|
17
16
|
response
|
18
17
|
end
|
@@ -21,7 +20,7 @@ module Scales
|
|
21
20
|
|
22
21
|
def create_random_id
|
23
22
|
id = SecureRandom.hex(16)
|
24
|
-
Storage::Async.connection.set("test_last_request_id",
|
23
|
+
Storage::Async.connection.set("test_last_request_id", id) if Goliath.env == :test
|
25
24
|
id
|
26
25
|
end
|
27
26
|
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Scales
|
2
|
+
module Server
|
3
|
+
module Dispatch
|
4
|
+
module Response
|
5
|
+
class << self
|
6
|
+
|
7
|
+
@@redis = nil
|
8
|
+
@@subscribers = {}
|
9
|
+
@@subscribed = false
|
10
|
+
|
11
|
+
def subscribe(id)
|
12
|
+
setup_subscription!
|
13
|
+
@@subscribers[id] = Fiber.current
|
14
|
+
Fiber.yield
|
15
|
+
end
|
16
|
+
|
17
|
+
def reset!
|
18
|
+
@@redis = nil
|
19
|
+
@@subscribers = {}
|
20
|
+
@@subscribed = false
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def connect!
|
26
|
+
return if @@redis and @@redis.connected?
|
27
|
+
@@redis = Storage::Async.new_connection!
|
28
|
+
end
|
29
|
+
|
30
|
+
def setup_subscription!
|
31
|
+
connect!
|
32
|
+
return if @@subscribed
|
33
|
+
|
34
|
+
@@redis.subscribe(Storage::RESPONSE_CHANNEL)
|
35
|
+
@@redis.on(:message) do |channel, message|
|
36
|
+
response = Job.to_response(message)
|
37
|
+
id = response[1]['scales.id']
|
38
|
+
|
39
|
+
fiber = @@subscribers.delete(id)
|
40
|
+
fiber.resume(response) if fiber
|
41
|
+
end
|
42
|
+
@@subscribed = true
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Scales
|
2
|
+
module Server
|
3
|
+
module Proxy
|
4
|
+
autoload :Backend, "scales-server/proxy/backend"
|
5
|
+
autoload :Callbacks, "scales-server/proxy/callbacks"
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
def run!(host = '0.0.0.0', port = 9999)
|
10
|
+
|
11
|
+
puts "Proxy Port: #{port}".green
|
12
|
+
puts "Server Ports: #{Backend.ports.join(', ')}".green
|
13
|
+
|
14
|
+
::Proxy.start(:host => host, :port => port, :debug => false) do |connection|
|
15
|
+
|
16
|
+
Backend.select do |backend|
|
17
|
+
connection.server backend, :host => backend.host, :port => backend.port
|
18
|
+
|
19
|
+
connection.on_connect &Callbacks.on_connect
|
20
|
+
connection.on_data &Callbacks.on_data
|
21
|
+
connection.on_response &Callbacks.on_response
|
22
|
+
connection.on_finish &Callbacks.on_finish
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Scales
|
2
|
+
module Server
|
3
|
+
module Proxy
|
4
|
+
|
5
|
+
class Backend
|
6
|
+
@ports = []
|
7
|
+
attr_reader :url, :host, :port
|
8
|
+
attr_accessor :load
|
9
|
+
alias :to_s :url
|
10
|
+
|
11
|
+
def initialize(options={})
|
12
|
+
raise ArgumentError, "Please provide a :url and :load" unless options[:url]
|
13
|
+
@url = options[:url]
|
14
|
+
@load = options[:load] || 0
|
15
|
+
parsed = URI.parse(@url)
|
16
|
+
@host, @port = parsed.host, parsed.port
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.add(ports)
|
20
|
+
ports.each{ |port| @ports << { :url => "http://0.0.0.0:#{port}" } }
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.ports
|
24
|
+
@ports.map{ |port| port[:url].split(":").last }
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.select(strategy = :balanced)
|
28
|
+
@strategy = strategy.to_sym
|
29
|
+
case @strategy
|
30
|
+
when :balanced
|
31
|
+
backend = list.sort_by { |b| b.load }.first
|
32
|
+
when :roundrobin
|
33
|
+
@pool = list.clone if @pool.nil? || @pool.empty?
|
34
|
+
backend = @pool.shift
|
35
|
+
when :random
|
36
|
+
backend = list[ rand(list.size-1) ]
|
37
|
+
else
|
38
|
+
raise ArgumentError, "Unknown strategy: #{@strategy}"
|
39
|
+
end
|
40
|
+
|
41
|
+
Callbacks.on_select.call(backend)
|
42
|
+
yield backend if block_given?
|
43
|
+
backend
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.list
|
47
|
+
@list ||= @ports.map { |backend| new backend }
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.strategy
|
51
|
+
@strategy
|
52
|
+
end
|
53
|
+
|
54
|
+
def increment_counter
|
55
|
+
self.load += 1
|
56
|
+
end
|
57
|
+
|
58
|
+
def decrement_counter
|
59
|
+
self.load -= 1
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Scales
|
2
|
+
module Server
|
3
|
+
module Proxy
|
4
|
+
|
5
|
+
module Callbacks
|
6
|
+
extend self
|
7
|
+
|
8
|
+
def on_connect
|
9
|
+
end
|
10
|
+
|
11
|
+
def on_data
|
12
|
+
lambda { |data| data }
|
13
|
+
end
|
14
|
+
|
15
|
+
def on_response
|
16
|
+
lambda { |backend, response| response }
|
17
|
+
end
|
18
|
+
|
19
|
+
def on_select
|
20
|
+
lambda { |backend| backend.increment_counter if Backend.strategy == :balanced }
|
21
|
+
end
|
22
|
+
|
23
|
+
def on_finish
|
24
|
+
lambda { |backend| backend.decrement_counter if Backend.strategy == :balanced }
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
metadata
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scales-server
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.0.4
|
5
|
+
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Thomas Fankhauser
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-08-
|
12
|
+
date: 2012-08-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
16
|
-
requirement: &
|
16
|
+
requirement: &70195223931780 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 0.9.2.2
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70195223931780
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &70195223931280 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,21 +32,21 @@ dependencies:
|
|
32
32
|
version: '2.11'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70195223931280
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: scales-core
|
38
|
-
requirement: &
|
38
|
+
requirement: &70195223930840 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - =
|
42
42
|
- !ruby/object:Gem::Version
|
43
|
-
version: 0.0.
|
43
|
+
version: 0.0.4
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70195223930840
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: goliath
|
49
|
-
requirement: &
|
49
|
+
requirement: &70195223930340 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,12 +54,24 @@ dependencies:
|
|
54
54
|
version: 1.0.0.beta.1
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70195223930340
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: em-proxy
|
60
|
+
requirement: &70195223929840 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 0.1.6
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70195223929840
|
58
69
|
description: Super Scale Caching Framework - Server
|
59
70
|
email:
|
60
71
|
- tommylefunk@googlemail.com
|
61
72
|
executables:
|
62
73
|
- scales-server
|
74
|
+
- scales-server-proxy
|
63
75
|
extensions: []
|
64
76
|
extra_rdoc_files: []
|
65
77
|
files:
|
@@ -67,18 +79,25 @@ files:
|
|
67
79
|
- lib/scales-server/base.rb
|
68
80
|
- lib/scales-server/boot/autoload.rb
|
69
81
|
- lib/scales-server/boot/initializers/goliath.rb
|
82
|
+
- lib/scales-server/boot/initializers/proxy.rb
|
70
83
|
- lib/scales-server/content_type.rb
|
71
84
|
- lib/scales-server/dispatch/enqueue.rb
|
72
85
|
- lib/scales-server/dispatch/job.rb
|
73
86
|
- lib/scales-server/dispatch/lookup.rb
|
74
87
|
- lib/scales-server/dispatch/request.rb
|
88
|
+
- lib/scales-server/dispatch/response.rb
|
75
89
|
- lib/scales-server/dispatch.rb
|
90
|
+
- lib/scales-server/proxy/backend.rb
|
91
|
+
- lib/scales-server/proxy/callbacks.rb
|
92
|
+
- lib/scales-server/proxy.rb
|
76
93
|
- lib/scales-server/server.rb
|
77
94
|
- lib/scales-server/status.rb
|
78
95
|
- lib/scales-server/version.rb
|
79
96
|
- lib/scales-server.rb
|
80
97
|
- !binary |-
|
81
98
|
YmluL3NjYWxlcy1zZXJ2ZXI=
|
99
|
+
- !binary |-
|
100
|
+
YmluL3NjYWxlcy1zZXJ2ZXItcHJveHk=
|
82
101
|
homepage: http://itscales.org
|
83
102
|
licenses: []
|
84
103
|
post_install_message:
|
@@ -94,9 +113,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
94
113
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
114
|
none: false
|
96
115
|
requirements:
|
97
|
-
- - ! '
|
116
|
+
- - ! '>='
|
98
117
|
- !ruby/object:Gem::Version
|
99
|
-
version:
|
118
|
+
version: '0'
|
100
119
|
requirements: []
|
101
120
|
rubyforge_project:
|
102
121
|
rubygems_version: 1.8.11
|