nginx upstream [warn] load balancing method redefined 处理办法

<pre class="wp-block-code"><code>业务同事反馈新增consistent hash url的时候有报错, "load balancing method redefined"

看了下配置, 大致是这样子
<p>upstream 2165 {
keepalive 4096;
check interval=10000 rise=2 fall=3 timeout=3000 type=http default_down=false;
check_http_send 'GET /check_alive HTTP/1.0\r\nHost: check.sohuitc.cn\r\n\r\n';
check_http_expect_alive http_2xx;
server 1.1.1.1 max_fails=0;
server 1.1.1.2 max_fails=0;
hash $request_uri consistent;
}</p>
简单搜索了下, 有这么个答案:
https:&#47;&#47;ma.ttias.be/nginx-nginx-warn-load-balancing-method-redefined/
答案是: "You can mix keepalive and least_conn, but you should define least_conn before keepalive.", 就是把LB的method 放到Keepalive 指令的后边, 考虑到least_conn 和 hash其实都是LB的method

那么, 这是为什么呢?
参考nginx官方的文档, https://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive
<p><code>When using load balancing methods other than the default round-robin method, it is necessary to activate them before the keepalive directive.</code></p>
官方文档要求把keepalive指令放到其他非RR的LB method的后边

我还想知道为什么呢?
翻开nginx的代码, 可以看到我这个hash 函数有个判断
http/modules/ngx_http_upstream_hash_module.c
<p>
    if (uscf-&gt;peer.init_upstream) {
        ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
                           "load balancing method redefined");
    }</code>而Keepalive指令, 会尝试去初始化这个 <span style="background-color: initial; font-family: inherit; font-size: 0.857143rem;">uscf-&gt;peer.init_upstream</p>
http/modules/ngx_http_upstream_keepalive_module.c
<p>
  kcf-&gt;original_init_upstream = uscf-&gt;peer.init_upstream
                                  ? uscf-&gt;peer.init_upstream
                                  : ngx_http_upstream_init_round_robin;

    uscf-&gt;peer.init_upstream = ngx_http_upstream_init_keepalive;</p>
所以如果Keepalive指令在前边, 准备加载LB method的时候, 会发现这个变量已经被初始化了, 会认为是有其他LB method被加载? 就会有个<span style="background-color: initial; font-family: inherit; font-size: 0.857143rem;">load balancing method redefined</span> 告警了

另外, 这个问题其实是由于另一个小的配置问题引出来的, 这里一并记录下
我们的配置有个报错, "enable hash balancing method support parameter backup", upstream中有backup配置也需要新增hash method, 触发了这个问题
参考文档https://forum.nginx.org/read.php?29,281365,281369#msg-281369
<p>Generally, hash methods don't support the "backup" parameter,
but for those who need backup when falling back to round robin,
there's a work around: put the "hash" directive after the
"server" directives in the "upstream" block.</p>
因此需要把hash 挪到后边, 这就刚好跟keepalive指令有了前后的冲突</code></pre>
从1.12版本测试结果看, hash 和backup一起用, 会导致backup无法起作用, 需要特别留意, 而1.25系列则正常, 估计是做了修复

发表回复