作者:吴香伟 发表于 2017/01/08
版权声明:可以任意转载,转载时务必以超链接形式标明文章原始出处和作者信息以及版权声明


我上小学时家离学校很远,家在某某山脚,学校在镇里。每周回家一趟,周五放学后回家,周日带着一星期吃的梅干菜回学校。从家到学校有5公里山路,现在觉得5公里不算长,骑个自行车只要一溜烟的功夫,但那时还小觉得很远。从学校到家的路上零零散散有几个路亭,这些路亭有的建在岔路口,有的建在木桥边,还有的建在转弯处。不同位置的亭子有不同好处,岔路口的宜送别,小桥边的方便在亭里歇个脚后再到桥底洗把脸,转弯处的路亭告诉你前面还有人家。除此之外,路亭还有很多其它功能,下雨天可以供人避雨,艳阳天可以供人乘凉,到了过年过节时还可以供人拜祭各路神仙。对我来说印象最深刻的是期末时在路亭里和小伙伴们相互修改成绩单,开学时相互填家长评语,其乐无穷。

从用户发起请求到数据落盘,Ceph也有很长的IO路径。在这条路径上也同样散落着功能各异的亭子(队列),梅干菜从一个路亭到下一个路亭靠的是两只小脚丫,IO从一个队列到另一个队列靠的是线程(池)。没错,本文要讲的就是路亭和脚夫的故事。不对是队列和线程。

队列和线程的关系

队列和线程在一起,通常称为生产者和消费者模式。生产者向队列添加元素,消费者从队列提取元素。一个队列可以同时拥有多个生产者和多个消费者。

图中的Tgt是改造过的与原生版本略有不同。

Ceph客户端队列

Pending队列

一个Tgt进程有多个Pending队列,一个队列负责来自一个Pool的请求。一个Pending队列只有一个生产者,所有队列共享同一个生产者,这个生产者就是Tgt主线程。Tgt主线程负责接收网络报文,并依据iSCSI协议将报文转换为iSCSI请求。因为要负责接收来自所有Lun的请求,所以主线程并不空闲,如果继续负责请求的处理,必然导致后面的请求不能被及时接收,进而降低Initiator发送请求的速度。网络本来就慢,再延迟接收,将导致性能大大的低。

此时Pending队列起到了缓冲的作用,让主线程只负责请求的接收过程,接收到的请求不用立即处理先缓存到队列,缩短主线程的执行路径从而解决网络请求不能被及时接收的问题。从另一方面来说,Pending队列解耦请求的接收过程和处理过程,将这两个过程分别交给队列的生产者和消费者。

Ok,我们Get到了队列的第一个作用,缓冲,第一个附带作用,解耦。一般在设计队列时考虑缓冲,在分析代码时看解耦。因为有100种解耦方法,队列只是其中之一,解耦并不是设计队列的充分条件。

PointerWq队列

开发者调用Librbd API读写块设备时,请求入PointerWq队列后立即返回给调用者。话音未落,我似乎又Get到了队列的第3个作用:实现异步调用。调用者将请求以及请求结果处理函数一并提交给Rbd层,Rbd层完成请求后回调请求结果处理函数,以此实现异步调用。

PointerWq队列隶属于ImageCtx类,代表一个Image存储块,不论读请求还是写请求都入同个队列。Bs-worker线程池,Pending队列的消费者,PointerWq队列的生产者,主要工作是将一个Pool请求队列分裂成若干个Image请求队列。

Out_q队列

从请求的粒度来看,Image请求在Ceph客户端中有下面几种形态:Image请求、Object请求、Op以及MOsdOp消息。Image请求只关注块设备中的一段区域,一段块设备区域可能对应于多个Object,这些Object可能属于不同PG不同Osd节点。一个Out_q队列对应一个Osd节点,隶属于一个连接,一个OSDSession。

Out_q是个优先级队列(第4个功能),不过对优先级的处理比较粗暴,只有最高优先级的请求全部出队列后才允许次高优先级的请求出队列。Ceph社区中曾有人建议通过请求的优先级来实现QoS,这显然是行不通的,因为特别容易导致低优先级用户饿死。

作为Out_q队列的生产者,Rbd_op_threads线程池的压力不小,一方面默认情况下池中只有一个线程(不知道是怎么考虑的)但要处理所有Image请求;另一方面它处理的逻辑最多,包括在Rbd层把Image请求拆分成Object请求(还要考虑Rbd缓存),在Rados层计算每个Object的目标Osd,以及回调函数的层层封装。虽然事情很多,但总体而言还是计算密集型不存在等待问题。

对Out_q队列的消费者Worker,本文关注的是AsyncMessenger的实现,SimpleMessenger会不一样。Messenger隶属于RadosClient,一个RadosClient实例拥有一个Messenger实例。老版本的SimpleMessenger会为每个连接都创建一个读线程和一个写线程。原生Tgt中为每个存储块创建一个RadosClient对象,一个RadosClient将与一个Osd建立一个连接,一个连接将有两个线程。粗略想想线程数目,心里有点发毛。

AsyncMessenger将工作线程Worker和Messenger解耦,不论有多少个RadosClient实例总线程数目都固定不变。不过和给定Osd节点的连接数还是会随着RadosClient实例的增加递增。一个Worker会同时处理多个连接,主要职责是从队列提取消息发送给Osd进程。

Ceph Osd队列

