Subject: Zero weight for 100 CONTINUE, instead of flow control

From: David Krauss <[email-masked]>
Date: Wed, 2 Apr 2014 03:18:45 +0800

>> #436 Enable weight of 0.
>> 
>> Not a lot of feedback here.  Potentially disruptive.
> 
> … and unless we see discussion on the list very soon, it’s not going to make it into this implementation draft.

Oh, I didn’t know of the issue, but I was just going to ask about this!

It’s a better replacement for 100 CONTINUE than hacking flow control. (See my previous message, "Flow control protocol redundancy.”)

Sending a POST with a weight of 0 may notify a server that the sender is unsure whether to proceed. This matches the client-initiated semantic of waiting for CONTINUE.

The disruption can be quite minimal, because a zero-weight condition need not be persistent. Say that an endpoint receiving a zero weight must respond with either a PRIORITY or a RST_STREAM.

Unlike CONTINUE, this does not contort the protocol and rely on specific header processing. Default behavior to always resume the stream (for servers) or discontinue it (for clients) is reasonable for any ignorant application-level software.

I really don’t like the idea of using flow control to force the other end to stop. It does not offer appropriate guarantees, it relies on default settings, and it’s a violation of network layering principles. Just as CONTINUE is too high-level for what it’s supposed to do, flow control is too low-level.

---

From: Mike Bishop <[email-masked]>
Date: Wed, 2 Apr 2014 20:52:20 +0000

I get the zero-weighted bulk download or video stream, where the client is basically saying that anything else it requests over the connection is more important.

That feels like an odd semantic, though -- the weight of the group implies the client's suggestion to the server on how to prioritize resources.  Overloading it to also, in this instance, reflect the client's wish to know the server's suggestion for how *it* should allocate resources seems a little odd.

Unless we're, in general, supporting that the server can send PRIORITY frames to the client to suggest how the client prioritize its uploads?  I hope not, but maybe I missed that discussion.

-----Original Message-----
From: David Krauss [mailto:[email-masked]] 
Sent: Tuesday, April 1, 2014 12:19 PM
To: HTTP Working Group
Subject: Zero weight for 100 CONTINUE, instead of flow control

> ... and unless we see discussion on the list very soon, it's not going to make it into this implementation draft.

Oh, I didn't know of the issue, but I was just going to ask about this!

It's a better replacement for 100 CONTINUE than hacking flow control. (See my previous message, "Flow control protocol redundancy.")

I really don't like the idea of using flow control to force the other end to stop. It does not offer appropriate guarantees, it relies on default settings, and it's a violation of network layering principles. Just as CONTINUE is too high-level for what it's supposed to do, flow control is too low-level.

---

From: David Morris <[email-masked]>
Date: Wed, 2 Apr 2014 14:16:14 -0700 (PDT)

I'm also wondering how useful this would be in practice considering
that a user driven client could be loading viewing totally unrelated
sites son the zero weight transfer from site A would frequently still
flood the end user's network connection and conflict with use of site B.

I worked on a product a few years ago that was intended to improve the
user experience by giving priority to time critical transfers such as
VOIP. This product was to run in the end user's computer. The
fundamental flaw in the approach was that it had no view of the actual
traffic on the connection between the local network, shared by other
computers, an the network.

So I suspect such a feature wouldn't do much in general to improve
the user experience. Probably better would be a mechanism that allowed
the recipient to pace the transfer based on a bytes per second target.
At least some of the major video sites do this now to avoid sending
content the user will click away from in seconds.

On Wed, 2 Apr 2014, Mike Bishop wrote:

> I get the zero-weighted bulk download or video stream, where the client
> is basically saying that anything else it requests over the connection
> is more important.
>
> That feels like an odd semantic, though -- the weight of the group
> implies the client's suggestion to the server on how to prioritize
> resources.  Overloading it to also, in this instance, reflect the
> client's wish to know the server's suggestion for how *it* should
> allocate resources seems a little odd.
>
> Unless we're, in general, supporting that the server can send PRIORITY
> frames to the client to suggest how the client prioritize its uploads?
> I hope not, but maybe I missed that discussion.
>

---

From: Martin Thomson <[email-masked]>
Date: Wed, 2 Apr 2014 14:18:41 -0700

> Unless we're, in general, supporting that the server can send PRIORITY frames to the client to suggest how the client prioritize its uploads?  I hope not, but maybe I missed that discussion.

Me too.  And that would be contrary to what is written.  If the server
were to send PRIORITY, it would be to make a request of the client
regarding resource allocation at the client.  Which, for HTTP/2, is
pretty much pointless.

100 Continue is addressed perfectly well by setting the initial stream
flow control window to zero and using WINDOW_UPDATE to open the pipe.
Either requires a round trip, but weight changing has other
(side-)effects.

---

From: David Krauss <[email-masked]>
Date: Thu, 3 Apr 2014 13:26:34 +0800

> regarding resource allocation at the client.  Which, for HTTP/2, is

The PRIORITY frame is specifically allowed in the half closed (remote) state, which corresponds to prioritization by the sender. Nothing currently disallows reprioritization by a server. The spec as currently written doesn’t differentiate at all between client and server.

As far as I can see, priority is a property of the stream applying to both endpoints, and anyone can set it.

In the CONTINUE case, the client would only really care whether the response is RST_STREAM or something else.

It is not reasonable to either require clients to weight uploads (client libraries are likely to often be simplistic), nor to require PRIORITY frames from the server to be meaningless. More sophisticated libraries will handle client and server stream multiplexing the same way. And, do not underestimate the variety of applications. HTTP/2, being more compact, is attractive for M2M communication and data acquisition, where clients might be data producers rather than consumers, yet have tight resource constraints.

It comes down to quality of implementation. Some things may be left unimplemented because they are meaningless for an application. The protocol is designed to be tolerant in any case, and a client must expect to see uselessly imprecise weighting in practice.

> Either requires a round trip, but weight changing has other

When the client makes a request before receiving the initial SETTINGS, the flow control windows are still initially set to 64 KiB. If the server refuses to accept anything but sends a zero-windowed SETTINGS in response, then the client will likely end up filling all the intermediate buffers at 64 KiB *per hop*, including the server itself, before it receives those settings.

As long as those buffers contain the unwanted data, it subtracts from the connection flow control window. Only the back-propagating RST_STREAM notifies forwarders to free resources again.

Zeroing the flow control window for all streams adds a round trip as latency for all streams, not only the ones that need a CONTINUE.

Weight changing need not have any side effects at all. I’ve only proposed a transient condition. The client is free to set a new priority after the server sends a PRIORITY. It remains likely meaningless until the server starts sending data.

Flow control based throttling is the methodology with side effects. If it were well-behaved, we’d just throttle everything from the client side and never bother with priorities in the first place!

---

From: David Krauss <[email-masked]>
Date: Thu, 3 Apr 2014 14:06:04 +0800

> content the user will click away from in seconds.

This is an issue with weighting in general, not my particular CONTINUE proposal. (Your response seems to be in relation to Herve’s proposal, though, since mine does not allow a stream to remain at zero weight.)

Any reasonably rich site today is loaded from several CDNs in addition to actual page’s origin. So, I rather doubt that prioritization will have much user-experience effect at all except in the case of opening background tabs from the same site while the foreground tab is still loading something.

The problem with hard, bytes-per-second data flow targets is implementation difficulty. The speed metadata originally inherited from SPDY was dropped. Implementation difficulty might not be a showstopper though, but only an indication that such a feature should be optional as indicated by SETTINGS.

---

From: Tatsuhiro Tsujikawa <[email-masked]>
Date: Thu, 3 Apr 2014 15:16:51 +0900

On Thu, Apr 3, 2014 at 2:26 PM, David Krauss <[email-masked]> wrote:

>
> On 2014-04-03, at 5:18 AM, Martin Thomson <[email-masked]>
> wrote:
>
> frames to the client to suggest how the client prioritize its uploads?  I
> hope not, but maybe I missed that discussion.
> >
> The PRIORITY frame is specifically allowed in the half closed (remote)
> state, which corresponds to prioritization by the sender. Nothing currently
> disallows reprioritization by a server. The spec as currently written
> doesn't differentiate at all between client and server.
>
And anyone can ignore priority in HEADERS and PRIORITY.

Both endpoints MUST support flow control and breakage leads to the
connection error.
On the other hand, PRIORITY mechanism is completely optional feature of the
protocol.
Simple implementation may just omit to implement it
Therefore, only flow control can do the better job which expect header did
previously.
Of course, you can propose a text or two to make PRIORITY mandatory and
which part.

Best regards,
Tatsuhiro Tsujikawa

> In the CONTINUE case, the client would only really care whether the
> response is RST_STREAM or something else.
>
> It is not reasonable to either require clients to weight uploads (client
> libraries are likely to often be simplistic), nor to require PRIORITY
> frames from the server to be meaningless. More sophisticated libraries will
> handle client and server stream multiplexing the same way. And, do not
> underestimate the variety of applications. HTTP/2, being more compact, is
> attractive for M2M communication and data acquisition, where clients might
> be data producers rather than consumers, yet have tight resource
> constraints.
>
> It comes down to quality of implementation. Some things may be left
> unimplemented because they are meaningless for an application. The protocol
> is designed to be tolerant in any case, and a client must expect to see
> uselessly imprecise weighting in practice.
>
> When the client makes a request before receiving the initial SETTINGS, the
> flow control windows are still initially set to 64 KiB. If the server
> refuses to accept anything but sends a zero-windowed SETTINGS in response,
> then the client will likely end up filling all the intermediate buffers at
> 64 KiB *per hop*, including the server itself, before it receives those
> settings.
>
> As long as those buffers contain the unwanted data, it subtracts from the
> connection flow control window. Only the back-propagating RST_STREAM
> notifies forwarders to free resources again.
>
> Zeroing the flow control window for all streams adds a round trip as
> latency for all streams, not only the ones that need a CONTINUE.
>
> Weight changing need not have any side effects at all. I've only proposed
> a transient condition. The client is free to set a new priority after the
> server sends a PRIORITY. It remains likely meaningless until the server
> starts sending data.
>
> Flow control based throttling is the methodology with side effects. If it
> were well-behaved, we'd just throttle everything from the client side and
> never bother with priorities in the first place!
>
>
>

---

From: David Krauss <[email-masked]>
Date: Thu, 3 Apr 2014 15:13:08 +0800

> And anyone can ignore priority in HEADERS and PRIORITY.

Correct.

> Both endpoints MUST support flow control and breakage leads to the connection error.
> On the other hand, PRIORITY mechanism is completely optional feature of the protocol.
> Therefore, only flow control can do the better job which expect header did previously.

EXPECT is client-initiated. It’s only mandatory for the server. Flow control throttling is server-initiated and mandatory for the client, who is kept blind.

To roughly emulate CONTINUE behavior, the client may wait for the initial settings frame to set the initial window properly. It may wait for a possible RST_STREAM before beginning the request body. It may wait for receipt of the first data frame before transmitting a second frame, but that would be a poor strategy because receipts don’t come from the origin server. Any of this behavior has no particular support in the protocol, may be hard to express properly by the application, and reduces performance.

Whereas EXPECT allows a client to defer a particular upload entirely, flow control throttling will result in a partial upload, unless one of the aforementioned tricks is employed. (Actually, only unless the client uses a timeout to wait for RST_STREAM.)

A PRIORITY handshake allows the client to check before uploading anything, as with EXPECT. Or it can preemptively send something, or query at any time whether the server wants more data.

Come to think of it, there is a strong UX argument for doing this with priorities and not something else. When uploading a photo album, Facebook provides live previews. Server-specified priority would help the client upload files with complete previews appearing at the earliest opportunity, yet allowing some number of actual servers to be represented by a single origin. (I have not verified that Facebook in fact uses more than one connection; it could just be a painted-on effect.)

>   Of course, you can propose a text or two to make PRIORITY mandatory and which part.

I suggested that a frame with PRIORITY_GROUP and zero weight must elicit either a response PRIORITY or a RST_STREAM; in fact that is the entirety of my proposal. The difference the weight domain 0..255 or 1..256 is actually immaterial since a stream is not allowed to be weighted at zero.

Detecting such a PRIORITY and generating a reflexive response should add little complexity to any implementation.

---

From: Martin Thomson <[email-masked]>
Date: Thu, 3 Apr 2014 09:52:59 -0700

David,

You seem to want something that a client sets in order to determine
the policies a client follows when sending data.

That doesn't need any protocol.  Maybe your stack needs an API hook for that.

[More responses inline.]

On 2 April 2014 22:26, David Krauss <[email-masked]> wrote:
> The PRIORITY frame is specifically allowed in the half closed (remote) state,

Correct.

> [...] which corresponds to prioritization by the sender.

...actually, this corresponds to prioritization by the *receiver*.

> Nothing currently disallows reprioritization by a server.  The spec as currently written doesn’t differentiate at all between client and server.

Technically correct.

> As far as I can see, priority is a property of the stream applying to both endpoints, and anyone can set it.

That's not quite right.  PRIORITY expresses the expectations of the
endpoint sending the PRIORITY frame about how the endpoint receiving
the PRIORITY frame should behave.

The PRIORITY frame does not provide a way to signal the intent of the
sending endpoint.

> It is not reasonable to either require clients to weight uploads (client libraries are likely to often be simplistic), nor to require PRIORITY frames from the server to be meaningless.

I believe it to be perfectly reasonable to have clients weight
uploads, otherwise we lose much of the advantages of a multiplexed,
concurrent protocol.  However, since the client is probably the one
most aware of the relative priority of streams, having an indication
from the server isn't usually of much use.  Clients will most likely
be able to weight streams on their own, without any signals in the
protocol itself.

> When the client makes a request before receiving the initial SETTINGS, the flow control windows are still initially set to 64 KiB. If the server refuses to accept anything but sends a zero-windowed…

This is one aspect of a well-known and thoroughly discussed issue (see
https://github.com/http2/http2-spec/issues/184).  We decided to do
nothing about this, instead requiring that servers handle clients
exercising default settings gracefully.   That means RST_STREAM if the
server can't handle unwanted streams or data.

If you are concerned about bytes in transit that aren't wanted, it's
actually worse than you have stated, because intermediaries can accept
and buffer more data.  Because, yes, flow control is hop-by-hop.  And
intermediaries are likely unaware of the context in which a request is
made.  Even if the server has an initial window of 0, that doesn't
mean intermediaries will follow suit.  Quite to the contrary.  But I
don't consider that to be an issue.

> As long as those buffers contain the unwanted data, it subtracts from the connection flow control window. Only the back-propagating RST_STREAM notifies forwarders to free resources again.

As I said, I don't consider this to be an issue.  This optimizes for
less latency in the case where the server wants to start accepting
data.  Rather than requiring a full end-to-end round trip, it only
requires a round trip on each affected (i.e., stalled) hop.  That
might result in and end-to-end delay if all hops are stalled, but that
will depend on the buffering policies of intermediaries.

To me, that's a description of a functioning flow control system.  I
don't see a problem there.