Subject: Re: Post before acking settings?

From: Jesse Wilson <[email-masked]>
Date: Sun, 08 May 2016 14:55:34 +0000

Thanks everyone for your advice on this. The nginx devs are planning to
make their server faster by introducing a preread buffer. Yay! And I’m
going to fix OkHttp to implement transparent recovery from REFUSED_STREAM
responses that don’t have a preceding GOAWAY. Also yay!

So I’m digging into REFUSED_STREAM. The spec doesn’t offer specific advice
for how clients should recover from REFUSED_STREAM responses. I can think
of a few different policies:

   1. Recover immediately on the same connection. (Seems like the
   definition of insanity?)
   2. Recover immediately on a different connection. But leave the refusing
   connection in the pool and eligible for new streams.
   3. Recover immediately on a different connection. Also take the refusing
   connection out of the pool so that it will not be used for new streams.

Seems like 3 is most in the spirit of the spec. But only option 1 can
recover from my nginx problem. Which means we’re going to implement a
heuristic like *“if the refused streamId is 1 then retry on the same
connection, otherwise retry on another connection”*. Sigh.
​

On Thu, Apr 28, 2016 at 4:00 AM Martin Thomson <[email-masked]>
wrote:

> On 28 April 2016 at 11:46, Jesse Wilson <[email-masked]> wrote:
> > As I understand this, nginx sets the default window size to 0 for all
> > streams. The flow control window isn’t expanded from 0 until nginx finds
> a
> > module to accept the request. In terms of round trips this seems like a
> > regression from HTTP/1.1:
>
> Yes, think of this as equivalent to forcing 100-continue on every
> request.  That has the effect of discouraging requests with bodies for
> performance reasons.
>
> This is definitely unfortunate from the perspective of performance,
> but it's an understandable position.  What a server is _expected_ to
> do is buffer up to the connection-level flow control window.
>
> However, it might be that 64k per connection (plus request header
> fields) is too much for some servers and RST_STREAM is the only
> option.  I would hope that only constrained devices do that, but - as
> Roberto is fond of pointing out - servers are effectively constrained
> devices.
>
> A better solution all around would be to set a small connection-level
> flow control window and to allow that much data to be buffered.  That
> would allow requests that fit into that window to avoid the round trip
> tax.
>
> (For the galleries, the SETTINGS ack thing was a red herring, nginx
> rejects requests with bodies.  Which of course you won't send once the
> SETTINGS are applied.)
>

---

From: Martin Thomson <[email-masked]>
Date: Mon, 9 May 2016 10:00:59 +1000

On 9 May 2016 at 00:55, Jesse Wilson <[email-masked]> wrote:
> Recover immediately on the same connection. (Seems like the definition of
> insanity?)

This is not necessarily the case.  Often, as is with the nginx case,
REFUSED_STREAM is highly transitory.  All that it takes is a round
trip, after which you have their settings updated and you know not to
violate their [maximum concurrent streams, flow control window,
etc...].  I would try on the same connection at least once.

Making new connections runs counter to the spirit of h2.  We want a
single connection that is good for everything.  I would retry exactly
once and then consider the request a lost cause.