欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

mina的ExecutorFilter使用方式 博客分类: nio minaExecutorFilter

程序员文章站 2024-02-23 11:50:46
...

    昨天群里讨论mina的ExecutorFilter,有点不明白的地方,早上看了下mina的ExecutorFilter源码,感觉主要逻辑还是很简单的。 

   源码头的注释:

 /**
38   * A filter that forwards I/O events to {@link Executor} to enforce a certain
39   * thread model while allowing the events per session to be processed
40   * simultaneously. You can apply various thread model by inserting this filter
41   * to a {@link IoFilterChain}.*/

    1.该过滤器,使用特定的线程模型,使每个session的evens得以同时执行,线程模型可定制。
	(就是你可以指定线程池类型)
42   /* 
43   * <h2>Life Cycle Management</h2>
44   * 
45   * Please note that this filter doesn't manage the life cycle of the {@link Executor}.
46   * If you created this filter using {@link #ExecutorFilter(Executor)} or similar
47   * constructor that accepts an {@link Executor} that you've instantiated, you have
48   * full control and responsibility of managing its life cycle (e.g. calling
49   * {@link ExecutorService#shutdown()}.
50   * <p> 
51   * If you created this filter using convenience constructors like
52   * {@link #ExecutorFilter(int)}, then you can shut down the executor by calling
53   * {@link #destroy()} explicitly.
54   */
	2.生命周期管理:
	注意:ExecutorFilter不负责线程池的生命周期管理,你自己负责

55   /* <h2>Event Ordering</h2>
56   * 
57   * All convenience constructors of this filter creates a new
58   * {@link OrderedThreadPoolExecutor} instance.  Therefore, the order of event is
59   * maintained like the following:
60   * <ul>
61   * <li>All event handler methods are called exclusively.
62   *     (e.g. messageReceived and messageSent can't be invoked at the same time.)</li>
63   * <li>The event order is never mixed up.
64   *     (e.g. messageReceived is always invoked before sessionClosed or messageSent.)</li>
65   * </ul>
66   * However, if you specified other {@link Executor} instance in the constructor,
67   * the order of events are not maintained at all.  This means more than one event
68   * handler methods can be invoked at the same time with mixed order.  For example,
69   * let's assume that messageReceived, messageSent, and sessionClosed events are
70   * fired.
71   * <ul>
72   * <li>All event handler methods can be called simultaneously.
73   *     (e.g. messageReceived and messageSent can be invoked at the same time.)</li>
74   * <li>The event order can be mixed up.
75   *     (e.g. sessionClosed or messageSent can be invoked before messageReceived
76   *           is invoked.)</li>
77   * </ul>
78   * If you need to maintain the order of events per session, please specify an
79   * {@link OrderedThreadPoolExecutor} instance or use the convenience constructors.
80   */
	3.event顺序
	默认线程池为OrderedThreadPoolExecutor,因此,管理event顺序如下:
		1. 任何event处理方法是排它的,比如messageReceived和messageSent不可能同时执行。
		2. event顺序不可能混淆,比如messageReceived一般先于sessionClosed或messageSent.
	如果你不使用OrderedThreadPoolExecutor,event的顺序会变得混乱:
        1. 所有的event处理方法可能会同时执行。
        2. event顺序变得混乱,比如sessionClosed或者messageSent先于messageReceived执行
	总之,如果你想每个session的event变得有序,请使用默认的线程池:)
	(不用的话好像后果很严重呵呵)

81   /* <h2>Selective Filtering</h2>
82   * 
83   * By default, all event types but <tt>sessionCreated</tt>, <tt>filterWrite</tt>,
84   * <tt>filterClose</tt> and <tt>filterSetTrafficMask</tt> are submitted to the
85   * underlying executor, which is most common setting.
86   * <p>
87   * If you want to submit only a certain set of event types, you can specify them
88   * in the constructor.  For example, you could configure a thread pool for
89   * write operation for the maximum performance:
90   * <pre><code>
91   * IoService service = ...;
92   * DefaultIoFilterChainBuilder chain = service.getFilterChain();
93   * 
94   * chain.addLast("codec", new ProtocolCodecFilter(...));
95   * // Use one thread pool for most events.
96   * chain.addLast("executor1", new ExecutorFilter());
97   * // and another dedicated thread pool for 'filterWrite' events.
98   * chain.addLast("executor2", new ExecutorFilter(IoEventType.WRITE));
99   * </code></pre>
100  */
	4.选择性过滤
	默认情况下,所有的event,除了sessionCreated之外,都会交给线程池去执行处理。
	但是如果你只想把某些event交给线程池,那可以这么做:
	IoService service = ...;
	DefaultIoFilterChainBuilder chain = service.getFilterChain();
	chain.addLast("codec", new ProtocolCodecFilter(...));
	// 使用这个线程池处理大部分event
    chain.addLast("executor1", new ExecutorFilter());
    // 使用这个线程池处理filterWrite这个event
    chain.addLast("executor2", new ExecutorFilter(IoEventType.WRITE));

 

 

   ExecutorFilter可以针对特定的event交给线程池执行,这点比较灵活,看下messageReceived的处理:

 

     public final void messageReceived(NextFilter nextFilter, IoSession session, Object message) {
         if (eventTypes.contains(IoEventType.MESSAGE_RECEIVED)) {
             IoFilterEvent event = new IoFilterEvent(nextFilter, IoEventType.MESSAGE_RECEIVED, session, message);
             fireEvent(event);
         } else {
             nextFilter.messageReceived(session, message);
         }
     }
 

   1.检查该event是否要交给线程执行.

   2.将它封装成IoFilterEvent

   3.提交线程池

  fireEvent(event);

protected void fireEvent(IoFilterEvent event) {
   executor.execute(event);
}

  来看看IoFilterEvent的fire方法(其实就是Runnable的run)

switch (type) {
          case MESSAGE_RECEIVED:
             Object parameter = getParameter();
              nextFilter.messageReceived(session, parameter);
              break;

  

  所以,如果使用了ExecutorFilter,在它之后的过滤器(nextFilter),以及handler,都会放在线程池中去执行,注意到粒度是event,当然默认是全部event。如此IO线程可摆脱其它业务逻辑,提升对客户端的响应效率。

  另外,ExecutorFilter中的默认OrderedThreadPoolExecutor,最好还是不要替代,个人看法。

相关标签: mina ExecutorFilter