V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
asp1111
V2EX  ›  Java

有个线程池奇怪的问题,不知道有人遇到过没

  •  
  •   asp1111 · 18 天前 · 2117 次点击
    项目背景是消息网关,之前在服务内有两个线程池,一个处理慢消息(处理时间长、数量少),一个处理快消息(处理时间短、数量大),逻辑都是从消息队列里拉消息,如果拉不到就惩罚性 sleep 1s ,随着时间增加看日志竟然发现快消息的线程池处理的消息越来越少,只有慢消息的线程池在运行。现在把线程池分开在两个服务里,看起来问题是消失了。
    这也太奇怪,难道说 jvm 会倾向于运行上下文切换次数少的线程?
    第 1 条附言  ·  18 天前
    服务器的配置是 12 核 48G ,消息队列用了 redis 的 list left push right pop
    15 条回复    2025-05-20 11:32:51 +08:00
    visper
        1
    visper  
       18 天前
    不会是因为慢消息线程池开得多,所 cpu 核心都占用完了吧。
    luckyrayyy
        2
    luckyrayyy  
       18 天前
    看下有没有死锁?
    asp1111
        3
    asp1111  
    OP
       18 天前
    @visper 慢的 max 是 4 ,快的 max 是 32
    vvtf
        4
    vvtf  
       18 天前
    没明白,
    是 2 个线程池拉取 2 个队列的消息?
    还是 2 个线程池拉取 1 个队列的消息?
    如果是 2 个队列的消息那就说明快队列没有消息了.
    如果是 1 个队列的消息, 那如何判断是快消息还是慢消息?且
    快线程拉取到慢消息了或慢线程拉取快消息了怎么处理?
    asp1111
        5
    asp1111  
    OP
       18 天前
    @vvtf 2 个线程池拉取 2 个队列的消息,实际情况是快消息队列出现了消息堆积
    souryou
        6
    souryou  
       18 天前
    插眼关注,感觉不是线程问题(或者看下 2 楼说的?有资源竞争问题吗)。在排查下队列问题吧,有些队列有调度机制,会不会认为你的处理速度上有问题,然后给的调度少了,楼主用的什么队列,可以的话剥离业务逻辑,show your code
    NCE
        7
    NCE  
       18 天前
    不是 jvm 会倾向于运行上下文切换次数少的线程,是 CPU 分配时间资源肯定是顺序分配,给 A 了,A 执行完了再给 B ,B 执行完了再给 A ,你的 sleep 1s 也是 CPU 时间开销。

    你线程池 max32 ,你逻辑 cpu 数量有 32 个嘛?

    架构设计也有问题,快慢是消息优先级不同,通道一致。
    Belmode
        8
    Belmode  
       18 天前
    就应该分成两个服务,放到不同的物理机器上。快/慢线程池都是你自己人为指定的,操作系统并不知道,没法确定两个线程池的优先级。现在可能就是因为当前 CPU 的所有核心都去处理慢消息了,导致快线程池无法抢占,造成积压。
    我觉得哪怕给两个线程池手动设置优先级都不太合理,就得分开到不同物理服务器中。
    DonaldY
        9
    DonaldY  
       18 天前   ❤️ 1
    为啥:“如果拉不到就惩罚性 sleep 1s” ?

    如果实际情况是出现消息堆积,那可能是消费者消费过慢,被踢出消费组了,之后就不消费了。。
    所以为啥惩罚性呢?
    vvtf
        10
    vvtf  
       18 天前
    `消息队列用了 redis 的 list left push right pop`
    redis 的连接数是多少, 是不是被慢消息占满了?
    fjyhack007
        11
    fjyhack007  
       17 天前
    如果慢消息线程运行时间长、上下文切换少,Linux 调度器会认为这些线程是“高效率线程”,从而倾向于继续调度它们。
    快消息线程频繁上下文切换、睡眠( sleep(1s))反而会被认为“不活跃”,调度优先级降低。
    这在 CFS ( Completely Fair Scheduler )调度策略下尤其明显,低 CPU 占用线程不一定被“公平”处理。
    JVM 本身不会偏向“上下文切换少”的线程,但底层的操作系统调度器(如 Linux CFS )会对“常活跃线程”倾斜调度资源,从而导致你看到的“慢消息线程占用 CPU 、快消息线程饿死”现象。拆服务实现了资源隔离,自然就恢复了。
    night98
        12
    night98  
       17 天前
    你应该把 jvm 的快消息线程池和线程状态打 log 下来看是处于什么状态,是线程因为比如 log 或者 sysout 死锁了,还是线程不活跃了,还是其他的原因。不过大概率是写法有问题,你慢的 max 是 4 ,注定吃不完 cpu
    shine1996
        13
    shine1996  
       17 天前
    你慢的时候拉下 Thread Dumps 贴出来看下
    你看下 redis 链接是不是不够用?
    命令换成 brpop 不要做 sleep?
    litchinn
        14
    litchinn  
       17 天前
    看线程堆栈,跑火焰图,看看 cpu 到底在干嘛
    siweipancc
        15
    siweipancc  
       17 天前 via iPhone
    阻塞式 pop ,不要睡了,怕连接数不足?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5306 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 06:57 · PVG 14:57 · LAX 23:57 · JFK 02:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.