Re: Stream State and PRIORITY Frames

Scott Mitchell <scott.k.mitch1@gmail.com> Fri, 20 January 2017 19:58 UTC

Return-Path: <ietf-http-wg-request+bounce-httpbisa-archive-bis2juki=lists.ie@listhub.w3.org>
X-Original-To: ietfarch-httpbisa-archive-bis2Juki@ietfa.amsl.com
Delivered-To: ietfarch-httpbisa-archive-bis2Juki@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 5AFED128BA2 for <ietfarch-httpbisa-archive-bis2Juki@ietfa.amsl.com>; Fri, 20 Jan 2017 11:58:34 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -9.699
X-Spam-Level:
X-Spam-Status: No, score=-9.699 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_HI=-5, RCVD_IN_SORBS_SPAM=0.5, RP_MATCHES_RCVD=-3.199, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=gmail.com
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id p2niZDlOKgGD for <ietfarch-httpbisa-archive-bis2Juki@ietfa.amsl.com>; Fri, 20 Jan 2017 11:58:32 -0800 (PST)
Received: from frink.w3.org (frink.w3.org [128.30.52.56]) (using TLSv1.2 with cipher DHE-RSA-AES128-SHA (128/128 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 67F131270B4 for <httpbisa-archive-bis2Juki@lists.ietf.org>; Fri, 20 Jan 2017 11:58:29 -0800 (PST)
Received: from lists by frink.w3.org with local (Exim 4.80) (envelope-from <ietf-http-wg-request@listhub.w3.org>) id 1cUfHY-0000ff-H5 for ietf-http-wg-dist@listhub.w3.org; Fri, 20 Jan 2017 19:55:32 +0000
Resent-Date: Fri, 20 Jan 2017 19:55:32 +0000
Resent-Message-Id: <E1cUfHY-0000ff-H5@frink.w3.org>
Received: from titan.w3.org ([128.30.52.76]) by frink.w3.org with esmtps (TLS1.2:RSA_AES_128_CBC_SHA1:128) (Exim 4.80) (envelope-from <scott.k.mitch1@gmail.com>) id 1cUfHT-0000eV-Bc for ietf-http-wg@listhub.w3.org; Fri, 20 Jan 2017 19:55:27 +0000
Received: from mail-lf0-f51.google.com ([209.85.215.51]) by titan.w3.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from <scott.k.mitch1@gmail.com>) id 1cUfHL-0001Vu-2F for ietf-http-wg@w3.org; Fri, 20 Jan 2017 19:55:22 +0000
Received: by mail-lf0-f51.google.com with SMTP id z134so64265257lff.3 for <ietf-http-wg@w3.org>; Fri, 20 Jan 2017 11:54:58 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=1bAjmCYYEtqr38exQoO9rPMrWEzXPRDUlaZ2UVGJ2JU=; b=KelnbsK/wGdlLz4XqqUiHXxtezwadUvZgmtlr5Rfh567ac04zaWHVI0blI9cpsOugC B1RvmKIHzQfOtoc0+PmVzidOK2ERHfk1fsPi9FpNMc95rQApraSBluQBJbaG14fyCzJU TmjlPAosP35S+iE4SlRCO0F2JHy2KK6OmqzNIi95zzvVEkVKjCxCoQFh9qnFlJjNMezu hLziFxvtspAKCgcLXG1xCFEVmmNvNufnya9lifAeThKlgnQBpZhLM1MhRkzyU5P170TQ YuC4uJq1Tp46BAzpbSoDFYMKSpoXIjbEMmkKyhmQuH2jnT86wt17Y4doE8NZMNf79ZpC d8Hg==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=1bAjmCYYEtqr38exQoO9rPMrWEzXPRDUlaZ2UVGJ2JU=; b=n5e+GLZxDjGo4FtoxTf08GP+w7VJI5uw/+fQORCuigKCb7GGxPsyyIHk608ISyNh51 hV2DzWkaXWDSJOaxGKhiOV1kZmaQaBLylL8w58JiP7si39SoV18vukG0aE+KK8xyIb5A fj6GK/BvAAfZ8hDYupmTqHQmEtoK93FRN3Wrt03gpqd3iNdHejVoN8fR+0+qgTJo8/Vg 39k62WQ+Oh8M4yIEzMjRtP8xIDPC6TEDzM8bIsGN2tr0aIBOTnUxNSulCPJ3Bb3zz9sa X6gbbFOut0G+y2YJveqPGIeJRwOQRyXMM/TZcpb5eSKbByezs159Fsq2xvViG9XxT4SK RtDw==
X-Gm-Message-State: AIkVDXLWitHoUpmXC3H8U2dmY2zJhkSRv0KQZ9a3TXWxVm+I6TPE3XXmYrH2Us9ryrgj5BXJviyxJzb2cNjpLg==
X-Received: by 10.46.76.10 with SMTP id z10mr7814840lja.9.1484942091613; Fri, 20 Jan 2017 11:54:51 -0800 (PST)
MIME-Version: 1.0
Received: by 10.25.18.200 with HTTP; Fri, 20 Jan 2017 11:54:50 -0800 (PST)
In-Reply-To: <CA+3+x5GTEKFHGcuPK0p9GKrBCwmkcVM2WpR43V79pLcZ7UuKEQ@mail.gmail.com>
References: <CAFn2buAYWHQSWhhoKZ2GKbqXR1A+tScjkAwZmOuQ9gV9jMp2bA@mail.gmail.com> <CAPyZ6=Kh3n+RJi=RqgFBojgRDpfJ=nbr0i4kvO20ET0Kt7UA8Q@mail.gmail.com> <CABkgnnWmPdDXVS+CvmChRjyqkJooSKgy6KdUdN+9nGzOyJazhg@mail.gmail.com> <CAFn2buDrHtB1z16iTWE945bU_qhxTypr05A=5B_nrQoyQijyOw@mail.gmail.com> <CAFn2buB_RpbwaTzDgYUNt0e9=vFyu--SYgSLBrfAd1Tf0b1_nQ@mail.gmail.com> <CAJutW=dX1Z8z+XJ10+uX729bxgWh417kXdd27kg=RO6VbcbvgA@mail.gmail.com> <CAFn2buDuGVBJ8WBptM3cNS_Wy_hnF1v_TMO5VzXriE6B9m-oqQ@mail.gmail.com> <CA+3+x5GTEKFHGcuPK0p9GKrBCwmkcVM2WpR43V79pLcZ7UuKEQ@mail.gmail.com>
From: Scott Mitchell <scott.k.mitch1@gmail.com>
Date: Fri, 20 Jan 2017 11:54:50 -0800
Message-ID: <CAFn2buAj9hnuhihR1GWZtZ9_e5kZjZQyKog6BXfV7O5qxvsJgQ@mail.gmail.com>
To: Tom Bergan <tombergan@chromium.org>
Cc: laike9m <laike9m@gmail.com>, Martin Thomson <martin.thomson@gmail.com>, Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>, HTTP Working Group <ietf-http-wg@w3.org>
Content-Type: multipart/alternative; boundary="f403045ea29ee1fe2305468c05ce"
Received-SPF: pass client-ip=209.85.215.51; envelope-from=scott.k.mitch1@gmail.com; helo=mail-lf0-f51.google.com
X-W3C-Hub-Spam-Status: No, score=-2.8
X-W3C-Hub-Spam-Report: AWL=0.515, BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_SORBS_SPAM=0.5, SPF_PASS=-0.001, W3C_AA=-1, W3C_WL=-1
X-W3C-Scan-Sig: titan.w3.org 1cUfHL-0001Vu-2F 2edafe3cafe7d9c0df43f63b540515b3
X-Original-To: ietf-http-wg@w3.org
Subject: Re: Stream State and PRIORITY Frames
Archived-At: <http://www.w3.org/mid/CAFn2buAj9hnuhihR1GWZtZ9_e5kZjZQyKog6BXfV7O5qxvsJgQ@mail.gmail.com>
Resent-From: ietf-http-wg@w3.org
X-Mailing-List: <ietf-http-wg@w3.org> archive/latest/33349
X-Loop: ietf-http-wg@w3.org
Resent-Sender: ietf-http-wg-request@w3.org
Precedence: list
List-Id: <ietf-http-wg.w3.org>
List-Help: <http://www.w3.org/Mail/>
List-Post: <mailto:ietf-http-wg@w3.org>
List-Unsubscribe: <mailto:ietf-http-wg-request@w3.org?subject=unsubscribe>

On Fri, Jan 20, 2017 at 10:28 AM, Tom Bergan <tombergan@chromium.org> wrote:

> IIUC, PUSH_PROMISEs don't count against the stream limit due to a
> (hypothetical) scenario like the following: A server currently has 199
> streams open on a connection, with limit of 200 per connection, and the
> client makes another request. Now the server has 200 streams open. The
> server wants to push a resource. Since the PUSH_PROMISE does not count
> against the stream limit, the server is allowed to send a PUSH_PROMISE,
> which notifies the client that the resource will be pushed (the client does
> not need to request it).
>
> I submit that this is a nearly-pointless optimization. Broadly speaking,
> there are two reasons a server might want to push a resource:
>
> 1. The server speculates that the client will need that resource shortly.
> If the pushed resource is not more important than basically all of the 200
> streams currently in flight, there is little reason to push that resource.
> This is a speculative push, meaning the goal is to reduce latency, but we
> can't reduce latency if the push will be queued behind 200 other streams
> anyway -- we might as well wait for the client to make the request.
>
> 2. The server is participating in a notification protocol where the push
> used to notify the client of some event. In this case, the PUSH_PROMISE
> does not need to be sent immediately because the server is not speculating
> about a future client request. It would be fine to queue the PUSH_PROMISE
> in the server until one of the 200 concurrent streams is closed.
>
> Therefore, I propose the following convention: servers should count
> PUSH_PROMISEs towards the concurrent stream limit. This doesn't
> necessarily help clients, since a client cannot rely on every server to
> implement this behavior, but overall it seems like a much simpler
> situation. FWIW, this is what I have implemented in Go's HTTP/2 server:
> https://github.com/golang/net/blob/77412025ac6f6821b4938edeb45af9
> 39de5cccec/http2/http2.go#L85
>
>
To clarify my original intention (given the spec has already been released)
is to have the limit be "advisory". The goal would be to preserve existing
behavior but also allow the client to inform the server of its limitations.
The server would have the option to use that information, or ignore it for
reserved streams. An important factor here is the end result for
violating SETTINGS_MAX_CONCURRENT_STREAMS
and the client resetting a PUSH_PROMISE is the same (stream error aka
RST_STREAM).

Although SETTINGS_MAX_CONCURRENT_STREAMS seems like a natural choice for
this there is one potential challenge. Section 5.1.2 includes the
language "Endpoints
MUST NOT exceed the limit set by their peer". The end result of "sending
too many push promises" and "violating SETTINGS_MAX_CONCURRENT_STREAMS" may
be the same (a stream error), but counting pushed streams
against SETTINGS_MAX_CONCURRENT_STREAMS may violate this MUST NOT clause
for existing implementations which don't count pushed streams against
SETTINGS_MAX_CONCURRENT_STREAMS. To be consistent the MUST NOT would have
to be relaxed and clarified.

https://tools.ietf.org/html/rfc7540#section-5.1.2

Endpoints MUST NOT exceed the limit set by their peer.  An endpoint
that receives a HEADERS frame that causes its advertised concurrent
stream limit to be exceeded MUST treat this as a stream error (Section
5.4.2 <https://tools.ietf.org/html/rfc7540#section-5.4.2>) of type
PROTOCOL_ERROR or REFUSED_STREAM.  The choice of error code determines
whether the endpoint wishes to enable automatic retry (see Section
8.1.4 <https://tools.ietf.org/html/rfc7540#section-8.1.4>) for
details).



> On Fri, Jan 20, 2017 at 9:01 AM, Scott Mitchell <scott.k.mitch1@gmail.com>
> wrote:
>
>>
>>
>> On Fri, Jan 20, 2017 at 5:17 AM, laike9m <laike9m@gmail.com> wrote:
>>
>>> If you don’t include RESERVED streams in the count for
>>> SETTINGS_MAX_CONCURRENT_STREAMS then how do you limit the amount of
>>> RESERVED streams, and how does your peer know about this limit? I have
>>> imposed an implementation specific metric in the past, but this seems less
>>> preferable than relying on something in the RFC that the peer is aware of.
>>> Either way having infinite of something doesn’t work in practice.
>>>
>>> As Martin has explained, H2 doesn’t limit the amount of RESERVED
>>> streams, based on the notion that HEADERS are close to free.
>>>
>>
>> "HEADERS are free" sounds like an over simplification which becomes more
>> apparent as the concurrency of streams and connections grows. There are
>> other provisions in the RFC to limit the amount of state consumed by
>> HEADERS (SETTINGS_HEADER_TABLE_SIZE, SETTINGS_MAX_HEADER_LIST_SIZE).
>>
>> In addition to headers this may require additional state to be allocated
>> for stream management. The specification also has mechanisms to limit state
>> consumed by streams.
>>
>> It’s true that one trying to send infinite number of PUSH_PROMISEs to
>>> client can cause problems, but 1. This only happens if the server is
>>> malicious, and if it’s malicious,having a limit in the RFC won’t
>>> prevent anything, and 2. Not counting PUSH_PROMISEs is a tradeoff for fast
>>> delivery of PUSH_PROMISEs, which stops client from sending more requests. I
>>> guess this is what Martin meant by “If you limit server push by applying a
>>> stream limit, then you prevent it from being used in time for the client to
>>> use it.”
>>>
>> (Forgot to reply to all :P)
>>>
>>
>> Malicious actors is a concern and must be dealt with. However there may
>> be proxy-like systems with large amounts of concurrency or other memory
>> constraint systems that already control their resources but the peer's only
>> mechanism to know about these limits is to try-then-fail. Assuming clients
>> impose some limit to their state (infinite state isn't practical) then the
>> problem of "the client won't accept this push" exists if the server knows
>> about it before hand or not. Knowing about it before hand gives the server
>> the ability to potentially prioritize which resources it wants to push or
>> make other more informed decisions.
>>
>>
>>
>>> On Thu, Jan 19, 2017 at 9:21 AM, Scott Mitchell <
>>> scott.k.mitch1@gmail.com> wrote:
>>>
>>>>
>>>>
>>>> On Tue, Jan 17, 2017 at 2:43 PM, Scott Mitchell <
>>>> scott.k.mitch1@gmail.com> wrote:
>>>>
>>>>> From my perspective I would like to see two clarifications:
>>>>>
>>>>> 1. It is clear to me that PRIORITY doesn't impact state.
>>>>>
>>>>
>>>> Just to clarify ... it is clear that a PRIORITY frame doesn't impact
>>>> the state of the stream  it is carrying priority information for. The
>>>> impacts PRIORITY frames have on other streams is not clear due to the
>>>> wording in section 5.1.1.
>>>>
>>>>
>>>>> However Section 5.1.1 states "first use of a new stream identifier"
>>>>> which makes no reference to stream state. If stream state is
>>>>> important/implied here better to be specific about it. I don't think the
>>>>> one-off example below this text is sufficient to convey the intended
>>>>> implications of this statement.
>>>>>
>>>>> 2. Section 5.1.2 states "Streams in either of the 'reserved' states
>>>>> do not count toward the stream limit." which seems to conflict with section
>>>>> 8.2.2 "A client can use the SETTINGS_MAX_CONCURRENT_STREAMS setting
>>>>> to limit the number of responses that can be concurrently pushed by a
>>>>> server.". These two statements appear to contradict each other. Since
>>>>> SETTINGS_MAX_CONCURRENT_STREAMS is really the only mechanism to limit
>>>>> resources due to server push I'm assuming section 5.1.2 is overly
>>>>> restrictive.
>>>>>
>>>>>
>>>>> On Tue, Jan 17, 2017 at 2:27 PM, Martin Thomson <
>>>>> martin.thomson@gmail.com> wrote:
>>>>>
>>>>>> On 18 January 2017 at 01:37, Tatsuhiro Tsujikawa <
>>>>>> tatsuhiro.t@gmail.com> wrote:
>>>>>> > If my understanding is correct, this only refers to the new stream
>>>>>> ID used
>>>>>> > by HEADERS, and PUSH_PROMISE frames which open or reserve streams.
>>>>>> The
>>>>>> > example text following that statement uses HEADERS which opens new
>>>>>> stream.
>>>>>> > PRIORITY frame does not change stream state, and there is no reason
>>>>>> to close
>>>>>> > all unused streams lower than bearing stream ID.  That said, I
>>>>>> agree that
>>>>>> > this is not crystal clear in the document.  In practice, this is
>>>>>> probably
>>>>>> > rather rare case.
>>>>>>
>>>>>> This is, I think, the expectation.
>>>>>>
>>>>>> I think that we probably want to clarify the point by explicitly
>>>>>> saying that PRIORITY doesn't affect stream states.  We say that it can
>>>>>> be sent in any state, but we don't also mention that important point.
>>>>>> Do people here agree that an erratum on this point is appropriate
>>>>>> here?
>>>>>>
>>>>>
>>>>>
>>>>
>>>
>>
>