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

Web 服务突然被挤暴,如何有效分流

  •  
  •   kaka6 · 2021-10-25 17:12:31 +08:00 · 3043 次点击
    这是一个创建于 886 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如题,一款微信小程序,平常日均活跃量 100 人左右,日均 pv 5K 以内 但没想到搞了个活动,访问人数直接上了 4 万+,把服务器挤爆,结果大家都无法访问,系统挂了

    avatar

    一台 Web 服务器(4C8G ,弹性 200M 带宽) + 一个 RDS Redis + 一个单机 RDS MySql 数据库(4C8G)

    看服务日志,主要是数据库的 CPU 遇到瓶颈,直接上了 100%

    临时数据库加到 8C 也不够,程序估计也是有问题,缺少合理的缓存,造成数据库访问频繁

    加硬件,是简单粗暴的方式 优化程序,还需要从头计议

    我想到做入口分流,大家有没有相关经验分享

    就是我根据环境配置,同一时间只想服务好比如 5000 人,超过 5000 人,在外面等候

    这样至少能保证一部分用户可用,不致于造成系统挂掉

    本地性的小应用,日常访问量少,感觉还没到做微服务、中台、集群等层面上

    所以想通过什么策略搞搞分流,至少在流量大时能保持一部分用户可用,会不会好做些

    大家给给建议,谢谢!

    25 条回复    2021-10-28 02:00:29 +08:00
    Chinsung
        1
    Chinsung  
       2021-10-25 17:49:56 +08:00
    搞个 sentinel 限流呗
    brucedone
        2
    brucedone  
       2021-10-25 18:27:40 +08:00
    你是啥业务,是查的多还是写的多?

    查的多要考虑缓存(考虑缓存穿透),锁,常规限流的算法(令牌桶等)

    写的多考虑异步,消息队列

    整体的思考是把流量尽量挡在前面,或者中间层,分层隔离
    tms
        3
    tms  
       2021-10-25 19:25:55 +08:00
    后端正在服务的人数满了,给前端返回一个状态,让前端显示排队呗。
    kaka6
        4
    kaka6  
    OP
       2021-10-25 19:55:24 +08:00
    @Chinsung 这个 sentinel 有了解过,好像一般都用在大项目,放我们这有点杀鸡用牛刀的感觉
    kaka6
        5
    kaka6  
    OP
       2021-10-25 19:58:07 +08:00
    @brucedone 读写都比较多,以长链接 socket 实现实时互动性服务,肯定是要缓存优化,通过暴露出来的问题,在缓存优化上可以有很多空间,以减少数据库 IO
    kaka6
        6
    kaka6  
    OP
       2021-10-25 20:02:35 +08:00
    @tms
    后端正在服务的人数满了,给前端返回一个状态,让前端显示排队呗。
    ---
    这个方向是我目前比较想做的,有没有什么工具、方法,或者中件间
    因为不好介定什么时候算人满,根据 api 请求数?有效 token 数?还是 qps?
    有点模不着头脑
    markgor
        7
    markgor  
       2021-10-26 08:53:16 +08:00   ❤️ 3
    既然小程序了,就已经前后分离了;
    具体业务你没提,我只能大概说说,

    1 、活动页面,进入后 请求后端,后端能正常回应的话进入业务流程,不能正常回应的继续等待或定时重发请求;(此时界面丢个 loadding 的 gif 即可。
    2 、后端先自己压测下,能接受多少请求,我看你这都是 socket 实现的,那就建立连接后 redis 计数器+1 ,断开连接后 redis 计数器-1 ,首次发起连接时候通过 redis 计数器来判断是否达到峰值(对应第一点)。



    最后,你的问题是数据库 CPU 达到 100%,这种情况我觉得应该优先排查 SQL 语句,尤其是看慢查日志,一般出现这些问题基本都是 SQL 语句的问题。
    分流对你并不适合,你的问题是数据库 CPU 100%,不是业务机器 CPU 100%。
    kaka6
        8
    kaka6  
    OP
       2021-10-26 09:12:00 +08:00
    @markgor 谢谢,弄个 redis 计数器,这也是个解决办法
    37Y37
        9
    37Y37  
       2021-10-26 09:17:30 +08:00
    改程序都是后话了,可以直接考虑下负载均衡这里,Hash/Source 算法,根据来源 IP 分流一部分用户到一个维护节点,例如你的应用服务器(前提是你应用服务器资源充足)上再启动个 http 服务,就给一个静态页面,提示排队中或者维护中之类的,也可以配合权重来确定分流多少比例的用户到排队
    keppelfei
        10
    keppelfei  
       2021-10-26 09:29:46 +08:00
    4c8g 的配置带 4w 人感觉没那么拥堵吧,我们以前也是这个配置,带 5w 人参加裂变活动都没什么大问题,用了 redis 、mq 等中间件削峰。
    kaka6
        11
    kaka6  
    OP
       2021-10-26 10:38:23 +08:00
    @keppelfei 厉害了,是怎么做到的,qps 要做到 300 以上吧
    aliyaoming
        12
    aliyaoming  
       2021-10-26 11:57:27 +08:00   ❤️ 1
    7 楼说到点上了 mysql cpu 100% 先看下 slow_query_log ,看下是不是 sql 写的不合理,排除 sql 外才是看应用层的问题,包括操作系统内核的优化以及 nginx 的优化等等,理论上 4c8G 的服务器从应用层顶 4 万 /日访问量(并发应该不会超过 5k ),还是没问题的,优化的好根本不用考虑负载均衡的事情
    darkengine
        13
    darkengine  
       2021-10-26 12:21:56 +08:00
    我也觉得是 sql 语句,甚至数据库某些表没有正确加索引导致的。不然 4 万+的日访问量不至于把 8C 的数据库服务器跑满。
    yc8332
        14
    yc8332  
       2021-10-26 16:23:40 +08:00
    要么 web 服务器限制连接数、要么就程序里弄个连接计数器。。超过了不让进来。
    xutt2017
        15
    xutt2017  
       2021-10-26 17:08:26 +08:00
    同意 7 楼的建议,不要搞那么复杂。先找到慢 SQL ,想办法优化。活动时,临时升级 MySQL 服务器配置。再建议就是,详细描述你的业务,看有没有办法将部分逻辑异步处理,先丢给 MQ 或 Redis ,再给 MySQL 。当前最好的办法还是从 MySQL 那里想解决办法。
    RangerWolf
        16
    RangerWolf  
       2021-10-26 17:23:07 +08:00
    对 先看慢查询日志
    tms
        17
    tms  
       2021-10-26 18:23:39 +08:00
    @kaka6 自己实现一个令牌桶算法限流也不麻烦,找找相关的中间件也有。至于如何界定人慢。这个你要自己压测,看看目前的程序能支撑多少就会打满 CPU ,具体到不同接口可能支撑的人数也不一样。
    如果有时间的话还是从根本上解决问题比较好,其他人说的也都比较在理,这个请求数下数据库 100%大概率是 SQL 语句和索引优化的问题。这种解决了才是一劳永逸的办法。
    killva4624
        18
    killva4624  
       2021-10-26 18:27:27 +08:00
    1 、mysql 慢查询优化,可以通过压力测试或者模拟回放线上请求看看是哪些语句执行时间长,针对性地优化表结构或者索引或者查询。
    2 、CPU 下来以后,再压测看看别的瓶颈没有,比如 TCP 链接数、TCP 内核参数之类。
    3 、如果还行,再考虑添加组件,比如 redis 缓存、mq 、队列之类,保证请求不要过载。
    gzf6
        19
    gzf6  
       2021-10-26 20:25:21 +08:00 via Android
    花果山?
    Chinsung
        20
    Chinsung  
       2021-10-27 11:12:43 +08:00
    @kaka6 #4 这东西本身还是比较轻量的,比起其他说的自己实现令牌桶之类来说的话,反而要更简单和稳定。这种都还要依赖个类似于网关的东西。
    或者可以尝试下用 nginx 做限流,肯定是支持的,了解下相关配置。
    ryalu
        21
    ryalu  
       2021-10-27 13:45:51 +08:00
    想啥限流分流都没啥用,治标不治本。最有效的方式是做读写分离,以及打开慢日志优化相关索引。
    tmackk
        22
    tmackk  
       2021-10-27 17:29:36 +08:00
    @gzf6 你说的是装机猿?
    kaneg
        23
    kaneg  
       2021-10-27 20:18:26 +08:00
    如果要限流,可以用 resilience 方面的库来做,可以限制并发,限制时间段内访问的次数,错误超过设定后丢弃部分请求等。比如 Java 的 resilience4j.
    gzf6
        24
    gzf6  
       2021-10-27 22:51:42 +08:00
    @tmackk 对,他前两天不是说爆了么
    huangzxx
        25
    huangzxx  
       2021-10-28 02:00:29 +08:00
    可以先限流,上 waf 或者 nginx limit_req 。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2684 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 15:30 · PVG 23:30 · LAX 08:30 · JFK 11:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.