高扩展的基于NIO的服务器架构(二)

接上文高扩展的基于NIO的服务器架构

Reactor模式

如下图所示,将不同事件的检测分离开,当一种事件发生时一个事件处理器EventHandler将通知与该事件处理相对应的专用工作线程

采用这种架构,连接的通道不得不注册在一个Selector上。这样才能通过调用register方法使通道有效。

未完待续

...
SocketChannel channel = serverChannel.accept();
channel.configureBlocking(false);

// register the connection
SelectionKey sk = channel.register(selector, SelectionKey.OP_READ);
...


 为了达到检测新事件的目的,Selector类具备向已注册channel所要它们的就绪事件的能力。通过调用select方法,Selector类收集到了已注册channel的就绪事件。在至少这些就绪事件中的一个事件已经完成之前,select方法是处于阻塞状态下的。这种情况下,select方法返回截至最后一次调用select方法时已经对I/O操作做好准备的连接的数量值。

已选择的连接可以通过调用Selector类的selectedKey方法被检索到。selectedKey方法会返回SelectionKey对象的一个结果集,这些结果集保持了IO事件的状态和连接的Channel的引用。

Selector被Dispatcher控制 。Dispatcher是一个单线程的类。与Selector是组合关系。Dispatcher类负责检索事件以及调遣处理所消耗的调度事件的EventHandler。通过循环,Dispatcher类调用Selector类的select方法来等待新事件。当新的事件进来时,select方法返回,同时先关联的channel通过调用selectedKeys方法被收回。

...
while (isRunning) {

	// blocking call, to wait for new readiness events
	int eventCount = selector.select();
	
	// get the events
	Iterator<SelectionKey> it = selector.selectedKeys().iterator();
	
	while(it.hasNext()) {
	
		SelectionKey key = it.next();
		it.remove();
		
		// readable event?
		if (key.isValid() && key.isReadable()) {
		
			eventHandler.onReadableEvent(key.channel());
		
		}
		
		// writable event?
		if (key.isValid() && key.isWritable()) {
		
			key.interestOps(SelectionKey.OP_READ);
			eventHandler.onWriteableEvent(key.channel());
		
		}
	
		...
	
	}
	
	...

}


像准备写或者准备读这样的事件,Dispatcher会调用EventHandler来处理。EventHandler负责解码请求数据,处理所需的服务活动,编码相应数据。由于工作线程为等待新的请求而而浪费事件,可扩展性和吞吐量的瓶颈只取决于系统资源如CPU或内存。因为需要线程切换好同步,响应时间上会逊色于传统的每个线程负责一个连接的架构。而这种事件驱动方式的架构是用来减少同步,优化线程管理,因此,这方面的开销忽略不计。

未完待续

 

posted on 2013-11-18 11:32  我的小人生  阅读(300)  评论(0编辑  收藏  举报