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

Java 执行大量长耗时接口,怎么使用单机处理

  •  
  •   layxy · 315 天前 · 2451 次点击
    这是一个创建于 315 天前的主题,其中的信息可能已经有所发展或是发生改变。

    目前使用的线程池,但是因为任务量太大,单机线程池和队列很快就满了,因为某些原因只能使用一台机器,有什么办法可以优化下

    第 1 条附言  ·  313 天前
    补充下,任务大部分都是查库,查 es,尤其是 es 比较慢
    第 2 条附言  ·  313 天前
    场景是这样的,我们有个定时任务,每隔一段时间触发,触发时会统计数据,查询 es 和 mysql,数据库倒还好,es 查询的比较多且慢,因为需要支持分布式任务调度,无论我扩容多少台,都只会调度到一台机器上,想过使用 mq 把长耗时部分分发出去分摊处理,但是大概率领导不让引入新的中间件,否则使用 flink 等实时处理可能更好,线程池目前扩大了,队列也增加了,但是还是偶尔会报警
    31 条回复    2023-07-26 11:39:10 +08:00
    cvbnt
        1
    cvbnt  
       315 天前 via Android
    加内存
    zpf124
        2
    zpf124  
       315 天前
    处理速度跟不上只能增加性能,要么加内存要么加机器。

    治标的话,只为了不爆,那就改成把待执行队列存库,然后代码改成读取数据库,有数据就处理,弄成定时任务或者直接死循环。
    chenqh
        3
    chenqh  
       315 天前
    加线程数?
    iceshiny
        4
    iceshiny  
       315 天前 via iPhone
    找瓶颈
    thinkershare
        5
    thinkershare  
       315 天前   ❤️ 1
    CPU 密集任务你看加再多线程,加再多内存也没啥用。I/O 密集型,使用线程池就够了,反正 I/O 线程也不会被 CPU 调用,设个大点的数量就好了。你给的条件太有限,给不出你优化意见。
    kaneg
        6
    kaneg  
       315 天前 via iPhone
    如果是纯 IO 型的调用,可以上异步 IO ,不怎么消耗线程。

    如果不想增加异步 IO 的复杂性的话,就直接上最新版 Java 的虚拟线程,几乎可以无限开线程。
    yeqizhang
        7
    yeqizhang  
       315 天前 via Android
    任务放在线程池队列里,为什么会爆?
    hefish
        8
    hefish  
       315 天前
    请问如何在不加内存,不加 cpu 的情况,让电脑跑的快一些?
    yazinnnn
        9
    yazinnnn  
       315 天前 via Android
    执行接口指的是调用外部服务?
    io 密集的话可以用 netty 之类的 nio 客户端或者升级 jdk 用 loom
    cpu 密集的话没救
    dqzcwxb
        10
    dqzcwxb  
       315 天前
    串行改并行,同步改异步
    十字秘诀送给你
    xiangyuecn
        11
    xiangyuecn  
       315 天前
    ThreadPoolExecutor 线程池处理机制:
    1. 新任务进入核心线程执行(核心线程默认不回收)
    2. 核心线程数据量满了,放到队列等待
    3. 队列 TMD 也满了,开新线程处理,直到线程数量达到最大线程数(这种线程会回收)


    我一直没明白,这玩意到底是哪里会用到这破逻辑,最大线程数有个卵用啊😂

    按我的脑回路,应该是核心线程满了,就开新线程,直到最大线程数,最大线程满了就放队列等待
    hhjswf
        12
    hhjswf  
       315 天前 via Android
    Java 项目耗时基本在 io 上,最大线程数量可以搞大一点
    arloor
        13
    arloor  
       315 天前
    mq ,来积压在 mq 上,对于 kafka 是挤压在磁盘上
    dreamlike
        14
    dreamlike  
       315 天前 via Android
    先做热点采集 jfr 打个火焰图看看
    再分析下 perf 没数据不知道该怎么处理 也不清楚是什么样子的业务
    如果是那种你依赖的服务响应非常慢 直接上 reactive 来做 io 所占的也就几个闭包的内存,然后善用 timeout 和 buffer 来做被压就好了

    如果是依赖于 cpu 嗯算 那基本只能叠机器了 这种一般采集完信息会显示 cpu 占用平均值非常高
    tairan2006
        15
    tairan2006  
       315 天前 via Android
    MQ 啊
    RuralHunter
        16
    RuralHunter  
       315 天前
    客户端提交任务后定时查询任务状态
    服务端接到任务直接放队列,执行线程从队列取任务执行保存执行结果。同时相应客户端的查询状态请求
    tangAtang
        17
    tangAtang  
       315 天前
    @xiangyuecn 这是历史问题,以前 CPU 可没这么多核心
    hhjswf
        18
    hhjswf  
       315 天前 via Android
    @xiangyuecn 按你的脑回路最大线程数也没用啊,如果有源源不断的任务,你这最大线程数一直满载,我为什么直接加大核心数?
    someonedeng
        19
    someonedeng  
       315 天前
    用带持久化的 mq
    key0323
        20
    key0323  
       314 天前
    加个 kafka 自己发消息自己消费
    xiangyuecn
        21
    xiangyuecn  
       314 天前
    @hhjswf #18 直接加大核心线程数,不就等同于说明了最大线程数没卵用😂

    目前我就是这样做的,核心线程数 等于 最大线程数,通过设置 allowCoreThreadTimeOut(true)去掉核心线程这个概念,每个线程都是普通的,超时没有任务了线程就被回收,充分利用机器性能,其实也就等于说明了最大线程数没有卵用
    xiangyuecn
        22
    xiangyuecn  
       314 天前
    比如 核心线程数 等于 最大线程数 等于 100 个线程,核心线程空闲 5 秒关闭,队列给到 200 个容量

    假如大部分时候只需要 20 个线程工作就够了,偶尔会有 200 个突发任务

    那么一直会开启的可能就是 20 个左右的线程,突发的 80 个任务会开启新的线程处理,线程满了,多余的 100 个任务会被加入队列
    -------

    如果按照默认的逻辑,就算给到平常一倍核心线程数:40 个核心线程,200 个容量队列,100 个最大线程

    200 个突发任务工作是不正常的:只会有 40 个线程同时工作,160 个被加入队列,因为队列没有满,不会开启新线程!
    100 个最大线程成了摆设,队列卡在这个位置比较尴尬。
    wxxxcxx
        23
    wxxxcxx  
       314 天前
    异步编程应该很适合,不知道 java 有没有好用的库
    Red998
        24
    Red998  
       314 天前
    主要还是优化接口耗时问题、 从这方面入手。异步治标不治本,异
    janus77
        25
    janus77  
       314 天前
    如果你线程池都满了,那物理配置不加的话也没法再有很大的提升
    我的建议是换语言
    byte10
        26
    byte10  
       314 天前
    你的任务是 是什么任务啊,也没说清楚,是计算型的,还是 IO 密集型的?你的任务是要循环读取 mysql 数据进行处理吗?计算密集型,只能物理解决或者优化计算的算法。IO 密集型 加线程,4 核心 500 个线程都没问题。
    layxy
        27
    layxy  
    OP
       313 天前
    @kaneg 公司目前最高只让用 11,而且虚拟线程现在还没 release,还要升级到至少 java19,这个方案行不通
    layxy
        28
    layxy  
    OP
       313 天前
    @byte10 IO 密集型,排查了下,耗时集中在 es 查询
    layxy
        29
    layxy  
    OP
       313 天前
    @janus77 线程池满了,但是 cpu 占用不高,后续再加线程池大小再看看,最终的话引入 mq 应该是最好的,但是这个不好推进
    byte10
        30
    byte10  
       313 天前
    @layxy ES 支持异步的,你选一个 ReactiveElasticsearchTemplate 客户端 , 这样就不需要多线程了。不过你要注意的是 Reactive 通常会有背压问题,需要判断 ES 服务器能否抗住,扛不住就注意要限流,不然会导致 es 挂掉。
    zzw66681
        31
    zzw66681  
       269 天前
    单机可以换一下 disruptor
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2862 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 08:02 · PVG 16:02 · LAX 01:02 · JFK 04:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.