Skip to content

RFC: Pool improvements

Julien Viet edited this page Jan 18, 2021 · 6 revisions

Introduction

Vert.x requires to use a pool for clients.

Vert.x uses several pool implementations

  • HTTP client pool: the most complete pool which was written a few years ago. This pool is also used by the Redis client.
  • SQL client pool: a simple pool
  • Mail client pool: a pool that was written a long time ago

The HTTP client pool has a few limitations that we need to circumvent:

  • currently coupled to an event-loop, this is fine currently but it prevents the pool to use for a shared pool (e.g createSharedHttpClient(...)
  • no timeout acquisition

Goals

  • The pool can use multiple event loops (the current pool uses a single event loop)
  • The client can specify an event loop to use and the pool should do a best effort to use it but does not have to
  • The pool can handle connections with a configurable concurrency, i.e the same connection can be borrowed multiple times from the pool
  • Acquisition timeout
  • SQL pool and Mail client pool reuse the pool

Non goals

Not identified for now

Design

Connection weight

Unlike traditional pools, the pool does not assume that all connections are equals.

The main use case is creating a pool of HTTP/2 and HTTP/1 connections with mixed concurrency characteristics. A client that wants to establish and HTTP/2 connections to a server does not have the guarantee that the server supports this protocol: it will receive a response from the server whether the protocol will be HTTP/2 or HTTP/1 once the connection is created. Connection weight allows the client to establish an HTTP/2 connection and fallback to a HTTP/1 connection.

The pool assigns each connection a weight, used to determine the maximum number of connections it can create. When a connection is created the initial weight is reserved and when the connection is established the weight can be corrected.

HTTP connection weight

An HTTP client defines a different maximum values for HTTP/1 and HTTP/2, the pool max weight being the product of the HTTP/1 and HTTP/2 weights.

  • when the client creates a connection it provides the weight of the other protocols it wants to creates
  • when the client establish the connection it provides the weight of the other protocol that was actually created

The pool can only create a connection when the sum of all connection weight is lesser than the max weight.

Example with HTTP/1 max pool size = 5 and HTTP/2 max pool size = 1:

  • client connects to create an HTTP/2 connection, weight => 0
  • server establishes an HTTP/2 connections

When the server downgrades to HTTP/1:

  • client connects to create an HTTP/2 connection, weight => 0
  • server establishes an HTTP/2 connections, weight => 1
  • client connects to create an HTTP/2 connection, weight => 6
  • server establishes an HTTP/2 connections, weight => 2
  • ...

Connection capacity

In addition of weight, each connection maintains a capacity which is the number of times it can be borrowed from the pool.

This is used by connections that supports pipelining and multiplexing.

  • an HTTP/1 connection with a pipelining limit can define this value as connection capacity
  • an HTTP/2 connection uses the connection max concurrency as connection capacity

Implementation

WIP https://github.com/eclipse-vertx/vert.x/pull/3731

Resources

A few useful resources to read that impact this effort:

Clone this wiki locally