Netty 线上使用案例

Posted Netty之家

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Netty 线上使用案例相关的知识,希望对你有一定的参考价值。

Netty 的版本

  • Netty3.6.5


关键字说明

1、 mongodb 消息的存储引擎
2、 LeaderServer 负责接收客户端的请求去mongodb load 数据ID
3、 LeaderClient 每个Topic维护一个LeaderClient 向LeaderServer发请求要数据一段区间 ID
4、 RingBuffer Disruptor 的缓冲区,LeaderServer接收到请求丢到RingBuffer,每个Topic 有一个 单独的RingBuffer
5、 RingBuffer 的process线程 负责从RingBuffer解析请求,从mongodb 查数据,写回 LeaderClient


问题描述

当一个topic 的请求查询mongodb 不段超时时,其他的topic的LeaderClient 的请求也超时, 而且当时查看网卡的发送接收队列,发现LeaderServer的接收队列堆积了好多请求,没有被 处理,当时一看还以为是网络,交换机的原因,经过ping网段和重启都无效。后来只能分析 代码发现是由于Netty的Worker IO线程把消息解码后同步put到RingBuffer导致的。


问题分析

我们的消息系统的每个topic是通过leader这样的角色来协调多个消费者消费一个区间的数 据。防止重复消费,不同的topic会通过netty连接到同一个LeaderServer,而且是每个Topic 一个链接,而且LeaderServer的Netty Worker IO线程是10个,这意味着每个Worker线程 会负责处理多个channle的请求。假如有个Worker线程堵住,则该Worker线程上的channle 上的请求都得不到处理,被堆积在系统的接收队列里,和当时的现象相符。再说下为啥 Worker 线程被堵住,是在RingBuffer被填满后即堆积1024个请求后,就被block住, RingBuffer 的process线程是根据请求去mongodb 查数据。我们的mongdb由于读写都是从 主,没有做读写分离,这样就是经常有表查询超时,超时时间是2s,但是在2s内RingBuffer 不会立即堆积,因为LeaderClient 发请求是有控制的,大概2s内发10次,那就是在 RingBuffer 的process线程处理了N次后,会导致RingBuffer堆满,只要一堆满,Netty的 Worker线程就会被block住2s,意味着2s内这个Worker线程负责的所有channel的请求都被 堆积。如果有多个Topic超时,就堵得更严重,因为是多个Netty的IO Worker线程被堵住。


问题总结

1、使用Netty时,IO线程和业务线程分开,异步处理时铁律,只要同步,就有可能被堵住

2.、使用Disruptor时,process线程最好不要是涉及IO或者网络操作,如果堵住,就导致写 往RingBuffer的线程block住,而且开源的实现会导致cpu 100%(默认的实现是在没有可用用的slot时,会sleep 1个ns 的时候,很容易让cpu跑满),这个我们Team已经改过了


以上是关于Netty 线上使用案例的主要内容,如果未能解决你的问题,请参考以下文章

实践案例丨Netty案例集锦之多线程篇(续)

荐书 | Netty进阶之路:跟着案例学Netty

从入门到实战,Netty多线程篇案例集锦

Netty 消息接收类故障案例分析

通过实际的案例详解 Netty 中 LengthFieldBasedFrameDecoder 的使用

Netty4.x实战专题案例文章列表