Connection reuse for HTTP/2?

2019-09-17 Thread David Pirotte
Hi all,

Is there a way to multiplex frontend HTTP/2 (GRPC) connections onto a shared 
pool of backend HTTP/2 connections?

My testing shows that one frontend connection with multiple concurrent requests 
will reuse one backend connection, but multiple frontend connections will not 
share backend connections.

Cheers,
Dave


Re: [PATCH] BUG/MINOR: mux-h1: Correctly report Ti timer when HTX and keepalives are used

2019-07-12 Thread David Pirotte
Sure thing, Christopher. Patch is attached. Thanks!

Cheers,
Dave

On Fri, Jul 12, 2019 at 5:00 AM Christopher Faulet 
wrote:

> Le 10/07/2019 à 17:58, David Pirotte a écrit :
> > Instructions to reproduce are below.
> >
> > When HTTP keepalives are used in conjunction with HTX, the Ti timer
> reports the
> > elapsed time since the beginning of the connection instead of the end of
> the
> > previous request as stated in the documentation. Tq and Tt also report
> > incorrectly as a result.
> >
> > So, when creating a new h1s, check if it is the first request on
> the connection.
> > If not, set the session create times to the current timestamp rather
> than the
> > initial session accept timestamp. This makes the logged timers behave as
> stated
> > in the documentation.
> >
> > I hope this is useful, and feedback is welcome if there is a more
> correct
> > strategy. Thanks!
> >
> Hi Dave,
>
> Thanks ! Of course it is useful. However, your patch was mangled by your
> mailer.
> Could you please resend it as an attachment or using the command "git
> send-email" ?
>
> --
> Christopher Faulet
>


0001-BUG-MINOR-mux-h1-Correctly-report-Ti-timer-when-HTX-.patch
Description: Binary data


[PATCH] BUG/MINOR: mux-h1: Correctly report Ti timer when HTX and keepalives are used

2019-07-10 Thread David Pirotte
Instructions to reproduce are below.

When HTTP keepalives are used in conjunction with HTX, the Ti timer reports
the elapsed time since the beginning of the connection instead of the end
of the previous request as stated in the documentation. Tq and Tt also
report incorrectly as a result.

So, when creating a new h1s, check if it is the first request on
the connection. If not, set the session create times to the
current timestamp rather than the initial session accept timestamp. This
makes the logged timers behave as stated in the documentation.

I hope this is useful, and feedback is welcome if there is a more correct
strategy. Thanks!

Cheers,
Dave

To reproduce, start up haproxy >= 1.9.0 with this configuration:
```
  global
log stdout format raw local0

  defaults
mode http
timeout connect 2s
timeout client 2s
timeout server 2s
log global
log-format "%ci:%cp [%tr] %ft Th:%Th Ti:%Ti TR:%TR Tw:%Tw Tc:%Tc Tr:%Tr
Td:%Td Tq:%Tq Tt:%Tt Ta:%Ta"

  listen htx
bind :10080
option http-use-htx
server app localhost:8080 # endpoint that sleeps for 1000ms and returns
200 OK

  listen nohtx
bind :10081
no option http-use-htx
server app localhost:8080 # endpoint that sleeps for 1000ms and returns
200 OK
```

...and then make some keepalive requests with something like Apache Bench
and note that Ti (and Tq/Tt) are counting from the initial connection:
```
127.0.0.1:33716 [10/Jul/2019:02:18:18.984] htx Th:0 *Ti:0* TR:0 Tw:0 Tc:0
Tr:1000 Td:0 Tq:0 Tt:1000 Ta:1000
127.0.0.1:33716 [10/Jul/2019:02:18:19.984] htx Th:0 *Ti:1000* TR:0 Tw:0
Tc:0 Tr:1000 Td:0 Tq:1000 Tt:2000 Ta:1000
127.0.0.1:33716 [10/Jul/2019:02:18:20.984] htx Th:0 *Ti:2000* TR:0 Tw:0
Tc:0 Tr:1001 Td:0 Tq:2000 Tt:3001 Ta:1001
127.0.0.1:53264 [10/Jul/2019:02:18:21.989] nohtx Th:0 Ti:0 TR:0 Tw:0 Tc:0
Tr:1000 Td:0 Tq:0 Tt:1000 Ta:1000
127.0.0.1:53264 [10/Jul/2019:02:18:22.989] nohtx Th:0 Ti:0 TR:0 Tw:0 Tc:0
Tr:1000 Td:0 Tq:0 Tt:1000 Ta:1000
127.0.0.1:53264 [10/Jul/2019:02:18:23.989] nohtx Th:0 Ti:0 TR:0 Tw:0 Tc:0
Tr:1000 Td:0 Tq:0 Tt:1000 Ta:1000
```

