em-proxy 0.1.4 → 0.1.5
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 +1 -0
- data/.rspec +0 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +36 -0
- data/README.rdoc +9 -6
- data/Rakefile +3 -18
- data/bin/em-proxy +48 -0
- data/em-proxy.gemspec +19 -70
- data/examples/balancing-client.rb +20 -0
- data/examples/balancing.rb +195 -0
- data/spec/balancing_spec.rb +103 -0
- data/spec/helper.rb +2 -2
- data/spec/proxy_spec.rb +1 -1
- metadata +63 -26
- data/VERSION +0 -1
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
.bundle
|
data/.rspec
ADDED
File without changes
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
em-proxy (0.1.5)
|
5
|
+
eventmachine
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: http://rubygems.org/
|
9
|
+
specs:
|
10
|
+
addressable (2.2.2)
|
11
|
+
ansi (1.2.2)
|
12
|
+
diff-lcs (1.1.2)
|
13
|
+
em-http-request (0.3.0)
|
14
|
+
addressable (>= 2.0.0)
|
15
|
+
escape_utils
|
16
|
+
eventmachine (>= 0.12.9)
|
17
|
+
escape_utils (0.1.9)
|
18
|
+
eventmachine (0.12.11)
|
19
|
+
rspec (2.4.0)
|
20
|
+
rspec-core (~> 2.4.0)
|
21
|
+
rspec-expectations (~> 2.4.0)
|
22
|
+
rspec-mocks (~> 2.4.0)
|
23
|
+
rspec-core (2.4.0)
|
24
|
+
rspec-expectations (2.4.0)
|
25
|
+
diff-lcs (~> 1.1.2)
|
26
|
+
rspec-mocks (2.4.0)
|
27
|
+
|
28
|
+
PLATFORMS
|
29
|
+
ruby
|
30
|
+
|
31
|
+
DEPENDENCIES
|
32
|
+
ansi
|
33
|
+
em-http-request
|
34
|
+
em-proxy!
|
35
|
+
eventmachine
|
36
|
+
rspec
|
data/README.rdoc
CHANGED
@@ -7,14 +7,17 @@ EventMachine Proxy DSL for writing high-performance transparent / intercepting p
|
|
7
7
|
|
8
8
|
== Getting started
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
$> gem install em-proxy
|
11
|
+
$> em-proxy
|
12
|
+
Usage: em-proxy [options]
|
13
|
+
-l, --listen [PORT] Port to listen on
|
14
|
+
-d, --duplex [host:port, ...] List of backends to duplex data to
|
15
|
+
-r, --relay [hostname:port] Relay endpoint: hostname:port
|
16
|
+
-v, --verbose Run in debug mode
|
14
17
|
|
15
|
-
|
18
|
+
$> em-proxy -l 8080 -r localhost:8081 -d localhost:8082,localhost:8083 -v
|
16
19
|
|
17
|
-
|
20
|
+
The above will start em-proxy on port 8080, relay and respond with data from port 8081, and also (optional) duplicate all traffic to ports 8082 and 8083 (and discard their responses).
|
18
21
|
|
19
22
|
== Simple port forwarding proxy
|
20
23
|
|
data/Rakefile
CHANGED
@@ -1,19 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'bundler'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
Jeweler::Tasks.new do |gemspec|
|
6
|
-
gemspec.name = "em-proxy"
|
7
|
-
gemspec.summary = "EventMachine Proxy DSL"
|
8
|
-
gemspec.description = gemspec.summary
|
9
|
-
gemspec.email = "ilya@igvita.com"
|
10
|
-
gemspec.homepage = "http://github.com/igrigorik/em-proxy"
|
11
|
-
gemspec.authors = ["Ilya Grigorik"]
|
12
|
-
gemspec.add_dependency('eventmachine', '>= 0.12.9')
|
13
|
-
gemspec.rubyforge_project = "em-proxy"
|
14
|
-
end
|
15
|
-
|
16
|
-
Jeweler::GemcutterTasks.new
|
17
|
-
rescue LoadError
|
18
|
-
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
19
|
-
end
|
3
|
+
Bundler.setup
|
4
|
+
Bundler::GemHelper.install_tasks
|
data/bin/em-proxy
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
|
4
|
+
$LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
|
5
|
+
|
6
|
+
require 'em-proxy'
|
7
|
+
require 'optparse'
|
8
|
+
|
9
|
+
ARGV << '--help' if ARGV.empty?
|
10
|
+
|
11
|
+
options = {}
|
12
|
+
OptionParser.new do |opts|
|
13
|
+
opts.banner = "Usage: em-proxy [options]"
|
14
|
+
|
15
|
+
opts.on("-l", "--listen [PORT]", Integer, "Port to listen on") do |v|
|
16
|
+
options[:listen] = v
|
17
|
+
end
|
18
|
+
|
19
|
+
opts.on("-d", "--duplex [host:port, ...]", Array, "List of backends to duplex data to") do |v|
|
20
|
+
options[:duplex] = v
|
21
|
+
end
|
22
|
+
|
23
|
+
opts.on("-r", "--relay [hostname:port]", String, "Relay endpoint: hostname:port") do |v|
|
24
|
+
options[:relay] = v.split(":")
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on("-v", "--verbose", "Run in debug mode") do |v|
|
28
|
+
options[:verbose] = v
|
29
|
+
end
|
30
|
+
end.parse!
|
31
|
+
|
32
|
+
|
33
|
+
Proxy.start(:host => "0.0.0.0", :port => options[:listen] , :debug => options[:verbose]) do |conn|
|
34
|
+
conn.server :relay, :host => options[:relay].first, :port => options[:relay].last.to_i
|
35
|
+
|
36
|
+
options[:duplex].each_with_index do |backend,i|
|
37
|
+
hostname, port = backend.split(":")
|
38
|
+
conn.server "backend_#{i}".intern, :host => hostname, :port => port.to_i
|
39
|
+
end if options[:duplex]
|
40
|
+
|
41
|
+
conn.on_data do |data|
|
42
|
+
data
|
43
|
+
end
|
44
|
+
|
45
|
+
conn.on_response do |server, resp|
|
46
|
+
resp if server == :relay
|
47
|
+
end
|
48
|
+
end
|
data/em-proxy.gemspec
CHANGED
@@ -1,76 +1,25 @@
|
|
1
|
-
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
1
|
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
5
3
|
|
6
4
|
Gem::Specification.new do |s|
|
7
|
-
s.name
|
8
|
-
s.version
|
5
|
+
s.name = "em-proxy"
|
6
|
+
s.version = "0.1.5"
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = ["Ilya Grigorik"]
|
9
|
+
s.email = ["ilya@igvita.com"]
|
10
|
+
s.homepage = "http://github.com/igrigorik/em-proxy"
|
11
|
+
s.summary = %q{EventMachine Proxy DSL}
|
12
|
+
s.description = s.summary
|
9
13
|
|
10
|
-
s.
|
11
|
-
s.authors = ["Ilya Grigorik"]
|
12
|
-
s.date = %q{2010-10-03}
|
13
|
-
s.description = %q{EventMachine Proxy DSL}
|
14
|
-
s.email = %q{ilya@igvita.com}
|
15
|
-
s.extra_rdoc_files = [
|
16
|
-
"README.rdoc"
|
17
|
-
]
|
18
|
-
s.files = [
|
19
|
-
"README.rdoc",
|
20
|
-
"Rakefile",
|
21
|
-
"VERSION",
|
22
|
-
"em-proxy.gemspec",
|
23
|
-
"examples/appserver.rb",
|
24
|
-
"examples/beanstalkd_interceptor.rb",
|
25
|
-
"examples/duplex.rb",
|
26
|
-
"examples/line_interceptor.rb",
|
27
|
-
"examples/port_forward.rb",
|
28
|
-
"examples/relay_port_forward.rb",
|
29
|
-
"examples/schemaless-mysql/mysql_interceptor.rb",
|
30
|
-
"examples/selective_forward.rb",
|
31
|
-
"examples/simple.rb",
|
32
|
-
"examples/smtp_spam_filter.rb",
|
33
|
-
"examples/smtp_whitelist.rb",
|
34
|
-
"lib/em-proxy.rb",
|
35
|
-
"lib/em-proxy/backend.rb",
|
36
|
-
"lib/em-proxy/connection.rb",
|
37
|
-
"lib/em-proxy/proxy.rb",
|
38
|
-
"spec/helper.rb",
|
39
|
-
"spec/proxy_spec.rb"
|
40
|
-
]
|
41
|
-
s.homepage = %q{http://github.com/igrigorik/em-proxy}
|
42
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
43
|
-
s.require_paths = ["lib"]
|
44
|
-
s.rubyforge_project = %q{em-proxy}
|
45
|
-
s.rubygems_version = %q{1.3.7}
|
46
|
-
s.summary = %q{EventMachine Proxy DSL}
|
47
|
-
s.test_files = [
|
48
|
-
"spec/helper.rb",
|
49
|
-
"spec/proxy_spec.rb",
|
50
|
-
"examples/appserver.rb",
|
51
|
-
"examples/beanstalkd_interceptor.rb",
|
52
|
-
"examples/duplex.rb",
|
53
|
-
"examples/line_interceptor.rb",
|
54
|
-
"examples/port_forward.rb",
|
55
|
-
"examples/relay_port_forward.rb",
|
56
|
-
"examples/schemaless-mysql/mysql_interceptor.rb",
|
57
|
-
"examples/selective_forward.rb",
|
58
|
-
"examples/simple.rb",
|
59
|
-
"examples/smtp_spam_filter.rb",
|
60
|
-
"examples/smtp_whitelist.rb"
|
61
|
-
]
|
62
|
-
|
63
|
-
if s.respond_to? :specification_version then
|
64
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
65
|
-
s.specification_version = 3
|
14
|
+
s.rubyforge_project = "em-proxy"
|
66
15
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
end
|
72
|
-
else
|
73
|
-
s.add_dependency(%q<eventmachine>, [">= 0.12.9"])
|
74
|
-
end
|
75
|
-
end
|
16
|
+
s.add_dependency "eventmachine"
|
17
|
+
s.add_development_dependency "rspec"
|
18
|
+
s.add_development_dependency "em-http-request"
|
19
|
+
s.add_development_dependency "ansi"
|
76
20
|
|
21
|
+
s.files = `git ls-files`.split("\n")
|
22
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
23
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
24
|
+
s.require_paths = ["lib"]
|
25
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# A simple HTTP client, which sends multiple requests to the proxy server
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
|
5
|
+
proxy = Net::HTTP::Proxy('0.0.0.0', '9999')
|
6
|
+
|
7
|
+
count = ENV['COUNT'] || 5
|
8
|
+
|
9
|
+
threads = []
|
10
|
+
count.to_i.times do |i|
|
11
|
+
threads << Thread.new do
|
12
|
+
proxy.start('www.example.com') do |http|
|
13
|
+
puts http.get('/').body
|
14
|
+
puts "^^^ #{i+1} " + '-'*80 + "\n\n"
|
15
|
+
end
|
16
|
+
sleep 0.1
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
threads.each { |t| t.join }
|
@@ -0,0 +1,195 @@
|
|
1
|
+
require 'lib/em-proxy'
|
2
|
+
require 'ansi/code'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
# = Balancing Proxy
|
6
|
+
#
|
7
|
+
# A simple example of a balancing, reverse/forward proxy such as Nginx or HAProxy.
|
8
|
+
#
|
9
|
+
# Given a list of backends, it's able to distribute requests to backends
|
10
|
+
# via different strategies (_random_, _roundrobin_, _balanced_), see <tt>Backend.select</tt>.
|
11
|
+
#
|
12
|
+
# This example is provided for didactic purposes. Nevertheless, based on some preliminary benchmarks
|
13
|
+
# and live tests, it performs well in production usage.
|
14
|
+
#
|
15
|
+
# You can customize the behaviour of the proxy by changing the <tt>BalancingProxy::Callbacks</tt>
|
16
|
+
# callbacks. To give you some ideas:
|
17
|
+
#
|
18
|
+
# * Store statistics for the proxy load in Redis (eg.: <tt>$redis.incr "proxy>backends>#{backend}>total"</tt>)
|
19
|
+
# * Use Redis' _SortedSet_ instead of updating the <tt>Backend.list</tt> hash to allow for polling from external process
|
20
|
+
# * Use <b>em-websocket</b>[https://github.com/igrigorik/em-websocket] to build a web frontend for monitoring
|
21
|
+
#
|
22
|
+
module BalancingProxy
|
23
|
+
extend self
|
24
|
+
|
25
|
+
BACKENDS = [
|
26
|
+
{:url => "http://0.0.0.0:3000"},
|
27
|
+
{:url => "http://0.0.0.0:3001"},
|
28
|
+
{:url => "http://0.0.0.0:3002"}
|
29
|
+
]
|
30
|
+
|
31
|
+
# Represents a "backend", ie. the endpoint for the proxy.
|
32
|
+
#
|
33
|
+
# This could be eg. a WEBrick webserver (see below), so the proxy server works as a _reverse_ proxy.
|
34
|
+
# But it could also be a proxy server, so the proxy server works as a _forward_ proxy.
|
35
|
+
#
|
36
|
+
class Backend
|
37
|
+
|
38
|
+
attr_reader :url, :host, :port
|
39
|
+
attr_accessor :load
|
40
|
+
alias :to_s :url
|
41
|
+
|
42
|
+
def initialize(options={})
|
43
|
+
raise ArgumentError, "Please provide a :url and :load" unless options[:url]
|
44
|
+
@url = options[:url]
|
45
|
+
@load = options[:load] || 0
|
46
|
+
parsed = URI.parse(@url)
|
47
|
+
@host, @port = parsed.host, parsed.port
|
48
|
+
end
|
49
|
+
|
50
|
+
# Select backend: balanced, round-robin or random
|
51
|
+
#
|
52
|
+
def self.select(strategy = :balanced)
|
53
|
+
@strategy = strategy.to_sym
|
54
|
+
case @strategy
|
55
|
+
when :balanced
|
56
|
+
backend = list.sort_by { |b| b.load }.first
|
57
|
+
when :roundrobin
|
58
|
+
@pool = list.clone if @pool.nil? || @pool.empty?
|
59
|
+
backend = @pool.shift
|
60
|
+
when :random
|
61
|
+
backend = list[ rand(list.size-1) ]
|
62
|
+
else
|
63
|
+
raise ArgumentError, "Unknown strategy: #{@strategy}"
|
64
|
+
end
|
65
|
+
|
66
|
+
Callbacks.on_select.call(backend)
|
67
|
+
yield backend if block_given?
|
68
|
+
backend
|
69
|
+
end
|
70
|
+
|
71
|
+
# List of backends
|
72
|
+
#
|
73
|
+
def self.list
|
74
|
+
@list ||= BACKENDS.map { |backend| new backend }
|
75
|
+
end
|
76
|
+
|
77
|
+
# Return balancing strategy
|
78
|
+
#
|
79
|
+
def self.strategy
|
80
|
+
@strategy
|
81
|
+
end
|
82
|
+
|
83
|
+
# Increment "currently serving requests" counter
|
84
|
+
#
|
85
|
+
def increment_counter
|
86
|
+
self.load += 1
|
87
|
+
end
|
88
|
+
|
89
|
+
# Decrement "currently serving requests" counter
|
90
|
+
#
|
91
|
+
def decrement_counter
|
92
|
+
self.load -= 1
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
# Callbacks for em-proxy events
|
98
|
+
#
|
99
|
+
module Callbacks
|
100
|
+
include ANSI::Code
|
101
|
+
extend self
|
102
|
+
|
103
|
+
def on_select
|
104
|
+
lambda do |backend|
|
105
|
+
puts black_on_white { 'on_select'.ljust(12) } + " #{backend.inspect}"
|
106
|
+
backend.increment_counter if Backend.strategy == :balanced
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def on_connect
|
111
|
+
lambda do |backend|
|
112
|
+
puts black_on_magenta { 'on_connect'.ljust(12) } + ' ' + bold { backend }
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def on_data
|
117
|
+
lambda do |data|
|
118
|
+
puts black_on_yellow { 'on_data'.ljust(12) }, data
|
119
|
+
data
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def on_response
|
124
|
+
lambda do |backend, resp|
|
125
|
+
puts black_on_green { 'on_response'.ljust(12) } + " from #{backend}", resp
|
126
|
+
resp
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def on_finish
|
131
|
+
lambda do |backend|
|
132
|
+
puts black_on_cyan { 'on_finish'.ljust(12) } + " for #{backend}", ''
|
133
|
+
backend.decrement_counter if Backend.strategy == :balanced
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
# Wrapping the proxy server
|
140
|
+
#
|
141
|
+
module Server
|
142
|
+
def run(host='0.0.0.0', port=9999)
|
143
|
+
|
144
|
+
puts ANSI::Code.bold { "Launching proxy at #{host}:#{port}...\n" }
|
145
|
+
|
146
|
+
Proxy.start(:host => host, :port => port, :debug => false) do |conn|
|
147
|
+
|
148
|
+
Backend.select do |backend|
|
149
|
+
|
150
|
+
conn.server backend, :host => backend.host, :port => backend.port
|
151
|
+
|
152
|
+
conn.on_connect &Callbacks.on_connect
|
153
|
+
conn.on_data &Callbacks.on_data
|
154
|
+
conn.on_response &Callbacks.on_response
|
155
|
+
conn.on_finish &Callbacks.on_finish
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
module_function :run
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
if __FILE__ == $0
|
167
|
+
|
168
|
+
require 'rack'
|
169
|
+
|
170
|
+
class Proxy
|
171
|
+
def self.stop
|
172
|
+
puts "Terminating ProxyServer"
|
173
|
+
EventMachine.stop
|
174
|
+
$servers.each do |pid|
|
175
|
+
puts "Terminating webserver #{pid}"
|
176
|
+
Process.kill('KILL', pid)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
# Simple Rack app to run
|
182
|
+
app = proc { |env| [ 200, {'Content-Type' => 'text/plain'}, ["Hello World!"] ] }
|
183
|
+
|
184
|
+
# Run app on ports 3000-3002
|
185
|
+
$servers = []
|
186
|
+
3.times do |i|
|
187
|
+
$servers << Process.fork { Rack::Handler::WEBrick.run(app, {:Host => "0.0.0.0", :Port => "300#{i}"}) }
|
188
|
+
end
|
189
|
+
|
190
|
+
puts ANSI::Code::green_on_black { "\n=> Send multiple requests to the proxy by running `ruby balancing-client.rb`\n" }
|
191
|
+
|
192
|
+
# Start proxy
|
193
|
+
BalancingProxy::Server.run
|
194
|
+
|
195
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'spec/helper'
|
2
|
+
require 'examples/balancing'
|
3
|
+
|
4
|
+
describe BalancingProxy do
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
class BalancingProxy::Backend
|
8
|
+
@list = nil; @pool = nil
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
before(:all) do
|
13
|
+
@original_stdout = $stdout
|
14
|
+
# Silence the noisy STDOUT output
|
15
|
+
$stdout = File.new('/dev/null', 'w')
|
16
|
+
end
|
17
|
+
|
18
|
+
after(:all) do
|
19
|
+
$stdout = @original_stdout
|
20
|
+
end
|
21
|
+
|
22
|
+
context "generally" do
|
23
|
+
|
24
|
+
it "should raise error for unknown strategy" do
|
25
|
+
lambda { BalancingProxy::Backend.select(:asdf)}.should raise_error(ArgumentError)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
context "when using the 'random' strategy" do
|
31
|
+
|
32
|
+
it "should select random backend" do
|
33
|
+
class BalancingProxy::Backend
|
34
|
+
def self.list
|
35
|
+
@list ||= [
|
36
|
+
{:url => "http://127.0.0.1:3000"},
|
37
|
+
{:url => "http://127.0.0.2:3000"},
|
38
|
+
{:url => "http://127.0.0.3:3000"}
|
39
|
+
].map { |backend| new backend }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
srand(0)
|
44
|
+
BalancingProxy::Backend.select(:random).host.should == '127.0.0.1'
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
context "when using the 'roundrobin' strategy" do
|
50
|
+
it "should select backends in rotating order" do
|
51
|
+
class BalancingProxy::Backend
|
52
|
+
def self.list
|
53
|
+
@list ||= [
|
54
|
+
{:url => "http://127.0.0.1:3000"},
|
55
|
+
{:url => "http://127.0.0.2:3000"},
|
56
|
+
{:url => "http://127.0.0.3:3000"}
|
57
|
+
].map { |backend| new backend }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
BalancingProxy::Backend.select(:roundrobin).host.should == '127.0.0.1'
|
62
|
+
BalancingProxy::Backend.select(:roundrobin).host.should == '127.0.0.2'
|
63
|
+
BalancingProxy::Backend.select(:roundrobin).host.should == '127.0.0.3'
|
64
|
+
BalancingProxy::Backend.select(:roundrobin).host.should == '127.0.0.1'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context "when using the 'balanced' strategy" do
|
69
|
+
|
70
|
+
it "should select the first backend when all backends have the same load" do
|
71
|
+
class BalancingProxy::Backend
|
72
|
+
def self.list
|
73
|
+
@list ||= [
|
74
|
+
{:url => "http://127.0.0.3:3000", :load => 0},
|
75
|
+
{:url => "http://127.0.0.2:3000", :load => 0},
|
76
|
+
{:url => "http://127.0.0.1:3000", :load => 0}
|
77
|
+
].map { |backend| new backend }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
BalancingProxy::Backend.select.host.should == '127.0.0.3'
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should select the least loaded backend" do
|
85
|
+
class BalancingProxy::Backend
|
86
|
+
def self.list
|
87
|
+
@list ||= [
|
88
|
+
{:url => "http://127.0.0.3:3000", :load => 2},
|
89
|
+
{:url => "http://127.0.0.2:3000", :load => 1},
|
90
|
+
{:url => "http://127.0.0.1:3000", :load => 0}
|
91
|
+
].map { |backend| new backend }
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
BalancingProxy::Backend.select.host.should == '127.0.0.1'
|
96
|
+
BalancingProxy::Backend.select.host.should == '127.0.0.1'
|
97
|
+
BalancingProxy::Backend.select.host.should == '127.0.0.2'
|
98
|
+
BalancingProxy::Backend.select.host.should == '127.0.0.3'
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
data/spec/helper.rb
CHANGED
data/spec/proxy_spec.rb
CHANGED
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
8
|
+
- 5
|
9
|
+
version: 0.1.5
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Ilya Grigorik
|
@@ -14,12 +14,11 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date:
|
17
|
+
date: 2011-01-16 00:00:00 -05:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: eventmachine
|
22
|
-
prerelease: false
|
23
22
|
requirement: &id001 !ruby/object:Gem::Requirement
|
24
23
|
none: false
|
25
24
|
requirements:
|
@@ -27,25 +26,70 @@ dependencies:
|
|
27
26
|
- !ruby/object:Gem::Version
|
28
27
|
segments:
|
29
28
|
- 0
|
30
|
-
|
31
|
-
- 9
|
32
|
-
version: 0.12.9
|
29
|
+
version: "0"
|
33
30
|
type: :runtime
|
31
|
+
prerelease: false
|
34
32
|
version_requirements: *id001
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: rspec
|
35
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
36
|
+
none: false
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
segments:
|
41
|
+
- 0
|
42
|
+
version: "0"
|
43
|
+
type: :development
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: *id002
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: em-http-request
|
48
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
segments:
|
54
|
+
- 0
|
55
|
+
version: "0"
|
56
|
+
type: :development
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: *id003
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: ansi
|
61
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
segments:
|
67
|
+
- 0
|
68
|
+
version: "0"
|
69
|
+
type: :development
|
70
|
+
prerelease: false
|
71
|
+
version_requirements: *id004
|
35
72
|
description: EventMachine Proxy DSL
|
36
|
-
email:
|
37
|
-
|
38
|
-
|
73
|
+
email:
|
74
|
+
- ilya@igvita.com
|
75
|
+
executables:
|
76
|
+
- em-proxy
|
39
77
|
extensions: []
|
40
78
|
|
41
|
-
extra_rdoc_files:
|
42
|
-
|
79
|
+
extra_rdoc_files: []
|
80
|
+
|
43
81
|
files:
|
82
|
+
- .gitignore
|
83
|
+
- .rspec
|
84
|
+
- Gemfile
|
85
|
+
- Gemfile.lock
|
44
86
|
- README.rdoc
|
45
87
|
- Rakefile
|
46
|
-
-
|
88
|
+
- bin/em-proxy
|
47
89
|
- em-proxy.gemspec
|
48
90
|
- examples/appserver.rb
|
91
|
+
- examples/balancing-client.rb
|
92
|
+
- examples/balancing.rb
|
49
93
|
- examples/beanstalkd_interceptor.rb
|
50
94
|
- examples/duplex.rb
|
51
95
|
- examples/line_interceptor.rb
|
@@ -60,6 +104,7 @@ files:
|
|
60
104
|
- lib/em-proxy/backend.rb
|
61
105
|
- lib/em-proxy/connection.rb
|
62
106
|
- lib/em-proxy/proxy.rb
|
107
|
+
- spec/balancing_spec.rb
|
63
108
|
- spec/helper.rb
|
64
109
|
- spec/proxy_spec.rb
|
65
110
|
has_rdoc: true
|
@@ -67,8 +112,8 @@ homepage: http://github.com/igrigorik/em-proxy
|
|
67
112
|
licenses: []
|
68
113
|
|
69
114
|
post_install_message:
|
70
|
-
rdoc_options:
|
71
|
-
|
115
|
+
rdoc_options: []
|
116
|
+
|
72
117
|
require_paths:
|
73
118
|
- lib
|
74
119
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -76,6 +121,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
76
121
|
requirements:
|
77
122
|
- - ">="
|
78
123
|
- !ruby/object:Gem::Version
|
124
|
+
hash: -2051780992673318158
|
79
125
|
segments:
|
80
126
|
- 0
|
81
127
|
version: "0"
|
@@ -84,6 +130,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
84
130
|
requirements:
|
85
131
|
- - ">="
|
86
132
|
- !ruby/object:Gem::Version
|
133
|
+
hash: -2051780992673318158
|
87
134
|
segments:
|
88
135
|
- 0
|
89
136
|
version: "0"
|
@@ -95,16 +142,6 @@ signing_key:
|
|
95
142
|
specification_version: 3
|
96
143
|
summary: EventMachine Proxy DSL
|
97
144
|
test_files:
|
145
|
+
- spec/balancing_spec.rb
|
98
146
|
- spec/helper.rb
|
99
147
|
- spec/proxy_spec.rb
|
100
|
-
- examples/appserver.rb
|
101
|
-
- examples/beanstalkd_interceptor.rb
|
102
|
-
- examples/duplex.rb
|
103
|
-
- examples/line_interceptor.rb
|
104
|
-
- examples/port_forward.rb
|
105
|
-
- examples/relay_port_forward.rb
|
106
|
-
- examples/schemaless-mysql/mysql_interceptor.rb
|
107
|
-
- examples/selective_forward.rb
|
108
|
-
- examples/simple.rb
|
109
|
-
- examples/smtp_spam_filter.rb
|
110
|
-
- examples/smtp_whitelist.rb
|
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
0.1.4
|