拆包粘包问题解决方案
- 消息定长,例如每个报文200个字节固定大小,如果不够,空格补位。FixedLengthFrameDecoder
- 在包尾部增加特殊字符进行隔断 DelimiterBasedFrameDecoder
- 将消息分为消息头和消息体,在消息头中包含消息总长度,然后进行逻辑处理
编解码
说白了就是java的序列化技术, 序列化的目的就两个,
- 进行网络传输,
- 对象持久化. 虽然我们可以使用java进行对象序列化,netty去传输,但是java序列化的 硬伤太多,比如java序列化无法跨语言,序列化码流太大,序列化性能太差等。
主流的编解码框架:
- JBoss的Marshalling包
- google的Protobuf
- 基于Protobuf的Kyro
- MessagePack框架
Marshalling是对jdk默认的序列化框架进行了优化,又保持跟Serializable 接口的兼容,同时增加了一些可调的参数和附加特性。
websocket的特点:
- 单一的tcp连接,双方可通信
- 对代理,路由器,防火墙透明
- 无头部信息,cookie和身份验证
- 无安全开销
- 通过ping/pong帧保持链路激活
- 服务器可主动传递消息给客户端,不需要再让客户端去轮询
netty最佳实践
我们真正需要去考虑的问题是如何实现多台机器之间如何通信? 大体上可以分为三种:
-
使用长连接通道不断开的形式通信,也就是服务器端与客户端的通道一直处于开启状态。 如果服务器性能足够好,推荐使用这种方式
-
一次性批量提交数据,采用短连接方式,也就是我们会把数据临时存在本地缓存中或者临时表里。 当达到临界值时一次性批量提交,或者定时任务轮询提交。缺点是做不到实时传输,对实时性不高的应用推荐使用
-
做一种特殊的长连接,当在指定的某一段时间里面,客户端与服务端没有发生任何通信,则断开连接。 下一次客户端再向服务端发起请求的时候再建立连接。这里我们需要考虑两个问题:
- 如何在超时后关闭通道,关闭通道后又如何再建立连接;
- 如果服务端宕机,客户端如何再与服务端重连