zoukankan      html  css  js  c++  java
  • brpc线程模型学习(转)

    转自:https://blog.csdn.net/okiwilldoit/article/details/82755526

    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。
    ————————————————
    版权声明:本文为CSDN博主「okiwilldoit」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/okiwilldoit/article/details/82755526

    联系方式:emhhbmdfbGlhbmcxOTkxQDEyNi5jb20=
  • 相关阅读:
    BZOJ1045 [HAOI2008]糖果传递 && BZOJ3293 [Cqoi2011]分金币
    [BZOJ1103][POI2007]大都市meg dfs序+树状数组
    [BZOJ1122][POI2008]账本BBB 单调队列+后缀和
    [BZOJ1131][POI2008]Sta
    [BZOJ1370][Baltic2003]Gang团伙 并查集+拆点
    网易云基于 Kubernetes 的深度定制化实践
    微服务化的基石——持续集成
    微服务的接入层设计与动静资源隔离
    从互联网+角度看云计算的现状与未来(2)
    从互联网+角度看云计算的现状与未来(1)
  • 原文地址:https://www.cnblogs.com/zl1991/p/15133758.html
Copyright © 2011-2022 走看看