一个简单基于LRU连接检测实现
2013-04-08 22:42
483 查看
在做网络应用的时候经常要处理不处于活动的连接,对于不活动的TCP连接可以通过设置KeepAlive来触发SocketError来处理掉.但有更多的时候是使用ping和pong来处理.对于ping,pong这种做法的发起者有两种情况,分别是由server或client发起.对于由服务器发起比较损耗资源毕竟每隔一段时间都要向整个连接列发送ping,当累计到定数量没得到pong回应用的时候杀死;而对于Client发起的话server只需要记录ping时间即可,隔一段时间没有得到ping的client杀死.但两种做法似乎都要对连接列表进行一次扫描,存在大量活动连接的时候这种做法似乎并不理想.
其实可以通过一个LRU算法简单地把活动连接前置,那在处理的时候只需要关心不活动的连接即可以,LRU算法大概如下:
LRU(least recently used)。
假设 序列为 4 3 4 2 3 1 4 2
物理块有3个 则
首轮 4调入内存 4
次轮 3调入内存 3 4
之后 4调入内存 4 3
之后 2调入内存 2 4 3
之后 3调入内存 3 2 4
之后 1调入内存 1 3 2(因为最近最久未使用的是4,所以丢弃4)
之后 4调入内存 4 1 3(原理同上)
最后 2调入内存 2 4 1
可以通过一个简单的链接来完成上面功能,当某个项目接收到ping的时候,移到链表头即可以.在扫链表的时候只需要由尾部扫起,值到某个值不存在超时的时候就可以停止扫描.
通过LRU就能做到在活跃连接比较多的情况有比较好的处理效果,由于链表在找值的时候必须要扫一次,所以当连接更新在链表中寻找相应的值成本是不太划算的.可以通过制订一个双向引用的结构来解决寻找问题.
制定一个应用接口和相应的节点类型.通过这个接口规范就可以方便定位到链表的节点上.
当一个项更新的时候就不再需要遍历链表查询,这样就能节省大量查询上的损耗.当然一个完整的LRU检测机制不是要一个timer来驱动,完全代码如下:
其实可以通过一个LRU算法简单地把活动连接前置,那在处理的时候只需要关心不活动的连接即可以,LRU算法大概如下:
LRU(least recently used)。
假设 序列为 4 3 4 2 3 1 4 2
物理块有3个 则
首轮 4调入内存 4
次轮 3调入内存 3 4
之后 4调入内存 4 3
之后 2调入内存 2 4 3
之后 3调入内存 3 2 4
之后 1调入内存 1 3 2(因为最近最久未使用的是4,所以丢弃4)
之后 4调入内存 4 1 3(原理同上)
最后 2调入内存 2 4 1
可以通过一个简单的链接来完成上面功能,当某个项目接收到ping的时候,移到链表头即可以.在扫链表的时候只需要由尾部扫起,值到某个值不存在超时的时候就可以停止扫描.
通过LRU就能做到在活跃连接比较多的情况有比较好的处理效果,由于链表在找值的时候必须要扫一次,所以当连接更新在链表中寻找相应的值成本是不太划算的.可以通过制订一个双向引用的结构来解决寻找问题.
/// <summary> /// 连接描述接口 /// </summary> public interface IConnecton { /// <summary> /// 获取对应在LRU算法中的节点 /// </summary> LinkedListNode<LRUDetect.Node> Node { get; set; } /// <summary> /// 超时操作,当LRU算法检测到应该连接超时的时候会调用该方法 /// </summary> void TimeOut(); } /// <summary> /// 节点信息 /// </summary> public class Node { /// <summary> /// 最后活动时间 /// </summary> public int LastActiveTime; /// <summary> /// 相关连接信息 /// </summary> public IConnecton Connection; /// <summary> /// 检测是否过期 /// </summary> /// <param name="cutime"></param> /// <param name="timeout"></param> /// <returns></returns> public bool Detect(int cutime, int timeout) { return Math.Abs(cutime - LastActiveTime) > timeout; } }
制定一个应用接口和相应的节点类型.通过这个接口规范就可以方便定位到链表的节点上.
public void Update(IConnecton connection) { lock (this) { LinkedListNode<LRUDetect.Node> node = connection.Node; if (node != null) { node.Value.LastActiveTime = Environment.TickCount; mLinkedList.Remove(node); mLinkedList.AddFirst(node); } else { node = mLinkedList.AddFirst(new Node()); node.Value.LastActiveTime = Environment.TickCount; node.Value.Connection = connection; connection.Node = node; } } }
当一个项更新的时候就不再需要遍历链表查询,这样就能节省大量查询上的损耗.当然一个完整的LRU检测机制不是要一个timer来驱动,完全代码如下:
/// <summary> /// 基于LRU算法的连接检测 /// </summary> public class LRUDetect : IDisposable { /// <summary> /// 构建检测器 /// </summary> /// <param name="timeout">超时时间以毫秒为单位</param> public LRUDetect(int timeout) { mTimeout = timeout; mTimer = new System.Threading.Timer(OnDetect, null, mTimeout, mTimeout); } private int mTimeout; private System.Threading.Timer mTimer; private LinkedList<Node> mLinkedList = new LinkedList<Node>(); /// <summary> /// 更新连接 /// </summary> /// <param name="connection">连接信息</param> public void Update(IConnecton connection) { lock (this) { LinkedListNode<LRUDetect.Node> node = connection.Node; if (node != null) { node.Value.LastActiveTime = Environment.TickCount; mLinkedList.Remove(node); mLinkedList.AddFirst(node); } else { node = mLinkedList.AddFirst(new Node()); node.Value.LastActiveTime = Environment.TickCount; node.Value.Connection = connection; connection.Node = node; } } } /// <summary> /// 删除连接 /// </summary> /// <param name="connection">连接信息</param> public void Delete(IConnecton connection) { lock (this) { LinkedListNode<LRUDetect.Node> node = connection.Node; if (node != null) { node.Value.Connection = null; mLinkedList.Remove(node); } } } private void OnDetect(object state) { lock (this) { int cutime = Environment.TickCount; LinkedListNode<Node> last = mLinkedList.Last; while (last != null && last.Value.Detect(cutime, mTimeout)) { last.Value.Connection.TimeOut(); last.Value.Connection = null; mLinkedList.RemoveLast(); last = mLinkedList.Last; } } } /// <summary> /// 连接描述接口 /// </summary> public interface IConnecton { /// <summary> /// 获取对应在LRU算法中的节点 /// </summary> LinkedListNode<LRUDetect.Node> Node { get; set; } /// <summary> /// 超时操作,当LRU算法检测到应该连接超时的时候会调用该方法 /// </summary> void TimeOut(); } /// <summary> /// 节点信息 /// </summary> public class Node { /// <summary> /// 最后活动时间 /// </summary> public int LastActiveTime; /// <summary> /// 相关连接信息 /// </summary> public IConnecton Connection; /// <summary> /// 检测是否过期 /// </summary> /// <param name="cutime"></param> /// <param name="timeout"></param> /// <returns></returns> public bool Detect(int cutime, int timeout) { return Math.Abs(cutime - LastActiveTime) > timeout; } } /// <summary> /// 释放对象 /// </summary> public void Dispose() { if (mTimer != null) { mTimer.Dispose(); mLinkedList.Clear(); } } }
相关文章推荐
- 一个简单基于LRU连接检测实现
- 基于LRU算法的连接检测实现
- 基于akka与scala实现一个简单rpc框架
- 简单实现一个人脸检测器(HOG+SVM实现人脸检测)
- Java学习3:基于Intellij IDEA实现一个简单Servlet
- 分享一个简单的unityAI框架,基于神经网络和遗传算法,可以简单的实现自成长的游戏对象
- 三分钟实现一个插件平台和一个插件——基于最简单的OSGi.NET插件框架
- 基于C#中的Trace实现一个简单的日志系统
- HTML5基于Tomcat 7.0实现WebSocket连接并实现简单的实时聊天
- 基于JAVA集合框架实现一个简单的学生管理系统
- 基于Java web服务器简单实现一个Servlet容器
- C语言连接到数据库实现一个具有简单的client端功能
- 简单实现了一个基于redis的分布式锁,存在bug...
- 一个C++基于boost简单实现的线程池
- Java实现一个简单的RPC框架(五) 基于Socket的传输层实现
- Rhyme/ 手写服务器 实现一个基于xml解析的简单的Tomcat服务器
- [J2EE]实现一个最简单的基于Servlet的web程序
- 分享一个基于长连接+长轮询+原生的JS及AJAX实现的多人在线即时交流聊天室
- ADO.Net实现非连接的简单分页方法(DataAdapter.Fill重载中的一个).
- 基于tcp的c/s模型的一个简单的socket实现