Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stack VS Queue Flexibility #110

Closed
joshuasager opened this issue Nov 20, 2018 · 2 comments
Closed

Stack VS Queue Flexibility #110

joshuasager opened this issue Nov 20, 2018 · 2 comments

Comments

@joshuasager
Copy link

joshuasager commented Nov 20, 2018

Hey @mperham,

I am trying to leverage connection_pool in order to maintain a collection of open HTTPS connections.

The motivation for this is that I am trying to make repeated requests to an API server, however, re-negotiating SSL over the web on every request is quite slow.

Right now, I have the following implementation:
config/puma.rb

...

preload_app!

on_worker_boot do
  RequestPool.initialize_connections(thread_count)

  ActiveSupport.on_load(:active_record) do
    ActiveRecord::Base.establish_connection
  end
end

lib/request_pool.rb

require 'http'
require 'connection_pool'

# @note Each key maps to a single connection.
# @note To add a new URL to the connection pool, you must first add it to config/connections.yml
# @example Stores connections to multiple servers in a single hash.
#   RequestPool.new('https://www.google.ca').connection do |conn, ssl_context|
#       conn.get('/route', ssl_context: ssl_context)
#   end
class RequestPool
    @@conn = {}

    SSL_VERSION = :TLSv1_2
    SSL_CIPHERS = "ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:-LOW".freeze

    def self.initialize_connections(size)
        self.config.each do |url|
            @@conn[url] = ConnectionPool.new(size: size) { HTTP.persistent(url).timeout(:per_operation, connect: 10, read: 15) }
        end
    end

    def initialize(base_url)
        raise ArgumentError unless @@conn.has_key? base_url
        @base_url = base_url
    end

    # @note we call .to_s to ensure the respones gets flushed. 
    #   See https://github.com/httprb/http/wiki/Persistent-Connections-(keep-alive) for more details
    def connection
        @@conn[@base_url].with do |conn|
            response = yield conn, ssl_config
            response.to_s
            response
        end
    end

    private

    def self.config
        YAML.load_file("#{Rails.root}/config/connections.yml")[Rails.env]
            .values
    end

    def ssl_config
        OpenSSL::SSL::SSLContext.new.tap do |ctx|
            ctx.ssl_version = SSL_VERSION
            ctx.ciphers     = SSL_CIPHERS
        end
    end
end

If connection_pool were to have the option of using a Stack instead of a Queue, then, the HTTPS connections would be reused more frequently before going stale.

Would this be something that the gem would be willing to incorporate?

@mperham
Copy link
Owner

mperham commented Nov 20, 2018

I believe @drbrain did some refactoring to make connection_pool better for pooling persistent http connections. I would search the issues/PRs for his input.

@mperham mperham closed this as completed Dec 17, 2019
@drbrain
Copy link
Collaborator

drbrain commented Apr 29, 2020

net-http-persistent uses connection_pool to maintain persistent connections for HTTP requests including TLS requests. I think you're looking for TimedStackMulti in these files as ConnectionPool by default works with a homogenous connection pool while HTTP connections need a heterogenous connection pool.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants