-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Instead of giving each client connection an upstream connection, each client channel is given an upstream channel upon request, which means that multiple client connections can share a single upstream connection, massivly reducing resources required of the upstream server.
- Loading branch information
1 parent
40cc76d
commit 54fdfd3
Showing
15 changed files
with
559 additions
and
420 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
Excluded: | ||
- test/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,3 +9,4 @@ | |
*.tar.gz | ||
*.swp | ||
/builds/ | ||
shard.override.yml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
name: amqproxy | ||
version: 1.0.0 | ||
version: 2.0.0 | ||
|
||
authors: | ||
- CloudAMQP <[email protected]> | ||
|
@@ -11,8 +11,6 @@ targets: | |
dependencies: | ||
amq-protocol: | ||
github: cloudamqp/amq-protocol.cr | ||
logger: | ||
github: 84codes/logger.cr | ||
|
||
development_dependencies: | ||
amqp-client: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
require "openssl" | ||
require "log" | ||
require "./records" | ||
require "./upstream" | ||
|
||
module AMQProxy | ||
class ChannelPool | ||
Log = ::Log.for(self) | ||
@lock = Mutex.new | ||
@upstreams = Deque(Upstream).new | ||
|
||
def initialize(@host : String, @port : Int32, @tls_ctx : OpenSSL::SSL::Context::Client?, @credentials : Credentials, @idle_connection_timeout : Int32) | ||
spawn shrink_pool_loop, name: "shrink pool loop" | ||
end | ||
|
||
def get(downstream_channel : DownstreamChannel) : UpstreamChannel | ||
at_channel_max = 0 | ||
@lock.synchronize do | ||
loop do | ||
if upstream = @upstreams.shift? | ||
next if upstream.closed? | ||
begin | ||
upstream_channel = upstream.open_channel_for(downstream_channel) | ||
@upstreams.unshift(upstream) | ||
return upstream_channel | ||
rescue Upstream::ChannelMaxReached | ||
@upstreams.push(upstream) | ||
at_channel_max += 1 | ||
add_upstream if at_channel_max == @upstreams.size | ||
end | ||
else | ||
add_upstream | ||
end | ||
end | ||
end | ||
end | ||
|
||
private def add_upstream | ||
upstream = Upstream.new(@host, @port, @tls_ctx, @credentials) | ||
Log.info { "Adding upstream connection" } | ||
@upstreams.unshift upstream | ||
rescue ex : IO::Error | ||
raise Upstream::Error.new ex.message, cause: ex | ||
end | ||
|
||
def connections | ||
@upstreams.size | ||
end | ||
|
||
def close | ||
Log.info { "Closing all upstream connections" } | ||
@lock.synchronize do | ||
while u = @upstreams.shift? | ||
begin | ||
u.close "AMQProxy shutdown" | ||
rescue ex | ||
Log.error { "Problem closing upstream: #{ex.inspect}" } | ||
end | ||
end | ||
end | ||
end | ||
|
||
private def shrink_pool_loop | ||
loop do | ||
sleep @idle_connection_timeout.seconds | ||
@lock.synchronize do | ||
(@upstreams.size - 1).times do # leave at least one connection | ||
u = @upstreams.pop | ||
if u.active_channels.zero? | ||
begin | ||
u.close "Pooled connection closed due to inactivity" | ||
rescue ex | ||
Log.error { "Problem closing upstream: #{ex.inspect}" } | ||
end | ||
elsif u.closed? | ||
Log.error { "Removing closed upstream connection from pool" } | ||
else | ||
@upstreams.unshift u | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.