昨天群里讨论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,最好还是不要替代,个人看法。