HTTP2 window update and priority

Hi

According to my view on the source code of Nginx 1.9.15, I noticed some
observation below:

  1. when there is no enough window, nginx won’t send back the response
    frame, though according to the log, nginx said it has sent the headers
    frame out, but client won’t receive it. This is not right according to
    RFC
    7540 because window update will only limit the data frames

2.when there is no enough window, nginx will first store the request in
the
queue, when it received a window update, nginx will start fetch the
streams
stored in the queue use ngx_queue_head within a while loop(line 2161 in
ngx_http_v2.c). I noticed the stream order I got is the same as the
sending
order with no relationship of the dependency tree, then nginx will
create
the corresponding data frames according to the stream order. But I
noticed
whether nginx will put the frame into the output queue depends on the
value of wev->ready, here a problem is that I noticed when the request
files is big, the wev->ready is set 0, only when this happens, the
priority
mechanism can work otherwise the frame will be sent out directly with no
dependency observation. I am still confused on how does nginx implement
the
priority. Could you please give me some suggestions.

A failed priority mechanism example debug log:

Best Regards
Muhui Jiang

On Monday 09 May 2016 21:27:31 Muhui Jiang wrote:

Hi

According to my view on the source code of Nginx 1.9.15, I noticed some
observation below:

  1. when there is no enough window, nginx won’t send back the response
    frame, though according to the log, nginx said it has sent the headers
    frame out, but client won’t receive it. This is not right according to RFC
    7540 because window update will only limit the data frames

You’ve misread the source code. HTTP/2 windows are handled in
ngx_http_v2_send_chain(), which is only called for response body
data.

dependency observation. I am still confused on how does nginx implement the
priority. Could you please give me some suggestions.

A failed priority mechanism example debug log:
https://github.com/valour01/LOG/blob/master/example.log

The prioritization has effect when there is concurrency for
connection. In your case from nginx point of view there was
only one stream in processing at any moment. The previous
stream was completed before the new one has been received.

wbr, Valentin V. Bartenev

Hi

You’ve misread the source code. HTTP/2 windows are handled in
ngx_http_v2_send_chain(), which is only called for response body
data.

when the window is blocked, Nginx logs that the headers frame has been
sent
out, however I cannot receive any response headers. The same client
tried
on h2o and I can receive the response headers.

The prioritization has effect when there is concurrency for
connection. In your case from nginx point of view there was
only one stream in processing at any moment. The previous
stream was completed before the new one has been received.

Let me explain my strategy in detail. I used some requests(stream id
1-15)
to consume the window (65535) And then block the window without sending
any
window update frame(I have sent a very large stream update before). Then
I
send the next 6 streams with different priorities. At this moment, the 6
streams should be blocked. Nginx should have enough time to handle the
priority. Then I send a very large window update frame, but nginx will
process the stream one by one with no priority observation. What I want
to
say is, only when the file is really large then the priority can be
observed. But I have give enough time to Nginx by block the request.
Nginx
should handle the priority though the file is really small. If you need
more information, please tell me. Many Thanks

Best Regards
Muhui Jiang

2016-05-10 21:15 GMT+08:00 Valentin V. Bartenev [email protected]:

Hi

To say more, I may need your comment on my understanding of Nginx

  1. Is the reason that I cannot receive the response headers frame
    because
    the response headers are stored in the SSL buffer?

2.Nginx will fetch the blocked request in the queue when receiving a
window
update frame (is the request order in the queue the same as my sending
order?)

3.Then Nginx will handle the request one by one in a non-block mode. I
noticed that when the requested file is small, nginx will create all the
data frames, push the data frames into out frames queue and sent it out.
(
the handling order is the same as my sending request order) When the
requested file is large(say 10Mb), nginx will create only a part of data
frames and then create some other data frames (the handling order is
related to the dependency tree). So:

  • when a file is large, how many data frames to be generated once before
    generating the other frames, is it related to the SSL buffer size and
    the
    maximum frame size? and when Nginx are going to send out the frames
    and
    start a new SSL buffer.
  • I dig the debug log and noticed the real process to reflect the
    priority
    handling is the order to generate the data frames and connect those
    data
    frames before sending then out. I cannot find the handling process
    related
    to priority when generating the data frames and connect them together.
    It
    would be great if you can tell me the strategy or locate the source
    code.
  • Like the case I mentioned above. when the requested file is small,
    clients can not get the expected receiving response order. How large a
    file
    should be then nginx can handle them concurrently. I think in the real
    environment, many js , css file are not so big. So Nginx can not give
    priority mechanism in those cases. I suggest that Nginx should change
    the
    request queue order(Here I noticed the request queue is the same as the
    receiving order) rather than handling priority when generating data
    frames,
    it would be too late. So that even the files is small, the response
    order
    will also follows the dependency tree.

Best Regards
Muhui Jiang

2016-05-10 22:33 GMT+08:00 Valentin V. Bartenev [email protected]:

On Tuesday 10 May 2016 22:12:59 Muhui Jiang wrote:

Hi

You’ve misread the source code. HTTP/2 windows are handled in
ngx_http_v2_send_chain(), which is only called for response body
data.

when the window is blocked, Nginx logs that the headers frame has been sent
out, however I cannot receive any response headers. The same client tried
on h2o and I can receive the response headers.

In addition, nginx uses SSL buffer to optimize record sizes.

You can tune it using the “ssl_buffer_size” directive:
http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_buffer_size

priority. Then I send a very large window update frame, but nginx will
process the stream one by one with no priority observation. What I want to
say is, only when the file is really large then the priority can be
observed. But I have give enough time to Nginx by block the request. Nginx
should handle the priority though the file is really small. If you need
more information, please tell me. Many Thanks

[…]

Ok, now I understand your case. You are right, currently in this
particular case priorities aren’t handled.

wbr, Valentin V. Bartenev