Reactor模式的.net版本简单实现--DEMO
近期在学习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 多路复用事件处理器的代码
public class Demultiplexer
{
private ConcurrentQueue<Event> eventQuene = new ConcurrentQueue<Event>();
private Object lockObj = new Object();
public List<Event> Select()
{
return this.Select(0);
}
public List<Event> Select(int time)
{
if(time > 0)
{
if (this.eventQuene.IsEmpty)
{
lock (lockObj)
{
if (this.eventQuene.IsEmpty)
{
System.Threading.Thread.Sleep(time);
}
}
}
}
List<Event> events = new List<Event>();
while(this.eventQuene.Count > 0)
{
Event tmp;
if(this.eventQuene.TryDequeue(out tmp))
{
events.Add(tmp);
}
}
return events;
}
public void AddEvent(Event argEvent)
{
this.eventQuene.Enqueue(argEvent);
}
}
此类主要防止多线程的共同竞争,因为多路径复用选择器会被多个线程同时使用。所以使用的线程安全的Queue。
2.2 Handler触发器和管理器
/// <summary>
/// Reactor的事件Handler触发器,提供事件Handler的注册,移除
/// </summary>
public class EventDispatch
{
private Demultiplexer demultiplexer;
Dictionary<EventType, EventHandler> eventHandlerMap = new Dictionary<EventType, EventHandler>();
public EventDispatch(Demultiplexer demultiplexer)
{
this.demultiplexer = demultiplexer;
}
public void RegisterHandler(EventType eventType, EventHandler eventHandler)
{
this.eventHandlerMap.Add(eventType, eventHandler);
}
public void RemoveHandler(EventType eventType)
{
this.eventHandlerMap.Remove(eventType);
}
public void HandleEvents()
{
this.Dispatch();
}
public void Dispatch()
{
string log = string.Format("thread id: {0} Dispatch", System.Threading.Thread.CurrentThread.ManagedThreadId);
Console.WriteLine(log);
while (true)
{
List<Event> events = this.demultiplexer.Select();
foreach(var itemEvent in events)
{
EventHandler eventHandler = this.eventHandlerMap[itemEvent.EventType];
eventHandler.Handle(itemEvent);
}
System.Threading.Thread.Sleep(1000);
}
}
}
主要职责,对Handler的注册、移除的管理,以及通过 多路复用选择器 选择相应的Handler进行处理。
2.3 服务端的实现
/// <summary>
/// 开启接受请求的服务端
/// </summary>
public class AcceptRuner
{
private System.Collections.Concurrent.ConcurrentQueue<object> sourceQueue = new System.Collections.Concurrent.ConcurrentQueue<object>();
private Demultiplexer demultiplexer;
public AcceptRuner(Demultiplexer demultiplexer)
{
this.demultiplexer = demultiplexer;
}
public void adConnection(object source)
{
this.sourceQueue.Enqueue(source);
}
public void Run()
{
string log = string.Format("thread id: {0} AcceptRunner", System.Threading.Thread.CurrentThread.ManagedThreadId);
Console.WriteLine(log);
while (true)
{
object source;
if(this.sourceQueue.TryDequeue(out source))
{
Event acceptEvent = new Event()
{
EventType = EventType.Accept,
Source = source
};
this.demultiplexer.AddEvent(acceptEvent);
}
}
}
}
此类效仿netty的serverBoostrap的实现,将外部新的连接以事件对象的形式添加到 多路复用选择器上。
2.4 其他类
Event:事件基类
EventHandler:事件处理器抽象基类。他派生了:AcceptEventHandler,ReadEventHandler。
EventType:事件类型
三、备注说明
1. 代码没有贴完整。但下载包就是完整的。
2. 这只我对Reactor模式的理解,如有偏颇之处,还望各拉指点一二。
- 生物信息学技能面试题(第4题)-多个同样的行列式文件合并起来
- PHP 底层的运行机制与原理
- asp.net web api 版本控制
- 如何编写更好的SQL查询:终极指南(上)
- asp.net web api 异常捕获
- asp.net web api 文件上传
- 使用MySQL正则表达式 __MySQL必知必会
- 史上最好用的免费翻蔷利器
- asp.net web api 接口安全与角色控制
- TensorFlow从0到1 | 第十五章 重新思考神经网络初始化
- asp.net web api 下载之断点续传
- apache2.4.x三种MPM介绍
- 没有自己的服务器如何学习生物数据分析(上篇)
- 【直播】我的基因组57:最简陋的祖源分析
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 想后台运行没想到导致磁盘满了
- 来看一道"简单的"C语言面试题
- 这行代码的打印结果确实让人迷惑!
- 如何实现一个高效的启发式算法?(VRPTW篇)
- Ubuntu Server搭建Hyperledger Fabric 2.1学习环境
- 辛辛苦苦学会的 webpack dll 配置,可能已经过时了
- 【程序中的数学】利用德摩根定律简化布尔运算
- Conjob For hybris
- ListView通用泛型适配器
- Android实现C/S聊天室
- OpenCV4.4 CUDA编译与加速全解析
- 如何利用Kotlin实现极简回调
- Android辅助权限的介绍和配置完整记录
- Redis基础——剖析基础数据结构及其用法
- SwipeRefreshLayout+RecyclerView实现上拉刷新和下拉刷新功能