Netty ServerBootstrap构造方法问题

jason5186 发布于 2012/03/10 15:18
阅读 7K+
收藏 1

请先看几行源码:

 public NioServerSocketChannelFactory(
            Executor bossExecutor, Executor workerExecutor) {
        this(bossExecutor, workerExecutor, SelectorUtil.DEFAULT_IO_THREADS);
    }

    public NioServerSocketChannelFactory(
            Executor bossExecutor, Executor workerExecutor,
            int workerCount) {
        if (bossExecutor == null) {
            throw new NullPointerException("bossExecutor");
        }
        if (workerExecutor == null) {
            throw new NullPointerException("workerExecutor");
        }
        if (workerCount <= 0) {
            throw new IllegalArgumentException(
                    "workerCount (" + workerCount + ") " +
                    "must be a positive integer.");
        }
        this.bossExecutor = bossExecutor;
        this.workerExecutor = workerExecutor;
        sink = new NioServerSocketPipelineSink(workerExecutor, workerCount);

    }

 NioServerSocketPipelineSink(Executor workerExecutor, int workerCount) {
        workers = new NioWorker[workerCount];
        for (int i = 0; i < workers.length; i ++) {
            workers[i] = new NioWorker(id, i + 1, workerExecutor);
        }
    }

其中,在构造NioServerSocketChannelFactory方法时,如未指定workcount,系统会默认指定为cup * 2 。 (我的cup是双核)我在这里的workcount的值是4。

在我的测试中,通过观察,只看到最多4个线程在工作。

到这里有了些疑问:

1、如果我在客户端一次创建10个线程,这里只有4个在工作,剩余线程是由workExecutor来缓存,还是由boosExecutor缓存?

2、在构造NioSErverSocketPipelineSink类时,只传递了workExecutor和workcount两个参数,通过观察源码没看到workExecutor有执行execute的地方 !?

3、boosExecutor和workExecutor在Netty中的用途是什么?

4、java api中对Executors.newCachedThreadPool()解释是:

创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。调用 execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。因此,长时间保持空闲的线程池不会使用任何资源。


api中提到长时间保持空闲的线程池不会使用任何资源,但他会在池中没有空闲线程时,给来访者创建新的线程,那么这时,假设我对这个服务发起1000、2000..个并发线程,那么netty在他的用户手册中提到“不再因过快、过慢或超负载连接导致 OutOfMemoryError”,那么netty是如何控制的 ?

5、在我构造ServerBootStrap方法时:

final ServerBootstrap server=new ServerBootstrap(
					new NioServerSocketChannelFactory(
							Executors.newCachedThreadPool(), 
							Executors.newCachedThreadPool())
					);

把Executors.newCachedThreadPool 替换为:Executors.newFixedThreadPool(n) 会对netty有什么影响?由于不了解boosExecutor和workExecutor的实际用意,所以也产生了低第5个问题 。

 

请各位朋友帮忙解答一下啊,非常感谢!

 

加载中
0
j
jason5186

呵呵,不知道是问题太简单,还是没人关心这些!!!   不过我想应该有很多人同我有一样的我问题。

至于Executors这个类,我知道他的实际用途,但到了netty这里实在让我不能理解他的用意。

0
xinglu
xinglu
    /**
     * Creates a new instance.
     *
     * @param bossExecutor
     *        the { @link Executor} which will execute the boss threads
     * @param workerExecutor
     *        the { @link Executor} which will execute the I/O worker threads
     * @param workerCount
     *        the maximum number of I/O worker threads
     */
第三个参数其实就是第二个线程池的最大线程数,这两个参数互相牵制,结果就是取最小值作为后台worker线程并发最大值.
如果你在handler里面阻塞同步式的处理,那么netty可能不适合你,如果是异步的迅速返回(另起线程处理)的话,netty还是比较合适的,我现在痛苦死了,研究了netty一段时间,发现不适合我的业务场景,又回到OIO的环境中了.
0
j
jason5186

引用来自“xinglu”的答案

    /**
     * Creates a new instance.
     *
     * @param bossExecutor
     *        the { @link Executor} which will execute the boss threads
     * @param workerExecutor
     *        the { @link Executor} which will execute the I/O worker threads
     * @param workerCount
     *        the maximum number of I/O worker threads
     */
第三个参数其实就是第二个线程池的最大线程数,这两个参数互相牵制,结果就是取最小值作为后台worker线程并发最大值.
如果你在handler里面阻塞同步式的处理,那么netty可能不适合你,如果是异步的迅速返回(另起线程处理)的话,netty还是比较合适的,我现在痛苦死了,研究了netty一段时间,发现不适合我的业务场景,又回到OIO的环境中了.
final ServerBootstrap server=new ServerBootstrap(
	                    new NioServerSocketChannelFactory(
	                            Executors.newCachedThreadPool(),
	                            Executors.newCachedThreadPool())
	                    );

难怪了,我用Executors.newFixedThreadPool(n)来替代第二个参数后,实际并发的线程与workcount的关系就复杂了。。

 

pipeline.addLast("handle", new MessageServerHandler());

这里的handler你说他是非线程安全的 ?

 

