在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\n
、EOF\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%的业务场景需求,如果有什么遗漏或者错误的地方,请留言指正,谢谢!
留个言
使用netty的websocket实现的客户端,收不到基于netty的websocket服务端发送的消息