spymemcached源码中Reactor模式分析

简介

spymemcached 是一个 memcached 的客户端, 使用 NIO 实现。采用Reactor模式实现,单线程,高性能Memcached客户端。 java

spymemcached源码分析:http://my.oschina.net/astute/blog/93492 react

Reactor模式介绍

所谓reactor模式,实际上是event-driven pattern在网络服务设计中的应用,以平衡CPU与IO速率,最大化CPU资源与IO资源的利用率; tomcat

先来看看经典的服务器设计: 服务器

经典网络服务接受客户端请求,响应请求过程能够抽象为如下步骤: 网络

  1. 读取请求数据 : read
  2. 解码数据: decode
  3. 计算:compute
  4. 编码数据:encode
  5. 发送数据:send

网络服务全部动做被抽象为这个五个步骤的handler;可能每一个handler有单独线程执行,或者由一个线程顺序执行; 多线程

这种经典设计中存在如下问题: 异步

  1. 每一个链接分配一个线程,而每一个链接发送请求数据较少,致使大量空闲线程;
  2. 大量线程上下文切换和锁竞争

为了解决上述问题,采用两个方法实现: memcached


  1. 采用分治的思想,将链接划分为更小粒度的非阻塞任务:将用户链接划分为 多个用户请求,每一个请求一个线程处理;减小 请求间空闲时间占用线程
  2. 采用事件处理模式,分派可执行任务;经过IO 事件触发 handler 处理


采用事件处理模式的单线程Reactor模式: 源码分析

单线程Reactor 处理 链接请求,全部用户请求都在同一个线程中;经过IO事件触发相应的操做;IO事件触发机制可参考java nio机制; 性能

单线程版本的Reactor模式,还有如下问题:

  1. 触发事件处理 与 处理事件 在同一个线程中;减缓了Reactor的事件触发及时性
  2. 全部请求必须等待以前请求中IO操做以外的处理过程
  3. 没法解决CPU与IO速率不一致问题
  4. 不能有效利用多核优点

为解决上述问题,采用多线程设计方案的Reactor模式:

多线程版本的Reactor模式,有如下优点:

  1. Reactor能够快速触发handler执行
  2. IO操做之外操做由线程池中线程独立处理
  3. Reactor 线程满负荷 IO操做
  4. 平衡CPU 与 IO 速率

reactor模式就介绍到此,具体看下spymemcached中reactor模式的应用吧

spymemcached中Reactor模式实现

spymemcached中reactor模式设计到如下概念:

  1. IO线程:MemcachedConnection 负责处理
  2. 工做线程:调用spymemcached操做的线程;一般是应用线程,例如tomcat线程等等;

工做线程职责:

  1. 经过MemcachedClient提交操做请求给MemcachedConnection
  2. MemachedClient提交操做过程:实例化异步操做回执OperationFuture(该回执都会实例化一个CountDownLatch(1));经过OperationFactory 生成定制Callback操做的Operation对象;将Operation操做加入对应ShardedNode 的inputQ;返回异步结果回执OperationFuture对象
  3. 调用OperationFuture对象的get操做阻塞在CountDownLatch,等待后台IO线程,调用countDown;

IO线程职责:

  1. 由MemcachedClient初始化启动后台MemcachedConnection 线程,接受工做线程提交操做:从inputQ拷贝到writableQ;发送操做请求到Memcached服务器;添加操做到readQ,并把操做从writableQ删除;修改监听IO事件
  2. 执行select操做,获取感兴趣IO事件
  3. 执行handleIO处理:根据SelectKey发生事件类型:执行读取操做 or 写入操做;
  4. 当IO操做完成后,调用Operation Callback对象的receivedStatus设置回执结果;调用countDown释放阻塞的工做线程;

因而可知,spymemcached Reactor模式实现中,工做线程至关于客户端请求; IO线程至关于单线程Reactor设计中的Reactor负责接收请求,处理请求;spymemcached对数据解码部分能够扩展实现线程池方式提供解码计算,无需占用Reactor线程资源,使得Reactor线程满负荷IO操做和事件触发;


在spymemcached的Reactor设计中:

MemcachedClient负责接收请求

MemcachedConnection负责处理IO请求

同时还能够扩展支持线程池TranscodeService对解码计算提供异步线程支持; 这也是OperationFuture.get()返回值仍未一个Futrue,内部再次调用future.get返回最终数据的缘由。

相关文章
相关标签/搜索