Osd进程从端口接收数据和Ceph客户端发送数据一样都由Worker线程完成。不同的是,Osd进程是服务端要监听端口。对监听Fd的Worker(处理连接打开和关闭)和属于该监听Fd连接(处理请求接收和响应发送)的Worker是同一个线程。

Osd接收到请求后根据不同的请求类型有两种处理方式:一种是Fast dispatch,要么直接处理掉要么入ShardedOp队列。另一种是入Dispatch队列。客户端读写请求走Fast dispatch路径,命令或者更新OsdMap版本的请求入Dispatch队列。

Mqueue分发队列

Mqueue是个优先级队列。

(待续)

参考资料

源码

拆开Ceph看队列和线程的更多相关文章

  1. 【Java并发】并发队列与线程池

    并发队列 阻塞队列与非阻塞队 ConcurrentLinkedQueue BlockingQueue ArrayBlockingQueue LinkedBlockingQueue PriorityBl ...

  2. 多线程多进程学习threading,queue线程安全队列,线程间数据状态读取。threading.local() threading.RLock()

    http://www.cnblogs.com/alex3714/articles/5230609.html python的多线程是通过上下文切换实现的,只能利用一核CPU,不适合CPU密集操作型任务, ...

  3. 自定义ThreadPoolExecutor带Queue缓冲队列的线程池 + JMeter模拟并发下单请求

    .原文:https://blog.csdn.net/u011677147/article/details/80271174 拓展: https://github.com/jwpttcg66/GameT ...

  4. 【Java】PS-查看Java进程-线程数

    PS-查看Java进程-线程数 ps 线程 个数_百度搜索 查看进程的线程数命令 - CSDN博客 java命令行运行jar里的main类 - coderland - 博客园

  5. python队列、线程、进程、协程

    目录: 一.queue 二.线程 基本使用 线程锁 自定义线程池 生产者消费者模型(队列) 三.进程 基本使用 进程锁 进程数据共享 默认数据不共享 queues array Manager.dict ...

  6. 6、TensorFlow基础(四)队列和线程

    队列和线程 和 TensorFlow 中的其他组件一样,队列(queue)本身也是图中的一个节点,是一种有状态的节点,其他节点,如入队节点(enqueue)和出队节点(dequeue),可以修改它的内 ...

  7. python队列、线程、进程、协程(转)

    原文地址: http://www.cnblogs.com/wangqiaomei/p/5682669.html 一.queue 二.线程 #基本使用 #线程锁 #自定义线程池 #生产者消费者模型(队列 ...

  8. exe崩溃用windbgattach后有宝贵现场,可看程序退出线程等,千万不要清屏

    exe崩溃用windbgattach后有宝贵现场,可看程序退出线程等,千万不要清屏

  9. 从JDK源码角度看java并发线程的中断

    线程的定义给我们提供了并发执行多个任务的方式,大多数情况下我们会让每个任务都自行执行结束,这样能保证事务的一致性,但是有时我们希望在任务执行中取消任务,使线程停止.在java中要让线程安全.快速.可靠 ...

随机推荐

  1. [iOS Animation]-CALayer 图层树

    图层的树状结构 巨妖有图层,洋葱也有图层,你有吗?我们都有图层 -- 史莱克 Core Animation其实是一个令人误解的命名.你可能认为它只是用来做动画的,但实际上它是从一个叫做Layer Ki ...

  2. WINDOWS动态链接库--MFC规则动态链接库

    第一代window程序员使用windows api进行编程,到了后来,微软推出MFC类库,于是,动态链接库进行了升级,可以在动态连接库中使用MFC的API,这就叫做MFC动态链接库, 其中MFC动态链 ...

  3. onchange、oninput、onpropertyChange事件的异同

    onchange事件适用于input\textarea\select元素上,支持各大浏览器,该事件只有在键盘或者鼠标操作改变对象属性,且失去焦点时触发,脚本触发无效: oninput事件适用于inpu ...

  4. 初步了解php,实现注册及登录

    直接上图(数据库是用wamp实现的) 注册页 html 及 php 代码 登陆页 html 及 php 代码

  5. Android学习笔记--处理UI事件

    Handling UI Events 在Android里, 有不只一种方式可以截获用户与你的应用程序交互的事件. 在你的界面上处理事件时,你需要捕获用户与某个View实例交互时所产生的事件.View类 ...

  6. D Vitamin - the wonder vitamin

    原文 Be healthier and happier by spending time in the sun In the dead of winter,we don't typically thi ...

  7. USACO 2015 December Contest, Platinum Problem Max Flow【树链剖分】

    题意比较难理解,就是给你n个点的树,然后给你m个修改操作,每一次修改包括一个点对(x, y),意味着将x到y所有的点权值加一,最后问你整个树上的点权最大是多少. 比较裸的树链剖分了,感谢Haild的讲 ...

  8. driver_register()函数解析

    driver_register()函数解析 /** * driver_register - register driver with bus * @drv: driver to register *  ...

  9. WDA 程序文本翻译OTR

    1.针对直接使用表字段,数据元素的情况: 1.1修改数据元素对应的语言值:DD04T. 1.2模拟SE63插入翻译条目:LXE_LOG 1.3运行时文件翻译条目:DDFTX *&------- ...

  10. mysql中游标的使用案例详解(学习笔记)

    1.游标是啥玩意?简单的说:游标(cursor)就是游动的标识,啥意思呢,通俗的这么说,一条sql取出对应n条结果资源的接口/句柄,就是游标,沿着游标可以一次取出一行.我给大家准备一张图: 2.怎么使 ...