近期在学习DotNetty,遇到不少的问题。由于dotnetty是次netty的.net版本的实现。导致在网上叙述dotnetty的原理,以及实现技巧方面的东西较少,这还是十分恼人的。在此建议学习和使用Dotnetty的和位小伙伴,真心阅读下netty的相关书籍,如《netty权威指南》。
闲话少说,进入正题。netty的性能之所以能够达到如此的高度。主要由于他使用Reactor模式处理socket的请求,让服务器的使用率最大化,且尽量减少线程的开销。本文章主要简单介绍下Reactor模式。
一、reactor概论
reactor模式主要解决处理多个客户端请求的设计模式。

首先从类图我们可以得知:
Dispatcher:Handler管理器,以及调用度。他依赖于Demultiplexer类
Demultiplexer:事件管理器,接受外部的事件,并提供给Dispatch使用。
Handle:事件源,表示触发了那些事件
EventHandler:各种类型的处理器,用于处理具体的业务,以及I/O的读写
当然,也可以通过序列图看出首先需要初始化Dispatcher, Demultiplexer等相关类,以及注册具体的事件处理器。
二、代码的具体实现
类图如下[源码下载]:

2.1 多路复用事件处理器的代码
1public class Demultiplexer 2 { 3 private ConcurrentQueue<Event> eventQuene = new ConcurrentQueue<Event>(); 4 private Object lockObj = new Object(); 5 6 public List<Event> Select() 7 { 8 return this.Select(0); 9 } 10 public List<Event> Select(int time) 11 { 12 if(time > 0) 13 { 14 if (this.eventQuene.IsEmpty) 15 { 16 lock (lockObj) 17 { 18 if (this.eventQuene.IsEmpty) 19 { 20 System.Threading.Thread.Sleep(time); 21 } 22 } 23 } 24 } 25 List<Event> events = new List<Event>(); 26 while(this.eventQuene.Count > 0) 27 { 28 Event tmp; 29 if(this.eventQuene.TryDequeue(out tmp)) 30 { 31 events.Add(tmp); 32 } 33 } 34 return events; 35 } 36 public void AddEvent(Event argEvent) 37 { 38 this.eventQuene.Enqueue(argEvent); 39 } 40 }
此类主要防止多线程的共同竞争,因为多路径复用选择器会被多个线程同时使用。所以使用的线程安全的Queue。
2.2 Handler触发器和管理器
1/// <summary> 2 /// Reactor的事件Handler触发器,提供事件Handler的注册,移除 3 /// </summary> 4 public class EventDispatch 5 { 6 private Demultiplexer demultiplexer; 7 Dictionary<EventType, EventHandler> eventHandlerMap = new Dictionary<EventType, EventHandler>(); 8 9 public EventDispatch(Demultiplexer demultiplexer) 10 { 11 this.demultiplexer = demultiplexer; 12 } 13 14 public void RegisterHandler(EventType eventType, EventHandler eventHandler) 15 { 16 this.eventHandlerMap.Add(eventType, eventHandler); 17 } 18 public void RemoveHandler(EventType eventType) 19 { 20 this.eventHandlerMap.Remove(eventType); 21 } 22 23 public void HandleEvents() 24 { 25 this.Dispatch(); 26 } 27 public void Dispatch() 28 { 29 string log = string.Format("thread id: {0} Dispatch", System.Threading.Thread.CurrentThread.ManagedThreadId); 30 Console.WriteLine(log); 31 while (true) 32 { 33 List<Event> events = this.demultiplexer.Select(); 34 foreach(var itemEvent in events) 35 { 36 EventHandler eventHandler = this.eventHandlerMap[itemEvent.EventType]; 37 eventHandler.Handle(itemEvent); 38 } 39 System.Threading.Thread.Sleep(1000); 40 } 41 } 42 }
主要职责,对Handler的注册、移除的管理,以及通过 多路复用选择器 选择相应的Handler进行处理。
2.3 服务端的实现
1/// <summary> 2 /// 开启接受请求的服务端 3 /// </summary> 4 public class AcceptRuner 5 { 6 private System.Collections.Concurrent.ConcurrentQueue<object> sourceQueue = new System.Collections.Concurrent.ConcurrentQueue<object>(); 7 8 private Demultiplexer demultiplexer; 9 10 public AcceptRuner(Demultiplexer demultiplexer) 11 { 12 this.demultiplexer = demultiplexer; 13 } 14 15 public void adConnection(object source) 16 { 17 this.sourceQueue.Enqueue(source); 18 } 19 20 public void Run() 21 { 22 string log = string.Format("thread id: {0} AcceptRunner", System.Threading.Thread.CurrentThread.ManagedThreadId); 23 Console.WriteLine(log); 24 while (true) 25 { 26 object source; 27 if(this.sourceQueue.TryDequeue(out source)) 28 { 29 Event acceptEvent = new Event() 30 { 31 EventType = EventType.Accept, 32 Source = source 33 }; 34 this.demultiplexer.AddEvent(acceptEvent); 35 } 36 } 37 } 38 }
此类效仿netty的serverBoostrap的实现,将外部新的连接以事件对象的形式添加到 多路复用选择器上。
2.4 其他类
Event:事件基类
EventHandler:事件处理器抽象基类。他派生了:AcceptEventHandler,ReadEventHandler。
EventType:事件类型
三、备注说明
1. 代码没有贴完整。但下载包就是完整的。
2. 这只我对Reactor模式的理解,如有偏颇之处,还望各拉指点一二。