nginx proxy_next_upstream 與openresty balancer.set_more_tries的使用


背景

我們這邊網關服務使用的 kong,前段時間上線一個服務,這個服務它報錯了,產生了502的錯誤碼,追查這個報錯的時候發現了網關服務的兩個可疑的地方,第一個疑點是我們在Kong上配置的 Retries = 5,但是實際實際上我們的代理重試至多只會重試三次。第二個疑點是我們的重試只重試了502 和 504,大量的500錯誤沒有重試。帶着這兩個問題了查了下kong和openresty代碼。

結論

首先給出問題的結論
第一個問題 Kong上配置的 Retries = 5,但是實際上只會重試三次。出現這個問題的原因是因為我們在nginx上有一行配置

proxy_next_upstream_tries 3;

當我們在基於openresty Kong 上做 balancer.set_more_tries(5) 這個操作的時候nginx會基於保護措施啟用nginx的配置 proxy_next_upstream_tries,所以proxy重試的時候最多只能重試三次。

第二個問題,就是為什么只有502 504 作出了重試,而且500沒有做重試
這個的原因也是因為我們在nginx的配置里面有這么一行配置

proxy_next_upstream error timeout http_502 http_504 non_idempotent;

只需要加上http_500 500的錯誤碼就可以重試了。

問題的定位

先說一下第一個問題的定位過程
主要是不知道有 nginx 有proxy_next_upstream_tries 這個參數,一直以為是openresty balancer.set_more_tries 控制的重試次數,一度自以為是的覺得這是bug,都想提個issues,直到在openresty的群組郵件里面春哥有一個關於這個問題的回復。
這個問題春哥在openresty的郵件群組里作出過解釋
https://img2020.cnblogs.com/blog/1557931/202109/1557931-20210921064201910-2122530166.jpg

Hello!

2015-11-19 18:52 GMT+08:00 DeJiang Zhu:
>> > - 在 `proxy_next_upstream_tries 0;` 的時候, set_more_tries 好像沒有效果了.
>
> 我測試了也是這樣
> 然后看了代碼發現: set_more_tries 並不能超過 proxy_next_upstream_tries 的配置 [1]

這是故意的,proxy_next_upstream_tries 規定的是重試上限。這可以避免 Lua 代碼邏輯上的錯誤而導致無休止的重試。

Regards,
-agentzh

就看到了 proxy_next_upstream_tries 配置,以及互斥的時候以哪個為准。

第二個問題,上游500的錯誤碼沒有被重試。
這個問題的定位主要是陷入了以前引入Kong的一個誤區了,我們的服務引入Kong的其中一個原因就是有些服務重啟中發生錯誤的不能將服務重試到沒有問題的上游服務器上去(其實主要是nginx不能按照我們的預想重試到上游服務上)。所以一直以為這是Kong的問題,所以把Kong的Kong init中關於Kong.balancer()的方法看了很長時間,測試了好多次,才確定不是這里問題,后來又去看了下 Passive health checks 被動健康檢查代碼,以為是這里做了重試,上游服務區的列表輪訓引起的,最后也確定了跟這里沒有關系。

最后一個一個過proxy_XXX的方法的時候,發現了 proxy_next_upstream 的配置說明,這個函數其實手冊將的特別清楚
http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream

Specifies in which cases a request should be passed to the next server:

error
an error occurred while establishing a connection with the server, passing a request to it, or reading the response header;
timeout
a timeout has occurred while establishing a connection with the server, passing a request to it, or reading the response header;
invalid_header
a server returned an empty or invalid response;
http_500
a server returned a response with the code 500;
http_502
a server returned a response with the code 502;
....
non_idempotent
normally, requests with a non-idempotent method (POST, LOCK, PATCH) are not passed to the next server if a request has been sent to an upstream server (1.9.13); enabling this option explicitly allows retrying such requests;

其它參數挺簡單的,有哪些請求應該被轉發到下一個上游服務器。主要是最后一個參數
non_idempotent, 默認情況下一些非冪等的函數(POST, LOCK, PATCH)不會被轉發到下一個上游服務器,這個參數會允許此類請求也被轉發到下一個上游服務器上。

還是應該多研究書冊,仔細看說明


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM