背景
cb-openapi-service去年出现过几次线程池满的异常,近来想写篇技术博文所以针对这个问题进行分析下。
问题场景
发布的时候dubbo报Thread pool is EXHAUSTED
问题分析
只有这个应用发布的时候报错那就是个个性问题,还是需要分析下这个个性问题出现的原因。既然是线程用完了那就要分析线程都干什么去了。首先介绍下dubbo的线程模型。
dubbo线程模型
dubbo线程模型是基于netty的,netty的线程模型是基于reactor的,netty和reactor就不做介绍了,主要介绍dubbo线程模型。dubbo线程模型是通过dispatcher来指定的,有以下值:
all:连接事件、断开事件、心跳、请求、响应都由业务线程池处理
message:连接事件、断开事件、心跳由IO线程池处理,请求、响应由业务线程池处理
direct:连接事件、断开事件、心跳、请求、响应都由IO线程池处理
execution:连接事件、断开事件、心跳、请求由IO线程池处理,响应由业务线程池处理
connection:连接事件、断开事件由IO线程池处理,请求、响应、心跳由业务线程池处理
dispatcher默认值是all,即全部事情都是由业务线程池在做,讲到这其实大致应该有思路了,既然是发布的时候报错,那是不是线程都去断连接了。接下来介绍怎么搜日志。
搜日志
dubbo断连接和建连接都有相应的日志,根据报错的时刻上下浮动一秒,即时间跨度三秒搜关键字disconnected,看哪个应用连接特别多
如果看日志看不出来,可以去机器上查看tcp连接。接下来介绍怎么查看tcp连接。
查看tcp连接
通过命令netstat -anpo可以查看tcp连接,可以发现10.19.17.94这台机器连接特别多
查看10.19.17.94这台机器部署的应用,发现是cb-openapi-webhook
查看cb-openapi-webhook的apollo配置,发现有个dubbo.consumer.connections=100
正常一个客户端跟服务端某个接口只会有一个连接,有了这个属性后服务端启动,客户端与服务端会建立200多个连接。那为什么cb-openapi-webhook需要建这么多连接呢,接下来介绍下dubbo的适用场景。
dubbo适用场景
dubbo适用于高并发小数据传输的场景,客户端和服务端维持一个NIO长连接,该数据通道为全双工通道,数据可以双向同时传输,并发大的时候请求报文虽然是串行传输,但是都比较小并不影响性能,空闲的时候只维持一个连接也不侵占资源。如果是大数据传输场景,并发大的时候串行传输,后面的请求就要等很久才能处理影响性能。如果大数据传输场景改成多个长连接,并发大的时候并行传输,可以提升性能,但是空闲的时候维持多个连接侵占资源。cb-openapi-webhook和cb-openapi-service之所以维持这么多连接,猜测是因为webhook要去service取数据,这个数据是对外通知报文,当时开发者可能觉得报文比较大所以用多连接并行传输来提升性能。其实像这种大数据传输最好是直接访问数据库,不要通过dubbo传输。
总结
- 大数据传输不要用dubbo
- 如果是发布的时候报Thread pool is EXHAUSTED,dubbo是dispatcher=all模式就去看是不是连接太多了
- 如果是正常运行的时候报Thread pool is EXHAUSTED,就去看是不是某个接口请求量突然变大了或某个接口耗时突然变长了