项目中用到的设计模式:Reactor设计模式

今天实在百无聊赖的看着代码,实在是没有意思,项目还要等到下个月启动,突然发现项目中的设计模式

挺有趣的,就翻出来看看。


因为我们项目中的结构是客户端-服务端,cs结构的,然后他们之间的通信,是怎么回事情的呢?

以前粗略的看了,主要是通过tcp\ip方式进行通信,但是至少概念中知道吧。今天就翻看一下server代码。


先来了解一下什么是reactor设计模式,反应堆模式。


高性能I/O设计模式 - Reactor

该设计模式用于派发/分离IO操作事件的,这里所谓的IO事件也就是诸如read/write 的IO操作,“派发\分离”就是将单独的IO事件通知到上层模块,Reactor用于同步IO。


Reactor设计模式中的要素如下:
Handles,也就是网络连接,文件句柄等。是事件源。
Synchronous Event Demultiplexer,同步事件的解复用(或者说派发),具体的比如select调用。比select更加高效的有linux下的epoll,freebsd下的kqueue以及windows下的iocp(IO Completion port)。
Initiation Dispatcher,注册、移除和分派事件处理句柄。
Event Handler,就是事件处理句柄。


结合上面的描述,给出来自参考资料[3]图片如下:





下面这个是项目中的类图:



1.reactor 负责响应IO事件,一旦发生,广播到响应的TcpThreadPool,TcpThreadPool发送给响应的IHandleEvent实现类去处理。


2. handler是非阻塞行为,同时负责将handlers与event事件绑定。


这里是refactor的handEvent方法;



	public int handleEvent(long wtime)
	{
		PendingObj handler = null;
		while ( (handler = _pendingQueue.pop()) != null)
		{					 	
			if (handler.handler == null) continue;
			switch (handler.type)
			{
				case ACP_TYPE:
					try
					{
						initServerChannel(handler);
					}
					catch (Exception e)
					{
						Debug.logOut(Debug.ERROR,this,e);
					}
					break;
				case CON_TYPE:
					try
					{
						initClientChannel(handler);
					}
					catch (Exception e)
					{
						Debug.logOut(Debug.ERROR,e);
					}
					break;
				default:
					try
					{
						updateSelectCol(handler);
					}
					catch (Exception e)
					{
						Debug.msg(Debug.ERROR,"updateSelectCol occur exception:",e.getMessage());
						Debug.logOut(Debug.ERROR,e);
					}
				  break;
			}
		}

		//		long cur = System.currentTimeMillis();
		//		long to = timequeue.earliestTime();
		//		long cal = to - cur;
		//		if (wtime > cal)
		//		wtime = cal;
		int num;
		this.wakenUp.set(false);
		try
		{
			if (wtime <= 0)
				num = selector.selectNow();  // no here,and not permit walking here,or else cpu 100%
			else
				num = selector.select(wtime);
		}
		catch (Exception e)
		{
			Debug.msg(Debug.ERROR,"selector occur exception:",e.getMessage());
			Debug.logOut(Debug.ERROR,e);
			return -1;
		}
		//		timequeue.dispatchHandlers();

		if (num <= 0) return num;	
		try
		{
			Iterator iterator = selector.selectedKeys().iterator();
			while (iterator.hasNext())
			{
				SelectionKey key = (SelectionKey) iterator.next();
				iterator.remove();
				IHandleEvent handlers = (IHandleEvent) key.attachment();
				int r1 = 0;
				if (! key.isValid()) continue;
				else if (key.isAcceptable())  // for server
				{
					r1 = handlers.handleAccept();
				}
				else if (key.isConnectable()) // 处理前一定要禁止任何操作
				{
					key.interestOps(key.interestOps() & ~key.readyOps());
					r1 = handlers.handleConnect();
				}
				else if (key.isReadable())
				{
					do
					{
						r1 = handlers.handleInput();
					} while (r1 > 0);
				}
				else if (key.isWritable())
				{
					if (pool != null )
					{
						TcpWorker worker = null;
						if (((TCPLink)handlers).isBusy) continue;
						else if ((worker = pool.getIdleWorker()) == null)		
						{
							try
							{
								Thread.sleep(1000);
							}
							catch (InterruptedException e)
							{
								Debug.msg(Debug.ERROR,e.getMessage());
								Thread.interrupted();
							}
							_pendingQueue.put(new PendingObj(handlers,SelectionKey.OP_WRITE,ADD_TYPE ));	
						}
						else 
							worker.setHandler(handlers);
						continue ;
					}

					int count = 0;
					do
					{
						r1 = handlers.handleOutput(); 
						count++;
						if (count > 3) break; 
					} while (r1 > 0); //连续写,r1为0时发送队列数据为空;here将来可考虑多线程
				}

				if (r1 < 0)
				{
					unregister(handlers,true);
				}
			}
		}
		catch (Exception e)
		{
			Debug.msg(Debug.ERROR,"SelectionKey occur runtime exception:",e);
			return -1;
		}
		return num;
	}



这些都是公司大牛写的,真的博大精深,感觉自己要学的东西太多啦。

相关文章

react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接...
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc ...