netty learn

"netty learn"

Posted by tablesheep on

Basic

Class desc
StringEncoder、StringDecoder 字符串编解码器
IdleStateHandler 空闲状态处理(心跳检测),构造函数可以指定读、写、读写操作多久没发生,然后向后面的ChannelHandler发送IdleStateEvent,后面的ChannelHandler需要实现ChannelInboundHandler#userEventTriggered方法处理

HTTP

Class desc
HttpRequestDecoder http request 解码器,用于服务端入站流量
HttpResponseEncoder http response 编码器,用于服务端出站流量
HttpServerCodec http服务端编解码器,通过CombinedChannelDuplexHandler组合HttpRequestDecoderHttpResponseEncoder
HttpRequestEncoder http requeset编码器,用于客户端出站流量
HttpResponseDecoder http response解码器,用于客户端入站流量
HttpClientCodec http 客户端编解码器,通过CombinedChannelDuplexHandler组合了HttpRequestEncoderHttpResponseDecoder
HttpObjectAggregator Http 消息聚合器,可以将分块的HttpMessageHttpContent聚合到单个的FullHttpRequestFullHttpResponse中,用于处理Response时将它插入HttpResponseDecoder之后,处理Request时将它插在HttpRequestDecoderHttpResponseEncoder之后
HttpContentCompressor Http 内容压缩,用于服务端,支持gzipdeflatebr压缩,同时支持Accept-Encoding请求头协商
HttpContentDecompressor Http 内容解压,用于客户端
   

Protobuf

protobuf 传输时,无脑把这四个加上就完事了

ProtobufVarint32FrameDecoder

解析varint 32 长度信息

1
2
3
4
5
* BEFORE DECODE (302 bytes)       AFTER DECODE (300 bytes)
* +--------+---------------+      +---------------+
* | Length | Protobuf Data |----->| Protobuf Data |
* | 0xAC02 |  (300 bytes)  |      |  (300 bytes)  |
* +--------+---------------+      +---------------+

ProtobufVarint32LengthFieldPrepender

拼接varint 32 长度信息

1
2
3
4
5
* BEFORE ENCODE (300 bytes)       AFTER ENCODE (302 bytes)
* +---------------+               +--------+---------------+
* | Protobuf Data |-------------->| Length | Protobuf Data |
* |  (300 bytes)  |               | 0xAC02 |  (300 bytes)  |
* +---------------+               +--------+---------------+

ProtobufDecoder

ProtobufEncoder

异步处理

1
2
3
4
//ctx: ChannelHandlerContext
ctx.channel().eventLoop().execute();
ctx.channel().eventLoop().scheduleWithFixedDelay();
ctx.channel().eventLoop().scheduleAtFixedRate();

@ChannelHandler.Sharable

用于标识ChannelHandler是否为共享实例,需要注意线程安全问题,使用🌰

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@ChannelHandler.Sharable
public class ShareableChannelHandler extends SimpleChannelInboundHandler<String> {
......    
}


public class DefaultChannelInitializer extends ChannelInitializer<SocketChannel> {
    
    private ShareableChannelHandler shareabledHandler = new ShareableChannelHandler();
    
    @Override
    protected void initChannel(SocketChannel sc) throws Exception {
        //注意注入时要以成员变量或者别的不变的方式,不能以新建对象的方式,否则共享不会失效
        sc.pipeline().addLast(shareabledHandler);
    }
}

对于@ChannelHandler.Sharable注解,Netty 仅仅只是在添加ChannelHandler时检查这个handler是否共享以及是否第一次添加,不满足其一则在报错

DefaultChannelPipeline

1
2
3
4
5
6
7
8
9
10
11
12
13
private static void checkMultiplicity(ChannelHandler handler) {
    if (handler instanceof ChannelHandlerAdapter) {
        ChannelHandlerAdapter h = (ChannelHandlerAdapter) handler;
        //判断是否共享以及是否第一次添加
        if (!h.isSharable() && h.added) {
            throw new ChannelPipelineException(
                    h.getClass().getName() +
                    " is not a @Sharable handler, so can't be added or removed multiple times.");
        }
        //标记为已添加过
        h.added = true;
    }
}