本文主要介绍Jetty对NIO的封装。
jetty对NIO的的封装主要包含几个重要的类:SelectorManager,ManagedSelector,SelectChannelEndPoint,
ExecutionStrategy,ExecuteProduceRun。下面对这几个类做详细介绍,及这几个类是如何窜连起来工作,处理IO事件的。
在介绍这几个类之前,先介绍Jetty中的LifeCycle,实现了改LifeCycle接口的类我们可以把它当作一个组件(compent)来看待,里面的接口包含了start,stop及对组件状态(isRunning,isStarted,isTopped)的判断,同时我们可以往上面注册某些状态监听方法。
先介绍最重要的类ManagedSelector,封装了JDK NIO中的Selector,它同时实现了Runable接口。 ManagedSelector成员变量有一个Selector和任务Queue,该任务队列放置的都是Runnable类型的任务。这Queue很重要,用来盛放通过ManagedSelector.submit方法提交上来的action,一般该方法由SelectorManager来调用。主要有三种类型的action:
1.Acceptor,用来注册监听类型的Key OP_ACCEPT
2.Accept,主要是把SocketChannel注册到selector上,用来读写操作;
3.Connect,用来注册Key OP_CONNECT,用来判断连接是否就绪;
一旦有以上三个任务提交上来,该 selector上的select操作都应该被wakeup。下面贴出三个类型的action与sumit方法,这个三个类型都是ManagedSelector内部类。
class Acceptor implements Runnable
{
private final ServerSocketChannel _channel;
public Acceptor(ServerSocketChannel channel)
{
this._channel = channel;
}
@Override
public void run()
{
try
{
SelectionKey key = _channel.register(_selector, SelectionKey.OP_ACCEPT, null);
if (LOG.isDebugEnabled())
LOG.debug("{} acceptor={}", this, key);
}
catch (Throwable x)
{
closeNoExceptions(_channel);
LOG.warn(x);
}
}
}
class Accept implements Runnable
{
private final SocketChannel channel;
private final Object attachment;
Accept(SocketChannel channel, Object attachment)
{
this.channel = channel;
this.attachment = attachment;
}
@Override
public void run()
{
try
{
final SelectionKey key = channel.register(_selector, 0, attachment);
submit(new CreateEndPoint(channel, key));
}
catch (Throwable x)
{
closeNoExceptions(channel);
LOG.debug(x);
}
}
}
class Connect implements Runnable
{
private final AtomicBoolean failed = new AtomicBoolean();
private final SocketChannel channel;
private final Object attachment;
private final Scheduler.Task timeout;
Connect(SocketChannel channel, Object attachment)
{
this.channel = channel;
this.attachment = attachment;
this.timeout = ManagedSelector.this._selectorManager.getScheduler().schedule(new ConnectTimeout(this), ManagedSelector.this._selectorManager.getConnectTimeout(), TimeUnit.MILLISECONDS);
}
@Override
public void run()
{
try
{
channel.register(_selector, SelectionKey.OP_CONNECT, this);
}
catch (Throwable x)
{
failed(x);
}
}
private void failed(Throwable failure)
{
if (failed.compareAndSet(false, true))
{
timeout.cancel();
closeNoExceptions(channel);
ManagedSelector.this._selectorManager.connectionFailed(channel, failure, attachment);
}
}
}
//submit方法:
public void submit(Runnable change)
{
if (LOG.isDebugEnabled())
LOG.debug("Queued change {} on {}", change, this);
try (SpinLock.Lock lock = _lock.lock())
{ //提交action
_actions.offer(change);
if (_selecting)
{
Selector selector = _selector;
if (selector != null)
//唤醒阻塞的select操作
selector.wakeup();
// To avoid the extra select wakeup.
_selecting = false;
}
}
}
还有一个重要的成员变量是执行策略类(ExecutionStrategy),该类的作用是jetty对它的注释是:ExecutionStrategy执行由Producer生产出的runnable任务,任务执行的策略根据实现的不同,或许在调用线程中直接执行或者另起一个新的线程来执行。ExecutionStrategy这里调用的生产者就是ManagedSelector内部类SelectorProducer,该内部类实现了.Producer接口。下面我们可以看看ManagedSelector.SelectorProducer的实现的一些方法:
//ManagedSelector.SelectorProducer,主要用来生产任务。
private class SelectorProducer implements ExecutionStrategy.Producer{
private Set<SelectionKey> _keys = Collections.emptySet();
private Iterator<SelectionKey> _cursor = Collections.emptyIterator();
@Override
public Runnable produce()
{
while (true)
{
//处理选中事件,如果有任务生成直接返回。
//注意这里叫作task,要和action区分开来,不用弄混了,
//这里的task都是根据selector上的相应的就绪key产生的读/写/连接task。
Runnable task = processSelected();
if (task != null)
return task;
//如果没有task产生,从actions中取任务
//这里返回的action都是实现了Product,不会改变selector上的感兴趣事件。(待确认)
//交由ExecutionStrategy去执行。
Runnable action = runActions();
if (action != null)
return action;
//更新相应变化的感兴趣Key
update();
//select,获取感兴趣的事件。
if (!select())
return null;
}
}
private Runnable processSelected()
{
while (_cursor.hasNext())
{
SelectionKey key = _cursor.next();
if (key.isValid())
{
Object attachment = key.attachment();
try
{
if (attachment instanceof SelectableEndPoint)
{
// Try to produce a task
//会产生读或写任务,或者读写任务。
SelectableEndPoint selectable = (SelectableEndPoint)attachment;
Runnable task = selectable.onSelected();
if (task != null)
return task;
}
else if (key.isConnectable())
{
Runnable task = processConnect(key, (Connect)attachment);
if (task != null)
return task;
}
else if (key.isAcceptable())
{
processAccept(key);
}
else
{
throw new IllegalStateException("key=" + key + ", att=" + attachment + ", iOps=" + key.interestOps() + ", rOps=" + key.readyOps());
}
}
catch (CancelledKeyException x)
{
if (attachment instanceof org.eclipse.jetty.io.EndPoint)
closeNoExceptions((EndPoint)attachment);
}
catch (Throwable x)
{
if (attachment instanceof org.eclipse.jetty.io.EndPoint)
closeNoExceptions((EndPoint)attachment);
}
}
else
{
Object attachment = key.attachment();
if (attachment instanceof EndPoint)
closeNoExceptions((EndPoint)attachment);
}
}
return null;
}
/**
*
* @return
*/
private Runnable runActions()
{
//循环处理任务队列中的任务,直到任务完全被处理完。
while (true)
{
Runnable action;
try (SpinLock.Lock lock = _lock.lock())
{
action = _actions.poll();
if (action == null)
{
// No more actions, so we need to select
_selecting = true;
return null;
}
}
//***重点*** 如果是生产者生成的任务,直接返回,交给 ExecutionStrategy来执行
if (action instanceof Product)
return action;
// Running the change may queue another action.
// 执行任务,或许会产生新的任务入队。
runChange(action);
}
}
private void runChange(Runnable change)
{
try
{
change.run();
}
catch (Throwable x)
{
x.printStackTrace();
}
}
private void update()
{
for (SelectionKey key : _keys)
updateKey(key);
_keys.clear();
}
private void updateKey(SelectionKey key)
{
Object attachment = key.attachment();
if (attachment instanceof SelectableEndPoint)
((SelectableEndPoint)attachment).updateKey();
}
//重新进行选择。。。。。。
private boolean select()
{
try
{
Selector selector = _selector;
if (selector != null && selector.isOpen())
{
int selected = selector.select();
try (SpinLock.Lock lock = _lock.lock())
{
// finished selecting
_selecting = false;
}
_keys = selector.selectedKeys();
_cursor = _keys.iterator();
return true;
}
}
catch (Throwable x)
{
closeNoExceptions(_selector);
}
return false;
}
}
接着看ManagedSelector里的run()方法,它直接调用_strategy.execute();这里的ExecutionStrategy具体的execute实现是ExecuteProduceRun。这里不帖代码,篇幅太长了。主要是循环的调用_producer.produce()产生任务,并执行任务;
最后介绍SelectorManager,主要是用来管理ManagedSelector。它主要是保存了对ManagedSelector数组的引用,同时也引用了一个线程池,用来执行ManagedSelector。SelectorManager实现了 LifeCycle接口,它在doStart方法中对ManagedSelector数组初始化,并在线程池里执行初始化好的ManagedSelector,具体代码如下:
protected void doStart() throws Exception
{
super.doStart();
for (int i = 0; i < _selectors.length; i++)
{
ManagedSelector selector = newSelector(i);
_selectors[i] = selector;
selector.start();
execute(selector);
}
}
还有写地方理解不是很深入,有些地方理解的可能不正确,大家结合源码校验下。。。。。。。待续
转发请标注来源: http://my.oschina.net/robinyao/blog/403615
END-------------------------------