博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
spymemcached源码中Reactor模式分析
阅读量:5847 次
发布时间:2019-06-19

本文共 2037 字,大约阅读时间需要 6 分钟。

hot3.png

简介

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

spymemcached源码分析:

Reactor模式介绍

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

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

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

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

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

这种经典设计中存在以下问题:

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

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

  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返回最终数据的原因。

转载于:https://my.oschina.net/yychao/blog/99873

你可能感兴趣的文章
JQuery this和$(this)的区别及获取$(this)子元素对象的方法
查看>>
关于分区索引与全局索引性能比较的示例
查看>>
沟通:用故事产生共鸣
查看>>
1080*1920 下看网站很爽
查看>>
CMake 构建项目Android NDK项目基础知识
查看>>
MySQL 不落地迁移、导入 PostgreSQL - 推荐 rds_dbsync
查看>>
[Erlang 0004] Centos 源代码编译 安装 Erlang
查看>>
51 Nod 1027 大数乘法【Java大数乱搞】
查看>>
三维重建技术概述
查看>>
AI x 量化:华尔街老司机解密智能投资正确姿势
查看>>
IT史上十大收购案
查看>>
数据切分——Atlas介绍
查看>>
游戏引擎cocos2d-android使用大全
查看>>
oracle job 定时执行参数
查看>>
Android命令Monkey压力测试,详解
查看>>
负载均衡(LB)集群 dr
查看>>
(转)直接拿来用!最火的iOS开源项目(一)
查看>>
div+css+js 树形菜单
查看>>
android EventBus 3.0 混淆配置
查看>>
我的友情链接
查看>>