After applying this patch to master/2.1-dev and re-running Apache Bench
test, the logs look as you would expect:

```
# Same ab command w/ the patch.
127.0.0.1:35860 [10/Jul/2019:05:43:59.858] HTTP/1.0 htx Th:0 *Ti:0* TR:0
Tw:0 Tc:0 Tr:1000 Td:0 Tq:0 Tt:1000 Ta:1000
127.0.0.1:35860 [10/Jul/2019:05:44:00.859] HTTP/1.0 htx Th:0 *Ti:0* TR:0
Tw:0 Tc:0 Tr:1000 Td:0 Tq:0 Tt:1000 Ta:1000
127.0.0.1:35860 [10/Jul/2019:05:44:01.859] HTTP/1.0 htx Th:0 *Ti:0* TR:0
Tw:0 Tc:0 Tr:1000 Td:0 Tq:0 Tt:1000 Ta:1000
127.0.0.1:55408 [10/Jul/2019:05:44:02.863] HTTP/1.0 nohtx Th:0 Ti:0 TR:0
Tw:0 Tc:0 Tr:1000 Td:0 Tq:0 Tt:1000 Ta:1000
127.0.0.1:55408 [10/Jul/2019:05:44:03.864] HTTP/1.0 nohtx Th:0 Ti:0 TR:0
Tw:0 Tc:0 Tr:1000 Td:0 Tq:0 Tt:1000 Ta:1000
127.0.0.1:55408 [10/Jul/2019:05:44:04.864] HTTP/1.0 nohtx Th:0 Ti:0 TR:0
Tw:0 Tc:0 Tr:1001 Td:0 Tq:0 Tt:1001 Ta:1001

# And from a ruby script that adds 300ms of delay between requests on a
persistent connection
127.0.0.1:35870 [10/Jul/2019:05:44:45.323] HTTP/1.1 htx Th:0 *Ti:0* TR:0
Tw:0 Tc:0 Tr:1000 Td:0 Tq:0 Tt:1000 Ta:1000
127.0.0.1:35870 [10/Jul/2019:05:44:46.624] HTTP/1.1 htx Th:0 *Ti:301* TR:0
Tw:0 Tc:0 Tr:1001 Td:0 Tq:301 Tt:1302 Ta:1001
127.0.0.1:35870 [10/Jul/2019:05:44:47.927] HTTP/1.1 htx Th:0 *Ti:301* TR:0
Tw:0 Tc:0 Tr:1000 Td:0 Tq:301 Tt:1301 Ta:1000
127.0.0.1:55420 [10/Jul/2019:05:44:49.230] HTTP/1.1 nohtx Th:0 Ti:0 TR:0
Tw:0 Tc:0 Tr:1000 Td:0 Tq:0 Tt:1000 Ta:1000
127.0.0.1:55420 [10/Jul/2019:05:44:50.531] HTTP/1.1 nohtx Th:0 Ti:301 TR:0
Tw:0 Tc:0 Tr:1000 Td:0 Tq:301 Tt:1301 Ta:1000
127.0.0.1:55420 [10/Jul/2019:05:44:51.833] HTTP/1.1 nohtx Th:0 Ti:301 TR:0
Tw:0 Tc:0 Tr:1000 Td:0 Tq:301 Tt:1301 Ta:1000
```
---
 src/mux_h1.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/mux_h1.c b/src/mux_h1.c
index 8712d2a0..7309734a 100644
--- a/src/mux_h1.c
+++ b/src/mux_h1.c
@@ -306,8 +306,16 @@ static struct h1s *h1s_create(struct h1c *h1c, struct
conn_stream *cs, struct se
if (!sess)
sess = h1c->conn->owner;

-   h1s->csinfo.create_date = sess->accept_date;
-   h1s->csinfo.tv_create   = sess->tv_accept;
+   /* Timers for subsequent sessions on the same HTTP 1.x
connection
+* measure from `now`, not from the connection accept time
*/
+   if (h1s->flags & H1S_F_NOT_FIRST) {
+   h1s->csinfo.create_date = date;
+   h1s->csinfo.tv_create   = now;
+   }
+   else {
+   h1s->csinfo.create_date = sess->accept_date;
+   h1s->csinfo.tv_create   = sess->tv_accept;
+   }
h1s->csinfo.t_handshake = sess->t_handshake;
h1s->csinfo.t_idle  = -1;
}