bthread是brpc使用的M:N线程库,目的是在提高程序的并发度的同时,降低编码难度,并在核数日益增多的CPU上提供更好的scalability和cache locality。

”M:N“是指M个bthread会映射至N个pthread,一般M远大于N。

由于linux当下的pthread实现(NPTL)是1:1的,M个bthread也相当于映射至N个LWP。bthread的前身是Distributed Process(DP)中的fiber,一个N:1的合作式线程库,等价于event-loop库,但写的是同步代码。

一.常见线程模型

1. 单线程reactor

N:1线程库,其处理流程如下所示:

缺点:
(1)各个回调之间会相互影响,如上图的callback2和callback3必须要等到callback1完成后才能进行。
(2)无法利用多核。
优点:无需加锁。

2. 多线程reactor

M:N线程库,其处理流程如下所示:

可以利用多核,可以共享地址空间,具有较好的性能,但并不能获得线性于CPU核数的性能扩展;

Removable by ET:使用边缘触发能减少就绪fd的数量,来降低开销;
Highly contended:reactor线程既要处理连接请求,又要处理线程池中线程的读写请求;
Cache bouncing:一个请求的处理会跨越不同的线程,cpu cache同步是微秒级的操作。

二.协程(coroutine)介绍

我们常说的协程特指N:1线程库,即所有的协程运行于一个系统线程中,计算能力和各类eventloop库等价

由于不跨线程,协程之间的切换不需要系统调用,可以非常快(100ns-200ns),受cache一致性的影响也小。但代价是协程无法高效地利用多核,代码必须非阻塞,否则所有的协程都被卡住,对开发者要求苛刻。

协程的这个特点使其适合写运行时间确定的IO服务器,典型如http server,在一些精心调试的场景中,可以达到非常高的吞吐。

但百度内大部分在线服务的运行时间并不确定,且很多检索由几十人合作完成,一个缓慢的函数会卡住所有的协程。在这点上eventloop是类似的,一个回调卡住整个loop就卡住了,比如ubaserver(注意那个a,不是ubserver)是百度对异步框架的尝试,由多个并行的eventloop组成,真实表现糟糕:回调里打日志慢一些,访问redis卡顿,计算重一点,等待中的其他请求就会大量超时。

三. bthread介绍

bthread是一个M:N线程库,一个bthread被卡住不会影响其他bthread。
关键技术两点: work stealing调度和butex。前者让bthread更快地被调度到更多的核心上。后者让bthread和pthread可以相互等待和唤醒。
因为单线程原因,这两点协程都不需要。
(1)优点:
• 用户可以延续同步的编程模式,能在数百纳秒内建立bthread,可以用多种原语同步。
• bthread所有接口可在pthread中被调用并有合理的行为,使用bthread的代码可以在pthread中正常执行。
• 能充分利用多核。
(2)特征:

1. bthread和pthread worker如何对应?

pthread worker在任何时间只会运行一个bthread,当前bthread挂起时,pthread worker先尝试从本地runqueue弹出一个待运行的bthread,若没有,则随机偷另一个worker的待运行bthread,仍然没有才睡眠并会在有新的待运行bthread时被唤醒。

2. bthread中能调用阻塞的pthread或系统函数吗?

可以,只阻塞当前pthread worker。其他pthread worker不受影响。

3. 一个bthread阻塞会影响其他bthread吗?

不影响。若bthread因bthread API而阻塞,它会把当前pthread worker让给其他bthread。若bthread因pthread API或系统函数而阻塞,当前pthread worker上待运行的bthread会被其他空闲的pthread worker偷过去运行。

4. pthread中可以调用bthread API吗?

可以。bthread API在bthread中被调用时影响的是当前bthread,在pthread中被调用时影响的是当前pthread。使用bthread API的代码可以直接运行在pthread中。

5. 若有大量的bthread调用了阻塞的pthread或系统函数,会影响RPC运行么?

会。比如有8个pthread worker,当有8个bthread都调用了系统usleep()后,处理网络收发的RPC代码就暂时无法运行了。只要阻塞时间不太长, 这一般没什么影响, 毕竟worker都用完了, 除了排队也没有什么好方法. 在brpc中用户可以选择调大worker数来缓解问题, 在server端可设置ServerOptions.num_threads或-bthread_concurrency, 在client端可设置-bthread_concurrency.

那有没有完全规避的方法呢?

  • 一个实际的解决方法是限制最大并发, 只要同时被处理的请求数低于worker数, 自然可以规避掉"所有worker被阻塞"的情况。
  • 另一个解决方法当被阻塞的worker超过阈值时(比如8个中的6个), 就不在原地调用用户代码了, 而是扔到一个独立的线程池中运行. 这样即使用户代码全部阻塞, 也总能保留几个worker处理rpc的收发。

四. 判断使用同步或异步

计算qps * latency(in seconds),如果和cpu核数是同一数量级,就用同步,否则用异步。
比如:
• qps = 2000,latency = 10ms,计算结果 = 2000 * 0.01s = 20。和常见的32核在同一个数量级,用同步。
• qps = 100, latency = 5s, 计算结果 = 100 * 5s = 500。和核数不在同一个数量级,用异步。
• qps = 500, latency = 100ms,计算结果 = 500 * 0.1s = 50。基本在同一个数量级,可用同步。如果未来延时继续增长,考虑异步。

这个公式计算的是并发数,和线程数,cpu核数是可比的。

  • 当这个值远大于cpu核数时,说明大部分操作并不耗费cpu,而是让大量线程阻塞着,使用异步可以明显节省线程资源(栈占用的内存)。
  • 当这个值小于或和cpu核数差不多时,异步能节省的线程资源就很有限了,这时候简单易懂的同步代码更重要。

