Introduction
Netty provides us with a lot of http2 packages, so that we can easily build a server that supports http2. The only thing we need to customize is the http2 handler.
In the previous article, we introduced a custom http2handler that inherits from Http2ConnectionHandler and implements Http2FrameListener. This kind of implementation is currently recommended by netty. One of the implementations introduced to you today is to replace the implementation of Http2ConnectionHandler in netty. However, this implementation is not mature and is still being improved.
Today I will introduce you to this way of implementation.
Http2FrameCodec
The core class of this implementation is Http2FrameCodec. In fact, Http2FrameCodec is also inherited from Http2ConnectionHandler.
Its main function is to map frames and Http2Frame objects in HTTP/2. Http2Frame is the encapsulation of all http2 frames in netty, so that you can focus on processing Http2Frame objects in subsequent handlers, thus getting rid of various details of the http2 protocol and reducing the workload of users.
For each incoming HTTP/2 frame, Http2FrameCodec will create an Http2Frame object and pass it to the channelRead method for processing the object.
By calling the write method, the outbound Http2Frame can be converted into http2 frame format.
Http2Frame, Http2FrameStream and Http2StreamFrame
There are three very similar classes in netty, they are Http2Frame, Http2FrameStream and Http2StreamFrame.
We know that a tcp connection in netty can establish multiple streams. Http2FrameStream is the class corresponding to stream. This class contains the id of the stream and the current state of the stream.
A stream contains multiple messages, and each message is composed of multiple frames, so Http2Frame is the netty class corresponding to these frames.
Http2StreamFrame itself is also a frame, in fact it inherits from Http2Frame.
Why is there such a class? Because the corresponding frame itself is generally associated with a specific stream, Http2StreamFrame represents this association relationship, and its associated stream can be specified through its set stream method. If you want the frame to be applied to the entire connection instead of a specific stream, if it is related to the entire connection, then the return of the stream() method is null.
The structure of Http2FrameCodec
Although Http2FrameCodec has a constructor, netty recommends using Http2FrameCodecBuilder to construct it:
Http2FrameCodecBuilder.forServer().build();
You can see that Http2FrameCodecBuilder has a forServer and a forClient method. One of them is used on the server side and the other is used on the client side.
It is mainly distinguished by the server attribute inside.
Stream's life cycle
The frame codec will send and write frames to a valid stream. As mentioned before, Http2StreamFrame is associated with an Http2FrameStream object.
For a valid stream, if either party sends a RST_STREAM frame, then the stream will be closed.
Or if the frame sent by either the sender or the receiver is marked with END_STREAM, the stream will also be closed.
Flow control
Http2FrameCodec provides automatic control of the flow, but we still need to do some operations to update the window.
Specifically, when we receive the Http2DataFrame message, after processing the message, we need to increase the size of the window, which means that the data has been processed and there is more space to accommodate the new data.
That is to say, you need to write an Http2WindowUpdateFrame to ctx. In this Http2WindowUpdateFrame, you need to pass in the size of the processed data and the id of the corresponding stream. The following is an example of processing a data frame:
/**
* 处理data frame消息
*/
private static void onDataRead(ChannelHandlerContext ctx, Http2DataFrame data){
Http2FrameStream stream = data.stream();
if (data.isEndStream()) {
sendResponse(ctx, stream, data.content());
} else {
// 不是end stream不发送,但是需要释放引用
data.release();
}
// 处理完data,需要更新window frame,增加处理过的Data大小
ctx.write(new DefaultHttp2WindowUpdateFrame(data.initialFlowControlledBytes()).stream(stream));
}
In the above example, we passed the corresponding stream id to DefaultHttp2WindowUpdateFrame. If the stream id is 0, it means that the entire connection is being processed instead of a single stream.
In addition to the window update frame, an Http2SettingsFrame can also be sent to the initial window of a particular stream, which can be initialized by setting Http2Settings.initialWindowSize().
Receive message
For each HTTP/2 stream, the frame contained in it can be divided into Http2HeadersFrame and Http2DataFrame, and Http2HeadersFrame must be the first frame received, and this headerFrame is also associated with the corresponding stream object: Http2FrameStream.
So we can deal with these two different frames separately when processing:
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof Http2HeadersFrame) {
onHeadersRead(ctx, (Http2HeadersFrame) msg);
} else if (msg instanceof Http2DataFrame) {
onDataRead(ctx, (Http2DataFrame) msg);
} else {
super.channelRead(ctx, msg);
}
}
Custom handler
If you use Http2FrameCodec, we only need to add a custom handler after adding Http2FrameCodec in pipline:
ctx.pipeline().addLast(Http2FrameCodecBuilder.forServer().build(), new CustHttp2Handler());
Because Http2FrameCodec has converted the frame in http2, we only need to process custom logic in CustHttp2Handler.
Netty recommends a custom handler to inherit from Http2ChannelDuplexHandler, because it has one more forEachActiveStream(Http2FrameStreamVisitor) method that creates newStream() and traverses all valid streams than ordinary ChannelDuplexHandler.
Summarize
This article explains the principle of Http2FrameCodec, and the matters needing attention in the implementation of the handler with it.
For the examples in this article, please refer to: learn-netty4
This article has been included in http://www.flydean.com/31-netty-framecodec-http2/
The most popular interpretation, the most profound dry goods, the most concise tutorial, and many tips you don't know are waiting for you to discover!
Welcome to pay attention to my official account: "Program those things", know technology, know you better!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。