我在HTTP2上使用泽西。当流量变得有点高时,就会引发异常。我得到了pcap发现服务器在没有接收到FIN的情况下发送FIN/确认字符。我不确定从服务器端关闭连接是单个FIN。或者单个FIN将确认字符组合到以前的数据包。它看起来是后者,因为客户端没有发送FIN。所以问题是为什么服务器在只有小流量的情况下发送FIN。我发现rece_q和send_q非常低。CPU使用率不是那么高。我已经调整了一些TCP参数,结果是一样的。这种行为是不稳定的,有时它是确定的,有时不确定。当我添加更多的请求(使用相同的TPS)然后不确定。它看起来服务器完成了连接,但不知道确切的原因。它是否与HTTP2有关。我们有什么地方可以看到确切的原因吗?
下面是pcap快照。
pcap快照
更新2017-07-30调试日志:
Sun Jul 30, 2017 8:31:35.591 PM org.glassfish.grizzly.http2.Http2FrameCodec parse
FINE: Rx [2]: connection=TCPNIOConnection{localSocketAddress={localhost/127.0.0.1:80}, peerSocketAddress={/127.0.0.1:57802}}, frame=DataFrame {streamId=277, type=0, flags=[none], length=42, data=BuffersBuffer (154351355) [pos=0 lim=42 cap=42 bufferSize=1 buffers=[HeapBuffer (165674143) [pos=0 lim=42 cap=8391], null, null, null]]}
Sun Jul 30, 2017 8:31:35.673 PM org.glassfish.grizzly.http2.Http2BaseFilter processFrames
FINE: Http2ConnectionException occurred on connection=TCPNIOConnection{localSocketAddress={localhost/127.0.0.1:80}, peerSocketAddress={/127.0.0.1:57802}} during Http2Frame processing
Sun Jul 30, 2017 8:31:35.684 PM org.glassfish.grizzly.http2.Http2FrameCodec serializeAndRecycle
FINE: Tx: connection=TCPNIOConnection{localSocketAddress={localhost/127.0.0.1:80}, peerSocketAddress={/127.0.0.1:57802}}, frame=GoAwayFrame {streamId=0, type=7, flags=[none], length=64{lastStreamId=199, errorCode=REFUSED_STREAM}
以及pcap快照中的流277
pcap包含来自第270、271和272号的流277
269包中有一个SETTINGS包。传输中途发送SETTINGS是否正常?并且在269之后,有三个包270、271和272正在使用蒸汽277。
奇怪的是,大约在8:31:35.684我没有找到GOWay数据包。但只在8:31:36.035发送了RST/确认字符。在这一轮调试日志如下:
Sun Jul 30, 2017 8:31:36.020 PM org.glassfish.grizzly.http2.Http2FrameCodec parse
FINE: Rx [2]: connection=TCPNIOConnection{localSocketAddress={localhost/127.0.0.1:80}, peerSocketAddress={/127.0.0.1:57802}}, frame=DataFrame {streamId=465, type=0, flags=[END_STREAM], length=0, data=ByteBufferWrapper (1101850112) [visible=[java.nio.HeapByteBuffer[pos=0 lim=0 cap=0]]]}
Sun Jul 30, 2017 8:31:36.023 PM org.glassfish.grizzly.http2.Http2BaseFilter processDataFrame
FINE: Data frame received for non-existent stream: connection=TCPNIOConnection{localSocketAddress={localhost/127.0.0.1:80}, peerSocketAddress={/127.0.0.1:57802}}, frame=DataFrame {streamId=277, type=0, flags=[END_STREAM], length=0, data=ByteBufferWrapper (1101850112) [visible=[java.nio.HeapByteBuffer[pos=0 lim=0 cap=0]]]}, stream=277
Sun Jul 30, 2017 8:31:36.024 PM org.glassfish.grizzly.http2.Http2BaseFilter processFrames
FINE: Http2StreamException occurred on connection=TCPNIOConnection{localSocketAddress={localhost/127.0.0.1:80}, peerSocketAddress={/127.0.0.1:57802}} during Http2Frame processing
Sun Jul 30, 2017 8:31:36.025 PM org.glassfish.grizzly.http2.Http2BaseFilter processFrames
FINE: Http2ConnectionException occurred on connection=TCPNIOConnection{localSocketAddress={localhost/127.0.0.1:80}, peerSocketAddress={/127.0.0.1:57802}} during Http2Frame processing
日志显示收到了一个不存在的流277。这个流正是第一个日志中记录的流。不确定这个蒸汽277会在接下来的几毫秒内导致RST/确认字符。我认为它应该与数据包269~272和流277有一些问题。
BTW,这次没有FIN/确认字符。
pcap
显示服务器上的异常终止。
您应该检查服务器日志以了解发生这种情况的更多详细信息。
一个可能的原因是服务器bug。
另一个可能的原因是客户端在数据包14发送了无效的HEADERS
帧;尽管如此,服务器应该发送一个GOAWay
帧,而不仅仅是关闭连接。
数据包17的RST
是正常的,因为客户端在处理FIN
之前在数据包16发送了一个HEADERS
帧,所以服务器回复一个RST
,表明发送的数据没有到达用户代码层。
服务器日志(可能在DEBUG级别)应该会告诉您更多关于发生的事情。