0
xinglu
xinglu
pipeline里面的handler算是线程安全吧,而且测试结果一个handler默认是对应一次connect连接后的多次交互.但如果你在某个handler里面启动了异步通知,也就是监听器,那么监听器里面的代码可能和下次handler处理的代码互斥,我现在就遇到这个问题,好头大,netty不允许在handler里面使用future的wait模式,只好自己写锁开控制并发.不知道对你有没有帮助,我现在有点想放弃netty了,太多不了解的内容,还不如用OIO方式写的方便和有控制力.虽然二者性能上有差异.
0
j
jason5186

引用来自“xinglu”的答案

pipeline里面的handler算是线程安全吧,而且测试结果一个handler默认是对应一次connect连接后的多次交互.但如果你在某个handler里面启动了异步通知,也就是监听器,那么监听器里面的代码可能和下次handler处理的代码互斥,我现在就遇到这个问题,好头大,netty不允许在handler里面使用future的wait模式,只好自己写锁开控制并发.不知道对你有没有帮助,我现在有点想放弃netty了,太多不了解的内容,还不如用OIO方式写的方便和有控制力.虽然二者性能上有差异.

哈哈,谢谢xinglu ,netty对我的业务还蛮实用的,我们之前使用nio的方式实现的 。 在经过测试对比后,netty在I/o方面的性能相当稳定,cpu使用率比nio/bio都平缓很多 。

0
xinglu
xinglu

引用来自“jason5186”的答案

引用来自“xinglu”的答案

pipeline里面的handler算是线程安全吧,而且测试结果一个handler默认是对应一次connect连接后的多次交互.但如果你在某个handler里面启动了异步通知,也就是监听器,那么监听器里面的代码可能和下次handler处理的代码互斥,我现在就遇到这个问题,好头大,netty不允许在handler里面使用future的wait模式,只好自己写锁开控制并发.不知道对你有没有帮助,我现在有点想放弃netty了,太多不了解的内容,还不如用OIO方式写的方便和有控制力.虽然二者性能上有差异.

哈哈,谢谢xinglu ,netty对我的业务还蛮实用的,我们之前使用nio的方式实现的 。 在经过测试对比后,netty在I/o方面的性能相当稳定,cpu使用率比nio/bio都平缓很多 。

请问你用什么工具做这种测试的,我也想学习一下,苦于一直没有性能测试的好工具
0
j
jason5186

引用来自“xinglu”的答案

引用来自“jason5186”的答案

引用来自“xinglu”的答案

pipeline里面的handler算是线程安全吧,而且测试结果一个handler默认是对应一次connect连接后的多次交互.但如果你在某个handler里面启动了异步通知,也就是监听器,那么监听器里面的代码可能和下次handler处理的代码互斥,我现在就遇到这个问题,好头大,netty不允许在handler里面使用future的wait模式,只好自己写锁开控制并发.不知道对你有没有帮助,我现在有点想放弃netty了,太多不了解的内容,还不如用OIO方式写的方便和有控制力.虽然二者性能上有差异.

哈哈,谢谢xinglu ,netty对我的业务还蛮实用的,我们之前使用nio的方式实现的 。 在经过测试对比后,netty在I/o方面的性能相当稳定,cpu使用率比nio/bio都平缓很多 。

请问你用什么工具做这种测试的,我也想学习一下,苦于一直没有性能测试的好工具

是公司内部研发的有针对性的测试工具,不过你可以试用一下jprofiler ,这是一个非常不错的工具。

另外,我的测试结果只是针对我的应用,根据应用中的线程经过的路径不同、逻辑不同等等,所以结果也会有大不同。 

0
j
jason5186

刚接触这个框架的时候,太急着使用,弄得很慌张,API都没查全就来弄这个了。。。


经过一段的实际应用、java源码、netty源码查了几遍,终于可以操控他了。


我个人认为对于workExecutor没有必要改变他,netty默认会使用CPU * 2来设置,基本都是够用,设置多了也是增加了线程上下文的频繁切换,反而会使线程的执行效率下降。


workExecutor这个线程池是用于处理用户请求的,我们写demo时通常都会由该线程直接调用handler,在执行相应的业务操作/DB操作等等,而实际应用中,基本不会这么做,如果执行的业务比较耗时,且线程的数量只有这几个可以支配,那么无法处理的请求将只能等待。

所以,基于这种情况,我们在配置ChannelPipelineFactory时,加入一个ExecutionHandler(ThreadPools)类,用于分发请求,让workExecutor线程更专注的去处理请求,而非调用业务处理器;而如何分发和分发请求的策略依赖于你的ThreadPools的实现。

当然,netty有已经实现的ThreadPools可以供你可以直接拿来使用,也你也可以自定义一个适合你的业务场景的ThreadPools。


所以,要构造一个ServerBootstrap默认的基本可以满足大部分的通讯场景,更多的需要你去关注的还是ExecutionHandler类。


另外,netty有些版本存在一些小的BUG,如资源未能正确释放,链路检测函数校验不严格等等,需要留意官方的版本修复日志,尽早发现并打上补丁。


结贴吧!



0
来啊糟老头子
来啊糟老头子
请问,高并发请求的时候,ServerBootstrap该怎么配置啊
0
yangjingv587
yangjingv587
同问,高并发请求的时候,ServerBootstrap该怎么配置啊
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部