关于粘包

最初网络编程的时候都是blocking IO的方式,也就是同步请求, 客户端 一个请求发到服务度,等服务端返回前会一直阻塞住, 直到服务端返回。

后来有了异步编程, 所谓的异步编程, 只不过吧 同步请求, 变成了写缓冲区。然后操作系统批量的发送缓冲区到服务端。

那么如果 服务端 是按照最初的编程模型, 客户端 是用异步编程模型的话,也许会遇到关于粘包的坑。

比如我上周遇到的 thrift 的官方java实现的坑。

作为 thrift server端, 他没有考虑 粘包的情况,她的实现是将 解码和处理业务 整体作为一个任务传递给 线程池 执行。

造成的结果是,如果发过来 多个 请求,粘包了, 粘成了一个,那么这个 “大包” 将在 线程池的某一个线程内 串行 执行。

上周就遇到了这种情况, 我们自己用 netty 实现的 thrift client 调用一个后端比较慢的服务, 发现怎么qps 一高 全部都超时了, client 的写缓冲区堵了, 但是 server 像是没有接收到那么多请求,一个错误都没有, 非常坑爹。

如果是 用 thrift 官方的 java client 其实是同步请求。所以不会遇到粘包。

那么如果是异步的话,如何减轻这种情况。

很简单,搞连接池,然后 取连接的策略变成 FIFO 就行了,连接池数量 == qps, 平均分发即可。

avatar

lelouchcr's blog