网络应用编解码

文章详细探讨了网络应用中的编解码问题,包括业务编解码和传输编解码。业务编解码涉及序列化和反序列化,考虑效率、资源占用和兼容性。传输编解码讨论了TCP的分包、粘包问题和UDP的顺序接收、确认控制、拥塞控制。Netty提供了内置编解码器支持,并允许自定义扩展。文章还提到了Netty的内存管理和Pipeline配置等关键概念。
摘要由CSDN通过智能技术生成

系列文章目录

1. Netty网络应用基础
2. Java I/O
3. IO/模型
4. 网络应用编解码
5. Netty Pipeline
6. Netty EventLoopGroup&EventLoop
7. Netty ThreadLocal&FastThreadLocal
8. Netty Future&Promise
9. Netty内存管理–(旧)PoolChunk&伙伴分配
10. Netty内存管理–内存池空间规格化SizeClasses
11. Netty内存管理–PoolChunk&PoolSubPage
12. Netty内存管理–内存池PoolArena
13. Netty内存管理–内存分配器PooledByteBufAllocator
14. Netty ObjectPool

写在前面

前面的博文咱们讨论了编解码, 想必你已经知道编解码过程就是字节数组到应用消息的转换, 接下来想跟你聊聊编解码场景需要考虑哪些问题, 以及常用的处理方式。就编解码中的信息而言, 一部分肯定是应用处理需要的信息, 另一部分则是与具体传输协议有关的信息。因此, 本篇分业务编解码和传输编解码来讨论。

一、业务编解码

业务编解码解决业务message到byte的转换, 在Java中就是序列化和反序列化。一般从编解码的效率, 资源占用和阅读友好性考虑。

项目说明场景特点
编码效率编码前后的空间消耗比窄带宽传输更多数据, 比如蓝牙应用
解码效率收到数据后,解码时间消耗接收端解码能力弱, 比如移动应用
资源占用编解码过程中CPU和内存占用接收或发送端CPU和内存较小, 比如嵌入式应用
升级兼容性协议升级时向前兼容的难易程度与协议变化频度有关
阅读友好性方便排查问题面向开发者,一般不直接考虑, 通过开发配套工具解决

二、传输编解码

1. TCP协议

想必你也知道TCP是面向数据流的传输, 数据流本身没有类似分段或者局部结束的概念, 所以在具体实现上以segment的承载能力为界限, 分割应用层数据。在MTU=1500个字节的情况下, TCP segment中一次至多有1460个字节可以填充应用消息。显然, 这种分割标准与应用层完全不同, 标准不同自然就会带来潜在的问题。

1.1 分包

如果一条应用层消息超过1460 byte则需要放在2个segment, 此时我们说TCP协议对message做了分包处理。个人认为, 分包的本质是整个网络链路上各跳的处理能力不同, 处理能力最差的节点可能仅能够缓存有限个MTU。

1.2 粘包

如果一条应用层消息只有10 byte, 那么理论上1460 byte可以填充146个, 然后通过一个TCP segment发出, 此时我们说TCP协议对message做了粘包处理。协议这么实现是为了充分利用每一个segment的承载能力。

1.3 小结

无论分包还是粘包, 应用层的核心问题是因为不知道消息本身的分割方式, 所以无法处理收到segment。解决方法有三种, 定长消息、变长消息(将消息长度编码在消息中)和固定分隔符。

2. UDP协议下

想必你已经知道UDP是面向数据报的, 所有的数据以数据包为单位传输, 在协议层面数据包之间没有顺序关系。如果要实现类似TCP协议中的可靠性, 则需要在应用层解决如下问题:

2.1 顺序接收

在UDP协议层面, 数据包可以顺序发送, 但由于IP层会对路由过程做动态优化, 可能存在后发先至的情况。为解决该问题, 一方面应用需要在消息中增加顺序字段(想想TCP中的seq), 另一方面应用接收端需要设定接收窗口而后在窗口内按照顺序字段做重排。

2.2 确认控制

有了顺序字段, 通信双方就可以做收发的的确认。对于超时未确认的数据报, 应用也可以自定义重传策略。比如流媒体领域通常允许一定的丢包率, 特定场景下不做重传也是可以的。

2.3 拥塞控制

整个通信链路是动态波动的, 带宽紧张时发送更多的数据包毫无意义, 同样带宽充裕时任然无所作为实在浪费资源, 而想要有所作为就得能感知波动这个是带宽探测。带宽探测包括链路带宽探测和对端的带宽探测(其实是处理能力探测)。有了探测结果, 应用就可以做比较, 而后调整收发速度。该过程可以参考TCP实现, 并结合应用场景做定制。

2.4 小结

笔者对UDP的传输做的比较少, 只能提供一些思路, 还请读者见谅。

三、Netty的支持

3.1 内置编解码方式

请添加图片描述

3.2 个人使用的评价

编解码方式编码效率解码效率资源占用升级兼容性阅读友好性备注
JSON/XML11555调试,小message场景
Protobuf54350关注编码效率
JDK原生序列化22350参考对象, 几乎不用
Flatbuffer45350关注解码效率

3.3 自定义扩展

Netty中通过实现MessageToByteEncoder和MessageToByeDecoder可以实现自定义编解码器, 其中考虑到解码是整个pipeline的第一环, 而编码则是最后一环, 所以在配置Pipeline应用自定义编解码器器时, 应格外注意顺序问题。

总结

本文从业务编解码和传输编解码两个方面讨论网络应用中的编解码问题。其中应用编解码层面本文讨论了评价方式和场景特点, 在传输编解码层面讨论了典型问题和解决方案。最后, 本文分享了Netty中对编解码的支持和以及部分个人使用经验。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值