V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
spikeLIN
V2EX  ›  Linux

nginx 负载均衡的几个问题

  •  
  •   spikeLIN · 2016-08-16 11:29:20 +08:00 · 2566 次点击
    这是一个创建于 2816 天前的主题,其中的信息可能已经有所发展或是发生改变。
    目前有三台服务器,ABC
    A 在外网做负载均衡,利用 upstream 转发到 B,C
    A 中 upstream 的设置里,B 和 C 都是一样的,为 max_fails=2 fail_timeout=30s
    BC 的 upstream 设置只转发到本地的一个端口,后面也都写了 max_fails=2 fail_timeout=30s,但是应该是无效的.
    现在有个问题就是某个请求会重复两次.
    根据 log 里的内容,A 的 nginx 的 log 里此请求只出现了一次.
    在 B 的 log 里出现了一次,B 中返回码为 499,request_time 为 60 秒
    然后在 C 的 log 内也出现了一次,返回码为 200.

    所以我的想法是,A 先转发到 B,B 接受请求后的后台程序执行了该请求,但是响应时间过长,导致返回 499,于是 A 的 nginx 以为请求没有被响应,就把此请求转发到 C,C 又重新接受了请求.导致了该请求被执行了两次.

    如果真的是这种原因的话,那么我有几个小小的问题
    第一,这个 60 秒是怎么算出来的?如果是按照 A 中的 max_fails=2 fail_timeout=30s 的设置得出的话,朝 B 转发两次,这样总共不应该是有三次请求的执行吗?(B 的两次和 C 的一次)
    第二,A 中 nginx 的 log 在 B 失败之后转发的记录是没有被记录在 log 里的吗?
    第三,这种情况有什么有效的处理方法吗?
    望各位 nginx 大牛不吝赐教.
    2 条回复    2016-08-17 11:22:25 +08:00
    pangliang
        1
    pangliang  
       2016-08-17 09:26:56 +08:00
    这个 60 秒应该不是打 了两次 B, 是恰巧 B 的执行就是 60 秒; 或者说是这个 request 的执行时间过长, 超过了指定的最长时间, 容器主动终止了运行, (不知道你是不是 php, php 默认 max runtime 就是 60 秒, 也就是说你在 php 里 sleep(120) 是不行的)

    另外 , 这个 fail_timeout 的意思不是告诉 A, 如果 B fail_timeout 秒不返回就算他 fail, 而是说, B 出现 max_fails 次 非 200 响应后, 把 B 打入冷宫 fail_timeout 秒

    你这个问题其实跟 nginx 没什么关系, 这种业务都是要有"订单号" 并且 请求来了先判断这个订单是否已经被处理过 的判断
    spikeLIN
        2
    spikeLIN  
    OP
       2016-08-17 11:22:25 +08:00
    @pangliang 原来是这样,十分感谢
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2225 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 04:18 · PVG 12:18 · LAX 21:18 · JFK 00:18
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.