Hi!请登陆

Netty框架几个常用Codec(解码器)组合及其用法

2020-10-17 72 10/17

在Netty实际开发中,会使用琳琅满目的Codec来应对各种各样的场景,如果没有丰富的实战经验,面对各种各样的Codec会无从下手。那么今天笔者将会罗列几组Codec组合,大家遇到相应业务场景或者技术场景的时候可以直接使用。

HTTP 服务

使用Netty搭建Http轻量级服务器是常见的Netty框架使用场景,用于接收HTTP请求然后转发使用,作为代理场景那是相当的好用。
一般HTTP报文通过底层的TCP传输过来,所以是分片传输的,当Netty Http服务器接到的是分片报文,那么在Http场景中就很难处理,毕竟谁都不可能处理一个分开的Http报文。

考虑到上面的几方面,Http轻量级服务器要使用到以下Codec组合:

  • HttpServerCodec ///HTTP 服务的解码器/

将二进制报文转为HTTP文本报文

  • HttpObjectAggregator(5121024) ///HTTP 消息的合并处理 最大512k*/

合并分批次过来的 HTTP报文,合并后Handler拿到的将是一个完整的HTTP报文

HttpProxyInitializer 代码示例:

@Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ch.pipeline()
                .addLast(new HttpServerCodec())/*HTTP 服务的解码器*/
                //如果没有aggregator,那么一个http请求就会通过多个Channel被处理,这对我们的业务开发是不方便的,而aggregator的作用就在于此。
                .addLast(new HttpObjectAggregator(512*1024))/*HTTP 消息的合并处理  最大512k*/
                .addLast(trafficShapingHandler,
                new HttpProxyFrontendHandler());
    }

TCP服务器

TCP服务器通常是以TCP报文进行通信,TCP报文是基于字节流的,所以不仅仅要应对TCP的粘包问题,还要应对字节流转变为字符流的问题。如果处理不善,第一个将会造成无法获取准确的报文问题,第二个将会出现乱码。笔者在开发过程中还遇到了

考虑以上方面的问题,站长推荐以下组合,满足日常TCP服务器场景需求。

TCP-Codec组合 - 1

  • LineBasedFrameDecoder // 通常会传入一个数字,表示报文长度

LineBasedFrameDecoder 解决的粘包的问题,只要报文以'n'结尾即可以分包。

  • StringDecoder // 通常输入解码后的字符格式,一般汉字选择:GBK 或者 UTF-8

Demo 示例代码:

@Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ch.pipeline()
                //.addLast(new LineBasedFrameDecoder(512*1024))
                .addLast("stringDecoder", new StringDecoder(Charset.forName("utf-8")))
                        .addLast(new TcpProxyFrontendHandler(proxyDefinition));
    }

TCP-Codec组合 - 2

利用此组合,可以自定义分隔符,但是同行的分隔符也就那么自动,为了进一步提高分包精度,利用使用自定义分分隔符来解决粘包问题。比如:\r\nEOF\n

  • DelimiterBasedFrameDecoder //传入数字,限制包的长度;传入ByteBuf参数,自定义个性分隔符或者组合分隔符。

这里接收的是一个 ByteBuf,其实就是一段字节流,因为长度没限制所以可以考虑自定义多个字符来形成个性的分隔符,提高分包精度以及防止报文污染。

  • StringDecoder //通常输入解码后的字符格式,一般汉字选择:GBK 或者 UTF-8

Demo 示例代码:

@Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ch.pipeline()
                //.addLast(new DelimiterBasedFrameDecoder(512*1024,"\n".toBytes()))//这里是伪代码,需要自己转化为ByteBuf
                .addLast("stringDecoder", new StringDecoder(Charset.forName("utf-8")))
                        .addLast(new TcpProxyFrontendHandler(proxyDefinition));
    }

TCP-Codec组合 - 3

实际开发中经常会碰到传递的是Json等格式化数据,刚开始接触的时候以为需要自己动手写Json规则的拆分包逻辑,后来查了文档才知道Netty已经提供了一个用于解决Json粘包问题的Codec。组合如下:

  • JsonObjectDecoder //满足Json规则的解码器
  • StringDecoder //字节转为字符

Demo 代码示例:

.addLast(new JsonObjectDecoder())
.addLast("stringDecoder", new StringDecoder(Charset.forName("utf-8")))

使用以上解码器组合,在Handler中直接可以拿到完成的Json包。

WebSocket 服务器

由于WebSocket的通信协议和Http的类似,所以在Netty实践中,WebSocket服务器使用Codec和Http协议中使用的类似。

  • HttpServerCodec //将请求与应答消息编码或者解码为HTTP消息
  • HttpObjectAggregator // 将http消息的多个部分组合成一条完整的HTTP消息
  • ChunkedWriteHandler //主要用于支持浏览器和服务端进行WebSocket通信

Demo 代码示例:

 protected void initChannel(SocketChannel socketChannel) throws Exception {
        ChannelPipeline pipeline = socketChannel.pipeline();
        // 将请求与应答消息编码或者解码为HTTP消息
        pipeline.addLast("http-codec", new HttpServerCodec());
        // 将http消息的多个部分组合成一条完整的HTTP消息
        pipeline.addLast("aggregator", new HttpObjectAggregator(HttpObjectConstant.MAX_CONTENT_LENGTH));
        // 向客户端发送HTML5文件。主要用于支持浏览器和服务端进行WebSocket通信
        pipeline.addLast("http-chunked", new ChunkedWriteHandler());
        // 服务端Handler
        pipeline.addLast("handler", new WebSocketServerHandler(webSocketUrl));
    }

结尾

站在巨人的肩膀上灵活使用Codec组合不仅能够简化技术实现,还能够满足各式各样的业务场景,快速响应业务需求。以上这些组合基本上能够满足90%的业务场景需求,如果有什么遗漏或者错误的地方,请留言指正,谢谢!

相关推荐