V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
WinMain
V2EX  ›  问与答

0 生产环境中,生产者速度远远大于消费者速度,该怎么设计?

  •  
  •   WinMain · 2018-02-10 10:44:41 +08:00 · 3405 次点击
    这是一个创建于 2469 天前的主题,其中的信息可能已经有所发展或是发生改变。

    背景:客户端(生产者)发一个请求到后端服务器,服务器需要三个步骤来处理这个请求,第一个是网络 io,需要固定 100ms 左右,第二个是 cpu 密集型的,需要 150ms 左右;第三个也是网络 io,需要 50ms 左右,也就是整个过程平均需要耗时 300ms,而且没法减少这个处理时间。

    处理:不管怎么优化,一个请求耗时 300ms 左右这个是固定的,异步和线程池之类的只能增大并发量对吧。最好的处理办法是不是线程池阻塞队列满的时候,依靠拒绝策略直接 reject 一些请求?要不然处理连接的线程都是阻塞,导致整个程序很快就没法正常工作了。还想过用消息队列,例如 python 的 lecery,但是考虑下生产者速度远远大于消费者,即使任务全部抛到消息队列,后端线程一个一个去拉消息处理,这样其实后面的任务基本是耗时越来越长对吧。

    提问:这种情况只能增加服务器,靠服务器抗住?

    PS:如果用异步的话,想问下,三个过程是分别异步,还是在一个线程里面处理好?

    17 条回复    2018-02-11 16:37:28 +08:00
    legendlzy
        1
    legendlzy  
       2018-02-10 10:48:46 +08:00
    我觉得要根据业务场景吧,如果业务不允许 reject,那就增加服务器咯,如果是类似于秒送那种,就 reject。。。菜鸡的看法
    CFO
        2
    CFO  
       2018-02-10 11:08:58 +08:00 via Android
    背压?
    Cbdy
        3
    Cbdy  
       2018-02-10 11:15:16 +08:00 via Android   ❤️ 1
    如果不是实时性要求很高的场景,用消息队列解耦。最简单的,生产者一个队列(生产请求),消费者一个队列(消费响应)。这样消费跟不上就可以多加几个消费者实例。记得在数据层控制好数据一致性。。
    ovear
        4
    ovear  
       2018-02-10 11:59:59 +08:00 via Android
    两个解决方法
    提高消费能力(包括消费者数目,消费速度,消费能力
    修改模型,采用推拉操作,生产者直接入库,消费者从库中拉出来。当然,会产生堆积。
    feverzsj
        5
    feverzsj  
       2018-02-10 12:05:09 +08:00   ❤️ 1
    用 c++重写
    kslr
        6
    kslr  
       2018-02-10 13:33:31 +08:00
    首先,这要看你这是什么业务,办法还是很多的。
    假如你这个数据模式一样,甚至可以丢弃一部分比较旧的。
    wangxiaoer
        7
    wangxiaoer  
       2018-02-10 13:43:45 +08:00 via Android
    用户请求是生产者
    应用后台是消费者

    生产者远远大于消费者不就是流量过高么,业界主流是加服务器,就是增加消费者数量。

    所以有什么可说的呢
    BruceHong
        8
    BruceHong  
       2018-02-10 14:17:24 +08:00
    最彻底的解决办法只有一种:增加消费者能力。
    binux
        9
    binux  
       2018-02-10 14:26:57 +08:00 via Android
    开流节源
    misaka19000
        10
    misaka19000  
       2018-02-10 14:29:41 +08:00 via Android
    如果对实时性要求不高,那就无所谓,慢慢处理就行了;如果有高性能要求,那么就应该用集群提供处理能力,降低延时
    skadi
        11
    skadi  
       2018-02-10 15:35:13 +08:00
    这种就是性能问题了啊.考虑 c/c++重写关键地方.
    julyclyde
        12
    julyclyde  
       2018-02-10 19:43:30 +08:00
    如果你把各项条件都限制死了,那最后就只能是权衡,而不可能解决了
    sen506
        13
    sen506  
       2018-02-10 22:55:53 +08:00 via iPhone
    你这个主要蛋疼的是有耗 cpu 的操作,这步看下能否单独剥离出去,例如多一个服务专门用线程池来搞,剩下的 io 密集还有与你那个处理 cpu 密集得服务间的通信直接协程或异步搞定。。这样虽然耗时不会减少,但是性能会好很多。。
    sen506
        14
    sen506  
       2018-02-10 23:01:10 +08:00 via iPhone   ❤️ 1
    另外,你这个耗 cpu 操作的时间太长了,看下怎么优化吧,150ms 的话,单线程 1 秒就只能处理 7 个请求。。
    WinMain
        15
    WinMain  
    OP
       2018-02-10 23:29:31 +08:00
    @sen506 嗯 准备弄两个线程池,一个 max 设置小点专门处理网络 IO,另外一个线程弄多点用来跑 CPU 运算的的试试看。
    cchange
        16
    cchange  
       2018-02-11 03:04:35 +08:00 via iPhone
    150ms 可否切割成多个小任务 改为轮寻
    sen506
        17
    sen506  
       2018-02-11 16:37:28 +08:00 via iPhone
    @WinMain 网络 io 不应该用线程池,性能太差了。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5904 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 02:12 · PVG 10:12 · LAX 18:12 · JFK 21:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.