拆开Ceph看队列和线程
作者:吴香伟 发表于 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看队列和线程的更多相关文章
- 【Java并发】并发队列与线程池
		
并发队列 阻塞队列与非阻塞队 ConcurrentLinkedQueue BlockingQueue ArrayBlockingQueue LinkedBlockingQueue PriorityBl ...
 - 多线程多进程学习threading,queue线程安全队列,线程间数据状态读取。threading.local() threading.RLock()
		
http://www.cnblogs.com/alex3714/articles/5230609.html python的多线程是通过上下文切换实现的,只能利用一核CPU,不适合CPU密集操作型任务, ...
 - 自定义ThreadPoolExecutor带Queue缓冲队列的线程池 + JMeter模拟并发下单请求
		
.原文:https://blog.csdn.net/u011677147/article/details/80271174 拓展: https://github.com/jwpttcg66/GameT ...
 - 【Java】PS-查看Java进程-线程数
		
PS-查看Java进程-线程数 ps 线程 个数_百度搜索 查看进程的线程数命令 - CSDN博客 java命令行运行jar里的main类 - coderland - 博客园
 - python队列、线程、进程、协程
		
目录: 一.queue 二.线程 基本使用 线程锁 自定义线程池 生产者消费者模型(队列) 三.进程 基本使用 进程锁 进程数据共享 默认数据不共享 queues array Manager.dict ...
 - 6、TensorFlow基础(四)队列和线程
		
队列和线程 和 TensorFlow 中的其他组件一样,队列(queue)本身也是图中的一个节点,是一种有状态的节点,其他节点,如入队节点(enqueue)和出队节点(dequeue),可以修改它的内 ...
 - python队列、线程、进程、协程(转)
		
原文地址: http://www.cnblogs.com/wangqiaomei/p/5682669.html 一.queue 二.线程 #基本使用 #线程锁 #自定义线程池 #生产者消费者模型(队列 ...
 - exe崩溃用windbgattach后有宝贵现场,可看程序退出线程等,千万不要清屏
		
exe崩溃用windbgattach后有宝贵现场,可看程序退出线程等,千万不要清屏
 - 从JDK源码角度看java并发线程的中断
		
线程的定义给我们提供了并发执行多个任务的方式,大多数情况下我们会让每个任务都自行执行结束,这样能保证事务的一致性,但是有时我们希望在任务执行中取消任务,使线程停止.在java中要让线程安全.快速.可靠 ...
 
随机推荐
- Javascript隔离方法
			
1.常用的隔离方法: (function() { })(); 2.query的隔离方法: 需要引入jquery: <script type="text/javascript" ...
 - html中的图片、css、js等路径加载问题
			
网页文件的存取路径有3种:物理路径.绝对路径和相对路径. 物理路径就是你的文件放在主机上的具体位置,例如:D:\\image\\1.jpg 这种格式,该方法可以很快确定出你的文件,但是在网页显示路径基 ...
 - slf4j与logback对接是如何将日志写到控制台的
			
今天一个以前同事问了个RT的问题 我翻了下代码,简单跟了下 很简单 1. demo代码 package org.simonme.demo.log; import org.slf4j.Logger; i ...
 - MQ-2烟雾传感器启动
			
MQ-2气体传感器所使用的气敏材料是在清洁空气中电导率较低的二氧化锡(SnO2).当传感器所处环境中 存在可燃气体时,传感器的电导率随空气中可燃气体浓度的增加而增大.使用简单的电路即可将电导率的 变化 ...
 - UIAlertController 自定义输入框及KVO监听
			
UIAlertController极大的灵活性意味着您不必拘泥于内置样式.以前我们只能在默认视图.文本框视图.密码框视图.登录和密码输入框视图中选择,现在我们可以向对话框中添加任意数目的UITextF ...
 - WCF应用场景
			
WCF全称Windows Communication Foundation,是Microsoft为构建面向服务的应用提供的分布式通信编程框架,是.NET Framework 3.5的重要组成部分.使用 ...
 - Uber广州车主官网本周将暂关闭
			
Uber广州车主官网本周将暂关闭 http://news.southcn.com/g/2015-05/04/content_123509931.htm
 - mysql5.7创建账户并授权
			
CREATE USER 'jeffrey'@'localhost' IDENTIFIED BY 'mypass'; GRANT ALL ON db1.* TO 'jeffrey'@'localhost ...
 - EntityFrameWork分页
			
EF分页代码 using System; using System.Collections.Generic; using System.Linq; using System.Web; using Sy ...
 - radiobutton设置样式
			
单选题里会用到radiobutton,如果不想使用系统提供的圆圈样式,可以自定义样式,想要做成的效果就是, 使用自定义的图片替换圆圈,然后选择有4个选项的其中一个,图片上有个对勾标记, 然后如果正确选 ...