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

遇到个高并发的问题

  •  
  •   luxinfl · 2022-03-15 10:11:58 +08:00 via Android · 4855 次点击
    这是一个创建于 975 天前的主题,其中的信息可能已经有所发展或是发生改变。

    配置:5 个 slb ,10 台 16C64G 的服务器。
    接口:一个天气页面的运营位查询接口。业务逻辑是本地缓存+一次 get 请求。本地缓存时间可以忽略不计。
    后端服务配置:默认 tomcat 设置,200msms 的获取连接时间,200ms 建立连接时间,500ms 的数据传输时间,默认最大路由数 30 。
    现状:六点到八点间每台 slb 的 ttps 稳定在 80w 左右,某个时间会升高到 100w+。此时服务时延会变高(10ms 升到 1600ms 左右),错误数也会升高,接口成功率在 99.95%左右。  

    有什么办法可以让这段时间的时延降低麽

    第 1 条附言  ·  2022-03-15 14:48:06 +08:00
    补充一下,运营位的广告内容,这个已经加载到本地缓存了,我是感觉业务中的一次 http 调用获取用户标签的应该是瓶颈所在。用的是 resttemplate 。
    第 2 条附言  ·  2022-03-15 14:59:58 +08:00
    现在状况是,24 小时内 10 亿次接口调用,12 点钟那会时延到 400+,nginx 期间狂报 499 ,502 。X﹏X
    第 3 条附言  ·  2022-03-15 15:55:47 +08:00
    看错了监控平台了,从 3 月 13 零点到 3 月 14 号 24 点,总请求量 13 亿,tps 显示 13ww ????有点迷惑。。
    41 条回复    2022-03-18 09:53:50 +08:00
    C603H6r18Q1mSP9N
        1
    C603H6r18Q1mSP9N  
       2022-03-15 10:14:56 +08:00
    你的 80w 是多长时间的? 1 分钟?
    paradoxs
        2
    paradoxs  
       2022-03-15 10:26:46 +08:00
    是缓存被击穿了么? 多配点缓存。
    defunct9
        3
    defunct9  
       2022-03-15 10:29:10 +08:00
    5 个 slb 是什么? f5|haproxy|nginx ???
    luxinfl
        4
    luxinfl  
    OP
       2022-03-15 10:37:16 +08:00 via Android
    @shanghai1998 就 tps 啊

    @paradoxs 不存在的,用的本地缓存,到死都不会消失的那种

    @defunct9 就是 Nginx.
    defunct9
        5
    defunct9  
       2022-03-15 10:44:45 +08:00
    加到 10 台 nginx 吧,估计是 https 的卸载能力不够了。
    libook
        6
    libook  
       2022-03-15 10:46:16 +08:00
    看一下缓存命中率如何,如果绝大多数请求都不命中缓存,那么缓存就是无效的,你得看是不是缓存释放太快,还是缓存空间不够用,还是你的业务不会有重复的返回数据。
    MoYi123
        7
    MoYi123  
       2022-03-15 10:57:17 +08:00
    比如应用服务器改成只回 helloworld, 把 https 换成 http, 不走 http 直接调用函数去运行,
    本地尝试复现问题, 把问题找到再说吧,
    不然我们也不知道具体情况.
    luxinfl
        8
    luxinfl  
    OP
       2022-03-15 10:58:36 +08:00 via Android
    @defunct9 服务器要钱啊。。。
    @libook 我们是按照国家运营,国内的是一样的。相当于 10 台服务器是一样的数据。
    defunct9
        9
    defunct9  
       2022-03-15 11:00:33 +08:00   ❤️ 1
    嗯,不愿意加钱,好办。把后端的 tomcat 换成 Go 写的程序就行了。
    libook
        10
    libook  
       2022-03-15 11:01:34 +08:00
    @luxinfl #8 你没回答我的问题呀,我问的是缓存命中率如何,你可以用日志或者其他方式来统计一下,比如每分钟的命中率多少。
    timethinker
        11
    timethinker  
       2022-03-15 11:24:10 +08:00
    推荐一篇文章,讲解的比较系统: https://mp.weixin.qq.com/s/apUVMfAI52uvc7U-iOVvKg
    micean
        12
    micean  
       2022-03-15 11:29:34 +08:00
    正常 10ms ,不会是缓存的问题,已经到极限了吧
    天气预报这种业务能不能上 CDN?
    angryfish
        13
    angryfish  
       2022-03-15 11:56:13 +08:00
    1.出口带宽是多少,峰值是的带宽有没有打满
    2.确认是 nginx 到达上限还是 tomcat 到达上线。如直接请求 tomcat 能否快速返回结果。
    3.程序是否可以进一步优化,如结果直接静态化为文件数据存放在 nginx ,请求直接走 ng 。等等。
    vace
        14
    vace  
       2022-03-15 12:21:10 +08:00
    天气这种允许一定延迟的场景,被动更新,按参数生成静态文件放 CDN ?
    C603H6r18Q1mSP9N
        15
    C603H6r18Q1mSP9N  
       2022-03-15 13:27:29 +08:00
    你看清楚了,阿里云 slb 上的并发是一分钟,不是 tps ,如果是 tps ,你 10 台机器,1 台要抗 8w 并发每秒, 就算程序是 hello world ,你的机子也扛不住。实际可以通过阿里云监控,可以查到并发的瓶颈是在哪里,正常是在数据库和缓存,这个时候加服务器意义不大了
    ZSeptember
        16
    ZSeptember  
       2022-03-15 14:22:50 +08:00
    业务是比较简单的,先定位问题,主要是看缓存命中率是不是预期的
    luxinfl
        17
    luxinfl  
    OP
       2022-03-15 14:41:42 +08:00 via Android
    @libook 这个只能说国内会 99.99%命中缓存,因为前台查询不会走数据库
    luxinfl
        18
    luxinfl  
    OP
       2022-03-15 14:44:14 +08:00 via Android
    @micean 不是天气预报,是天气页面里面的广告位
    @vace 是广告,而且这个广告确实基本不会变
    @shanghai1998 华为云,监控上面确实是 tps ,每五分钟统计一次,5 个 slb 都是 100w +,确实一整天的流量就集中在早上两小时。
    luxinfl
        19
    luxinfl  
    OP
       2022-03-15 14:45:10 +08:00 via Android
    @vace 有个场景,需要用设备号去查询用户标签信息,会根据这个筛选,这一步省略不了。
    haython
        20
    haython  
       2022-03-15 15:11:13 +08:00
    每秒 80 万,2 个小时就 50 亿了。5 个 slb ,每个都稳定在 80 万。如果我没算错,你这个数据肯定是错的
    ymy3232
        21
    ymy3232  
       2022-03-15 15:24:21 +08:00
    1.resttemplate 的连接池
    2.带宽
    3.获取用户标签的时长
    ElmerZhang
        22
    ElmerZhang  
       2022-03-15 15:30:24 +08:00
    首先就你的描述来看,tps 80w 是不可能的。tps 全称 Transactions per second ,单台限 30 连接,每个请求耗时 10ms 的话,单台理论最高 tps 是 1000 * 30 / 10 = 3000 。10 台后端加起来也就 30000 。
    如果是 transactions per 5 minutes 的话还合理一点,那样 80W 的时候 tps 是 2666 ,100W 的时候 tps 是 3333 。

    如果你的时延是在 slb 上统计的,先看看后端的连接数用满了没。
    如果你的时延是在后端统计的话,有可能是所依赖的某项服务或者连接数之类的达到瓶颈了导致的。
    byte10
        23
    byte10  
       2022-03-15 15:46:24 +08:00
    @haython 我也觉得,单机 80w 不太可能,8w/s 感觉都难,除非真的是 hello world 。
    @luxinfl 要不看看用 NIO 吧 https://www.bilibili.com/video/BV1FS4y1o7QB ,像你那样的机器,单机十万问题不大,另外 http 请求是一问一答的,所以你要大并发吞吐量,就需要增加很多连接数,你用的 tomcat 是多线程模式把?多线程设置多少?你可以看看 cpu 占用率和内存占用率。cpu 没满,那就是线程数不够了,IO 密集型,线程要多。不过最好还是 NIO 去实现把,看看我的视频有说明 NIO 是怎么解决网络 IO 时长的问题的。
    luxinfl
        24
    luxinfl  
    OP
       2022-03-15 15:53:13 +08:00 via Android
    @haython 我发现了,是这个 nginx 总的 tps 。。。
    luxinfl
        25
    luxinfl  
    OP
       2022-03-15 15:59:40 +08:00 via Android
    @ElmerZhang 是五分钟统计的一次。。而且还错看了整个 nginx 的 tps 。。
    sampeng
        26
    sampeng  
       2022-03-15 16:03:58 +08:00
    为啥都在纠结 tps 是多少。。。不去给个思路排查?
    就算是 tps8w ,难道就不算高并发就不是问题了?


    这个链路有两个口,一个是 slb ,一个是应用程序。所以要先确定是 slb->应用程序这一条链路是否是通畅无延迟的。因为 slb 本身也是一个池子,他抖动一下你只能看着。所以要有手段检查 slb->应用程序的延迟。一般是在你的这一测也加监控,不是光去看 slb 的监控,而且顺便把应用程序的监控也加了也好分析应用程序本身有什么问题。

    看是 tomact ,就是 java 。prometheus 挂起来。看看接口的 99%延迟是多少,看看每台 qps 是多少(其实不重要,tps 只是有比较才用,一直都是一个均值没啥用)。每台机器要挂一个 node exporter 。看机器的详细的指标。网络吞吐是不是到瓶颈,内存是不是到瓶颈,是不是那个时候在做 full gc 。等等。。这些信息都没有。。。让广大 v 友盲猜?
    luxinfl
        27
    luxinfl  
    OP
       2022-03-15 16:09:15 +08:00 via Android
    @sampeng 有 prometheus ,但是没有接监控平台,端口估计也没放开,现网查不到数据。看样子可以先考虑把这些东西都加上,新项目上线,一些外围服务都还没搞。
    sampeng
        28
    sampeng  
       2022-03-15 16:10:23 +08:00
    @luxinfl 有 prometheus 。。直接 curl 就能拿到了。。没那么麻烦。。。
    sampeng
        29
    sampeng  
       2022-03-15 16:11:54 +08:00
    @luxinfl 回车打快了。。
    无所谓了。排查问题,一定要有监控。。盲猜都是秀操作
    luxinfl
        30
    luxinfl  
    OP
       2022-03-15 16:32:46 +08:00 via Android
    @sampeng 没权限,看不到,在想办法。。
    defunct9
        31
    defunct9  
       2022-03-15 21:35:32 +08:00 via iPhone
    开 ssh ,让我上去看看
    luxinfl
        32
    luxinfl  
    OP
       2022-03-16 09:29:39 +08:00 via Android
    @sampeng 大佬,调用外部接口的 http 连接数应该是有上限的吧,这个能查出来麽
    luxinfl
        33
    luxinfl  
    OP
       2022-03-16 09:31:18 +08:00 via Android
    @byte10 大佬,http 连接池的连接和 cpu 线程都需要去看 cpu 和内存的占用率麽?是不是 http 连接越多,占用内存也越多,对其他参数有影响么
    sampeng
        34
    sampeng  
       2022-03-16 10:36:50 +08:00
    @luxinfl 有没上限也是看要看监控。java 的 jvm 的监控能看得到。很简单。。你怀疑线程数,就设置更多的线程呗,碰碰运气嘛。

    这里有一个误区,并不是线城数越多越好。只要足够快,1 个线程也够用。要看 jvm 监控里面堵塞线程数,max 线程数等等。。就算没监控,你们也要有 ssh 权限上去看 jstack ,如果能正好撞上有问题的时候线程的问题可以看得出来。

    没有监控都是盲猜,运气好撞上,运气不好就找不到。详细监控才是追查这种问题的办法。还有可以把 GC 日志打开,是不是在 GC ,但你们什么权限都没有。。查个鬼
    byte10
        35
    byte10  
       2022-03-16 11:21:55 +08:00
    @luxinfl 不是啊。。。你可以去看下我的那个视频。

    1 、首先确保你的这个接口业务代码是否有网络 IO 的代码?(比如查询 redis ,查询数据库,查询第三方接口),你说是用本地缓存,那么不存在 redis 的 IO 时间。但是你说的另外 : ”有个场景,需要用设备号去查询用户标签信息,会根据这个筛选,这一步省略不了。“ 那么这一步的 IO 是可能存在瓶颈的,假设这个网络 IO 耗时 10ms ,那么你 100 个 tomcat 线程,也就是 1w/s 的并发,还只是理论的情况。如果你增加 1000 个线程,那么 cpu 处理的效率也会有点下降,频繁的线程上下文切换。

    2 、如果业务代码存在网络 IO ,那么怎么改?那么可以使用 NIO 异步的方式去调用 数据库,redis ,第三方 http 接口等。但是也要注意那个连接数的问题,有一些协议不支持多路复用,比如 http 。如果你调用外部第三方接口是 http 接口,那么就需要设置比较大的 http 连接数,这个数量一般几千上万都可以,对方的服务也一般支持。

    3 、但是你的服务应该有其他的接口的吗?假设你只有 8 个线程,其他 B 接口进来之后,有几个线程被这几个 B 接口长时间 IO 阻塞了,那么就会导致你的天气接口吞吐量下降。所以也需要预留部分线程给这些 B 接口。

    这么大的吞吐量,有可能是你的服务出现瓶颈,所以先让你看看是不是 cpu 满了,如果满了,可能就是服务机器的性能达到一定的瓶颈了。下游的数据库服务或者第三方服务等也可能是瓶颈。上游只有 slb ,那么问题不大。
    luxinfl
        36
    luxinfl  
    OP
       2022-03-17 19:16:43 +08:00 via Android
    @byte10 对方的接口网络 io 大部分在 10ms ,偶尔有波动。我关掉外部调用,纯走本地缓存,碰到个奇怪的现象,tomcat 的 maxTread 调到 400 ,maxConnection 调到 2 万,关掉外部接口调用,跑了几次压测,cpu 和内存和几乎没有变化,按道理,线程数越多,cpu 和内存使用率不应该越高麽。。
    luxinfl
        37
    luxinfl  
    OP
       2022-03-17 19:18:57 +08:00 via Android
    @sampeng 今天一堆领导在排查了,访问量越来越高,一天都快 30 亿次接口调用,后端服务没啥问题,在扩容 slb ,不知道最后结果会是啥样。。
    sampeng
        38
    sampeng  
       2022-03-17 19:31:25 +08:00
    @luxinfl 我才看见前面说的。。5 个 SLB 。。。slb 还能按个数说的? nginx 吧?
    sampeng
        39
    sampeng  
       2022-03-17 19:32:38 +08:00
    @luxinfl max 不代表说一定要用那么多。。我前面也说了,误区是线程越多越好。其实如果足够快。1 个线程也够用。。想象 redis
    luxinfl
        40
    luxinfl  
    OP
       2022-03-18 09:27:30 +08:00 via Android
    @sampeng 这边习惯这么说,其实就是 nginx
    byte10
        41
    byte10  
       2022-03-18 09:53:50 +08:00
    @luxinfl 不是啊。。。少年。如果没有任何 io 的情况下,线程数 等于 cpu 即可,当然略大于也没啥问题。另外你说的 cpu 和内存几乎没变化,是因为你的压测工具不行。。。。你要换性能相同的客户端机器去压测你这台服务机器。还有客户端 http 连接数,需要大于服务端线程数的 3-5 倍左右才行。所以你应该要把我的那个视频完整的看完,你才能理解 http 要怎么进行压测才是最准确的。我盲猜你用 jmeter ,那玩意不行。你用 wrk ,或者其他的,甚至你用我的视频中的 那个压测脚本,多进程跑几个,绝对可以得到客观的性能数据。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5906 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 37ms · UTC 02:37 · PVG 10:37 · LAX 18:37 · JFK 21:37
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.