老问题,netty的固定个数的worker线程阻塞大量的并发连接

xinglu 发布于 2012/03/06 22:46
阅读 25K+
收藏 8

【开源中国 APP 全新上线】“动弹” 回归、集成大模型对话、畅读技术报告”

小弟正在做一个大批量的联机交易系统, 对netty正在熟悉中.

由于一直认为,使用cachedThreadPool不方便控制大量客户端恶意并发连接的风险,给我一种不可控的感觉,所以在启动NIO server时,我一直使用fixedThreadPool方式

new NioServerSocketChannelFactory(
                        Executors.newSingleThreadExecutor(),
                        Executors.newFixedThreadPool(5))

我一直认为,是5个worker线程负责并行处理客户端的连接请求,一次请求处理完毕后就丢弃本次连接(不是关闭),换下一个连接请求. 但是当我并发连接超过5个tcp连接时,只要前面5个连接不关闭(这5个连接可以执行任何输入,只要不关闭),后续的新增连接虽然能连接到,但是无法到达后续的具体handler进行处理,好像被worker线程池阻塞住了.我想问有没有什么方法能够不使用cachedThreadPool作为worker线程池,却又能够并发的处理大量客户端连接,话说SOCKET NIO不就是以这个(处理大量并发连接)为新特性的吗? 我总是感觉这样风险太大.假如客户的客户端发生bug,一直不断死循环来连接,连上又不关闭,那我的服务器性能岂不是要受到巨大影响吗?

难道各位的生产环境都是用cachedThreadPool方式吗?如果是这样的话,那还不如回到OIO的时代,通过自己创建的可控线程池处理,还更好控制一些.

网上说的用connectionTimeout和Server的backlog参数解决方案,我都觉得不是很有说服力

谢谢!

以下是问题补充:

@谢远熙:这个问题确实是存在的,存在的原因 我这里存在的条件: netty作为服务端,socket客户端(阻塞的) (2012/03/07 19:10)
加载中
0
xinglu
xinglu
Server的第三个参数决定了最后的并发数量,所以如果halder里面有大量耗时操作的话,是不会有更多并发的,最多就是第三个参数的个数了.大家不用担心内存被撑爆,第三个参数不填时默认是CPU内核数的2倍.而且第三个参数如果比第二个参数的线程池里面的线程数少的话,还会造成第阻塞现象.所以其实cacheThreadPool就是最优的解决方案,甚至在老外给出的官方例子中我们还能看到第一个参数和第二个参数公用一个threadPool的情况.我们要做的仅仅是在hanlder里面快速的处理完数据并且返回,否则NETTY可能真的不合适这个业务场景了,加入真有耗时操作,请交给你自定义的后台业务处理线程池再进行处理.
0
JavaGG
JavaGG

LZ所说的情况应不会发生的,除非你在handler里写了死循环。

另外可以设定timeout时间,让超时的连接释放调

nio的特性就保证了,不会因为某几个连接有问题而影响到整个服务器

楼主可以放心使用

0
xinglu
xinglu

引用来自“JavaGG”的答案

LZ所说的情况应不会发生的,除非你在handler里写了死循环。

另外可以设定timeout时间,让超时的连接释放调

nio的特性就保证了,不会因为某几个连接有问题而影响到整个服务器

楼主可以放心使用

不是吧,我都试了一晚上了,而且代码非常简单,main函数就几行启动代码,外带一个handler,而且网上也有人发出同样问题的
JavaGG
JavaGG
可否把handler代码贴出来see see??
0
demon
demon
work 线程是核心分发线程,不负责处理业务逻辑,只是起到分发请求到handler 的作用,默认work线程数你的cpu的核心个数,设置多了没有用,提高并发需要在handler 里面做线程池处理,不然的话 work 线程只能串行处理请求,并发量大减。
0
xinglu
xinglu

其实我只是连接,并没有要求handler做什么操作,前2个connect也并没有发出消息,只是连接上了,也没有走到handler里面,但就是这样,就阻塞了第三个连接的写操作

下面是一些日志,前两个连接都是先open,再bound,最后connect,我没有关闭,随后发起第三个connect并且发出一些信息,netty就在handler里面无法响应,只有关闭前面的connection 才能进去,感觉就是被blocked一样.

 

收到响应事件:[id: 0x0067ac19, /127.0.0.1:6691 => /127.0.0.1:8080] OPEN12565936
2012-3-7 9:34:09 org.jboss.netty.example.discard.DiscardServerHandler handleUpstream
信息: [id: 0x0067ac19, /127.0.0.1:6691 => /127.0.0.1:8080] OPEN
收到响应事件:[id: 0x0067ac19, /127.0.0.1:6691 => /127.0.0.1:8080] BOUND: /127.0.0.1:808025527824
2012-3-7 9:34:09 org.jboss.netty.example.discard.DiscardServerHandler handleUpstream
信息: [id: 0x0067ac19, /127.0.0.1:6691 => /127.0.0.1:8080] BOUND: /127.0.0.1:8080
收到响应事件:[id: 0x0067ac19, /127.0.0.1:6691 => /127.0.0.1:8080] CONNECTED: /127.0.0.1:669125276323
2012-3-7 9:34:09 org.jboss.netty.example.discard.DiscardServerHandler handleUpstream
信息: [id: 0x0067ac19, /127.0.0.1:6691 => /127.0.0.1:8080] CONNECTED: /127.0.0.1:6691
收到响应事件:[id: 0x0131f71a, /127.0.0.1:6695 => /127.0.0.1:8080] OPEN22413802
2012-3-7 9:34:53 org.jboss.netty.example.discard.DiscardServerHandler handleUpstream
信息: [id: 0x0131f71a, /127.0.0.1:6695 => /127.0.0.1:8080] OPEN

 

0
xinglu
xinglu
上面第三个connection只有open事件,没有触发bound事件,这里是不是有点奇怪?
0
xinglu
xinglu
用调试工具测试一下,worker thread pool和这个cacheThreadPool大小没有必然的联系,是我想多了,还需要进一步对netty底层研究一下
0
谢远熙
我也遇到该问题,也是使用了fix固定的线程
0
xinglu
xinglu

引用来自“谢远熙”的答案

我也遇到该问题,也是使用了fix固定的线程
我现在的做法是这样的,就用cache线程池就行,这个和后台线程池大小没有必然联系的,我用jprofile测过了,我cpu是4核,他的worker线程大小一直是8个,线程池大小好像和构造函数里面第三个参数有关系,而不是传入的第二个线程池.
0
谢远熙
那你说的现象还成立吗
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部