五. bthread应用场景,bthread或异步?

  • 协程适合的场景:适合写运行时间确定的IO服务器,典型如http server,在一些精心调试的场景中,可以达到非常高的吞吐。
  • 异步即用回调代替阻塞,有阻塞的地方就有回调。由于在协程在io阻塞时,会进行切换,io完成后,又回调,它是一种异步处理模式。
  • brpc中的异步和单线程的异步是完全不同的,异步回调会运行在与调用处不同的线程中,你会获得多核扩展性,但代价是你得意识到多线程问题。

有了bthread这个工具,用户甚至可以自己实现异步。以“半同步”为例,在brpc中用户可以这样使用:发起多个异步RPC后挨个Join,这个函数会阻塞直到RPC结束。

结论:

延时不高时你应该先用简单易懂的同步接口,不行的话用异步接口,只有在需要多核并行计算时才用bthread。

延时不长,qps不高时,我们更建议使用同步接口,这也是创建bthread的动机:维持同步代码也能提升交互性能。
如果仅仅是为了并发RPC,别用bthread。

brpc线程模型学习相关推荐

  1. brpc源码分析——线程模型

    brpc线程模型 从一个server的启动过程谈起,我们这里以echo server为例: int main(int argc, char* argv[]) {// gflags介绍:https:// ...

  2. Netty学习(三):Netty线程模型和代码示例

    〇.前言 网络编程的基本线程模型,详见:Netty学习(二):线程模型 一.工作原理简图 Netty主要基于主从 Reactors 多线程模型(如下图) 做了一定的改进,其中主从Reactor 多线程 ...

  3. srs代码学习(2)- 线程模型

    代码阅读到现在.发现srs有两大类线程.一个是主线程的逻辑. 一个是监听线程簇.结构图如下 一定还有第三种线程模型,负责底层的多路分发.今天还没有发现. 2016.08.25--21:00 仔细阅读了 ...

  4. mongodb线程池_常用高并发网络线程模型设计及MongoDB线程模型优化实践

    服务端通常需要支持高并发业务访问,如何设计优秀的服务端网络IO工作线程/进程模型对业务的高并发访问需求起着至关重要的核心作用. 本文总结了了不同场景下的多种网络IO线程/进程模型,并给出了各种模型的优 ...

  5. Android系统Surface机制的SurfaceFlinger服务的线程模型分析

    在前面两篇文章中,我们分析了SurfaceFlinger服务的启动过程以及SurfaceFlinger服务初始化硬件帧缓冲区的过程.从这两个过程可以知道,SurfaceFlinger服务在启动的过程中 ...

  6. C#高性能大容量SOCKET并发(十):SocketAsyncEventArgs线程模型

    原文:C#高性能大容量SOCKET并发(十):SocketAsyncEventArgs线程模型 线程模型 SocketAsyncEventArgs编程模式不支持设置同时工作线程个数,使用的NET的IO ...

  7. Netty和RPC框架线程模型分析

    <Netty 进阶之路>.<分布式服务框架原理与实践>作者李林锋深入剖析Netty和RPC框架线程模型.李林锋已在 InfoQ 上开设 Netty 专题持续出稿,感兴趣的同学可 ...

  8. Netty 和 RPC 框架线程模型分析

    https://www.infoq.cn/article/9Ib3hbKSgQaALj02-90y 1. 背景 1.1 线程模型的重要性 对于 RPC 框架而言,影响其性能指标的主要有三个要素: I/ ...

  9. 线程模型、pthread 系列函数 和 简单多线程服务器端程序

    一.线程有3种模型,分别是N:1用户线程模型,1:1核心线程模型和N:M混合线程模型,posix thread属于1:1模型. (一).N:1用户线程模型 "线程实现"建立在&qu ...

最新文章

  1. linux中将文本中的单词换掉的指令_为什么说从PDF中提取文本是一件困难的事?...
  2. Android每周一个学习计划——RxJava2 0的学习使用
  3. android studio转载文章
  4. 【Java Web】Myeclipse下运用maven管理项目jar包
  5. 如何让自己的网站快速被百度搜索引擎搜索到
  6. 存储过程或视图的字符串查询
  7. Shell 变量的操作方法
  8. php中有两个美元符号$$的变量——可变变量
  9. 用户登录python_python用户登录系统
  10. 【课程复习+记录】最优化理论与方法
  11. 医院耗材管理系统开发_7
  12. C语言typedef用法详解
  13. php临时终止,PHP终止脚本执行的方法介绍
  14. 分享若何利用博客做外链的心得寻味
  15. uniapp 即时通讯_uniapp中与webview的即时通讯
  16. numpy_abs和fabs
  17. css-盒子模型border-box
  18. IAR使用方法建立工程文件超详细操作步骤
  19. CF1525C Robot Collisions(思维,类似括号匹配)
  20. VR全景航拍补天教程

热门文章

  1. 小程序 正整数与char(character)的相互转换,十六进制与十进制相互转换
  2. 张蕾:北斗链将重新回到技术研发的道路上
  3. orgchart实现组织结构图
  4. 检测钻石的边缘,以及确定钻石顶点的位置
  5. 《用户至上:用户研究方法与实践(原书第2版)》一导读
  6. ANSYS多孔结构 多孔材料 孔隙结构建模教程
  7. 3位领导2把椅子,应对类似情况的标准答案
  8. SEO优化人员必备的几种关键词优化工具_零距离seo
  9. 树莓派4B启动失败之原因排查及解决方案
  10. 华为携手思迈特软件成立BYOD移动办公联盟