服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

服务器及中间件:apache mina 线程模型配置


 
1、禁止缺省的threadmodel设置
       mina2.0及以后版本已经没有threadmodel了,如果使用这些版本的话,可以跳过本节。
       threadmodel设置是在mina1.0以后引入的,但是使用threadmodel增加了配置的复杂性,推荐禁止掉缺省的theadmodel配置。
       ioacceptor acceptor = ...;
       ioserviceconfig acceptorconfig = acceptor.getdefaultconfig();
       acceptorconfig.setthreadmodel(threadmodel.manual);
       注意在相关指南中,假定你已经如本节所说的禁止了threadmodel的缺省配置。
 
2、配置i/o工作线程的数量
      这节只是nio实现相关的,nio数据包以及虚拟机管道等的实现没有这个配置。
      在mina的nio实现中,有三种i/o工作线程:
      >>acceptor线程 接受进入连接,并且转给i/o处理器线程来进行读写操作。每一个socketacceptor产生一个acceptor线程,线程的数目不能配置。
      >>connector线程 尝试连接远程对等机,并且将成功的连接转给i/o处理器线程来进行读写操作。每一个socketconnector产生一个connector线程,这个的数目也不可以配置。
      >>i/o处理器线程 执行实际上的读写操作直到连接关闭。每一个socketacceptor或socketconnector都产生它们自己的i/o处理线程。这个数目可以配置,缺省是1。
       因此,对于每个ioservice,可以配置的就是i/o处理线程的数目。下面的代码产生一个有四个i/o处理线程的socketacceptor。
       ioacceptor acceptor = new socketacceptor(4, executors.newcachedthreadpool());
没有单凭经验来决定i/o处理线程数目的方法,大概可以从1开始增加。
       ioacceptor acceptor = new socketacceptor(runtime.getruntime().availableprocessors() + 1, executors.newcachedthreadpool());
 
3、增加一个executorfilter到iofilterchain中
       executorfilter是一个iofilter,用于将进入的i/o事件转到一个 java.util.concurrent.executor实现。事件会从这个executor转到下一个iofilter,通常是一个线程池。可以在 iofilterchain的任何地方增加任意数目的executorfilter,实现任何类型的线程模型,从简单的线程池到复杂的seda。
      到现在为止我们还没有增加executorfilter,如果没有增加executorfilter,事件会通过方法调用转到一个 iohandler,这意味着在iohandler实现中的业务逻辑会在i/o处理线程里运行。我们叫这种线程模型为"单线程模型"。单线程模型可以用来就会低反应网络应用程序,受cpu限制的业务逻辑(如,游戏服务器)。
      典型的网络应用需要一个executorfilter插入到iofilterchain中,因为业务逻辑和i/o处理线程有不同的资源使用模式。如果你用iohandler的实现来执行数据库操作,而没有增加一个executorfilter的话,那么,你整个服务器会在执行数据库操作的时候锁定,特别是数据库性能低的时候。下面的例子配置一个ioservice在一个新的iosession建立时增加一个executorfilter。
      ioacceptor acceptor = ...;
      defaultiofilterchainbuilder filterchainbuilder = acceptor.getdefaultconfig().getfilterchain();
      filterchainbuilder.addlast("threadpool", new executorfilter(executors.newcachedthreadpool());
      这里要注意executorfilter没有管理特定的executor的生命周期,当完成时,需要关闭所有特定executor的工作线程。
     executorservice executor = ...;
     ioacceptor acceptor = ...;
     defaultiofilterchainbuilder filterchainbuilder = acceptor.getdefaultconfig().getfilterchain();
     filterchainbuilder.addlast("threadpool", new executorfilter(executor);
     // start the server.
     acceptor.bind(...);
    // shut down the server.
    acceptor.unbind(...);
    executor.shutdown();
    使用一个executorfilter通常不意味着要用一个线程池,对于executor的实现没有任何限制。
 
4、应该把executorfilter放在iofilterchain的什么地方
     这个要根据于具体应用的情况来定。如果一个应用有一个protocolcodecfilter实现和一个常用的有数据库操作的iohandler实现的话,那么就建议在protocolcodecfilter实现的后面增加一个executorfilter,这是因为大部分的协议解码实现的性能特性是受cpu限制的,和i/o处理线程是一样的。
     ioacceptor acceptor = ...;
     defaultiofilterchainbuilder filterchainbuilder = acceptor.getdefaultconfig().getfilterchain();
     // add cpu-bound job first,
     filterchainbuilder.addlast("codec", new protocolcodecfactory(...));
     // and then a thread pool.
     filterchainbuilder.addlast("threadpool", new executorfilter(executors.newcachedthreadpool());
 
5、选择ioservice的线程池类型时要小心
     executors.newcachedthreadpool()经常是ioservice首选的。因为如果使用其它类型的话,可能会对 ioservice产生不可预知的性能方面的影响。一旦池中的所有线程都在使用中,ioservice会在向池尝试请求一个线程时开始锁定,然后会出现一个奇怪的性能下降,这有时是很难跟踪的。
 
6、不推荐ioservices和executorfilters共享一个线程池
     你可以想让ioservices和executorfilters共享一个线程池,而不是一家一个。这个是不禁止的,但是会出现很多问题,在这种情况下,除非你为ioservices建立一个缓冲线程池。


扫描关注微信公众号