說明
部分的服務(wù)節(jié)點(diǎn)經(jīng)常再經(jīng)過了nginx已經(jīng)進(jìn)入到了上游服務(wù)器服務(wù)內(nèi)部之后,因?yàn)橐恍┪粗脑?,如第三方接口的請求超時(shí)等,也會(huì)引起的服務(wù)的502的響應(yīng)異常,如何再此類的情況解決節(jié)點(diǎn)不直接的響應(yīng)返回的502的狀態(tài)碼和結(jié)果信息,或者重試。
本實(shí)踐主要是嘗試這種方案的可行性。
應(yīng)用場景
此場景僅限于自己業(yè)務(wù)中,比如當(dāng)某個(gè)業(yè)務(wù)進(jìn)行到內(nèi)部服務(wù)器且經(jīng)過第三方接口直充成功的之后,突然的莫名成的程序進(jìn)程崩潰或無響應(yīng)的時(shí)候,此時(shí)重新提交一下相關(guān)的接口進(jìn)行分發(fā)核對一下具體的充值接口情況,避免返回給第三方服務(wù)商的的接口狀態(tài)是502的響應(yīng)。
正常來說充值類的業(yè)務(wù)最好不要進(jìn)行二次的確認(rèn)提交,不過我這邊進(jìn)行加鎖處理,目前暫時(shí)先這樣處理!
環(huán)境
首先配置一下具體的服務(wù)
nginx 的配置環(huán)境
127.0.0.1:5555用于引發(fā)502狀態(tài)碼的服務(wù)測試。
127.0.0.1:6666 用于引發(fā)502狀態(tài)碼引發(fā)之后,Nginx 下的 recursive error pages 之后的代理轉(zhuǎn)發(fā)到的服務(wù)節(jié)點(diǎn)
步驟:
PS:因當(dāng)前服務(wù)已安裝響應(yīng)的模塊bottle.所以直接的使用它來啟動(dòng)一個(gè)簡單的服務(wù)即可
搭建服務(wù)1:
#!/usr/bin/evn python
# coding=utf-8
from bottle import route, run, abort,request
from urllib.parse import quote, unquote
import urllib
def write_request_headers_log():
"""寫客戶端訪問路由的日志記錄"""
# 記錄客戶端提交的參數(shù)
request_log = '\nheaders:'
try:
request_log = request_log + '\nheaders:' + urllib.parse.unquote(str(request.headers.__dict__))
except:
request_log = request_log + '\nheaders:' + urllib.parse.unquote(str(request.headers))
try:
pass
# log_helper.request_log(request_log + '\n')
except:
# log_helper.request_log(request_log + '頭部記錄異常')
pass
print(request_log)
@route('/')
def index():
write_request_headers_log()
print(request.query_string)
print(request.forms)
return "你好"
@route('/hello/502')
def index():
write_request_headers_log()
write_request_headers_log()
print(request.query_string)
print(request.forms)
abort(502)
run(host='127.0.0.1', port=5555,debug=True,reloader=True)
搭建服務(wù)2:
#!/usr/bin/evn python
# coding=utf-8
from bottle import route, run, abort,request
from urllib.parse import quote, unquote
import urllib
def write_request_headers_log():
"""寫客戶端訪問路由的日志記錄"""
# 記錄客戶端提交的參數(shù)
request_log = '\nheaders:'
try:
request_log = request_log + '\nheaders:' + urllib.parse.unquote(str(request.headers.__dict__))
except:
request_log = request_log + '\nheaders:' + urllib.parse.unquote(str(request.headers))
try:
pass
# log_helper.request_log(request_log + '\n')
except:
# log_helper.request_log(request_log + '頭部記錄異常')
pass
print(request_log)
@route('/')
def index():
print('我是服務(wù)2')
write_request_headers_log()
print(request.query_string)
print(request.forms)
return "你好"
@route('/hello/502')
def index():
print('我是服務(wù)2')
write_request_headers_log()
write_request_headers_log()
print(request.query_string)
print(request.forms)
run(host='127.0.0.1', port=6666,debug=True,reloader=True)
nginx 配置(沒啟用recursive error pages 的情況下)
upstream ceshsihii_test {
server 127.0.0.1:5555 weight=1 max_fails=0 fail_timeout=12s;
}
upstream ceshsihii6666_test {
server 127.0.0.1:6666 weight=1 max_fails=0 fail_timeout=12s;
}
server {
listen 5554;
charset utf-8;
server_name 127.0.0.1;
location / {
proxy_pass http://ceshsihii_test;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 300; #nginx跟后端服務(wù)器連接超時(shí)時(shí)間(代理連接超時(shí))
proxy_send_timeout 300; #后端服務(wù)器數(shù)據(jù)回傳時(shí)間(代理發(fā)送超時(shí))
proxy_read_timeout 300; #連接成功后,后端服務(wù)器響應(yīng)時(shí)間(代理接收超時(shí))
error_page 502 = @fetch;
}
location @fetch {
proxy_pass http://ceshsihii6666_test;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 300; #nginx跟后端服務(wù)器連接超時(shí)時(shí)間(代理連接超時(shí))
proxy_send_timeout 300; #后端服務(wù)器數(shù)據(jù)回傳時(shí)間(代理發(fā)送超時(shí))
proxy_read_timeout 300; #連接成功后,后端服務(wù)器響應(yīng)時(shí)間(代理接收超時(shí))
}
access_log /data/logs/nginx/ceshsihii_test.log main;
}
測試啟動(dòng)
[root@web-1 ceshi]# python server_5555.py
Bottle v0.12.10 server starting up (using WSGIRefServer())...
Listening on http://127.0.0.1:5555/
Hit Ctrl-C to quit.
[root@web-1 ceshi]# python server_6666.py
Bottle v0.12.10 server starting up (using WSGIRefServer())...
Listening on http://127.0.0.1:6666/
Hit Ctrl-C to quit.
測試服務(wù)響應(yīng)正常:
[root@web-1 ~]# curl http://127.0.0.1:5554/
你好[root@web-1 ~]#
測試502響應(yīng)
[root@web-1 ~]# curl http://127.0.0.1:5554/hello/502
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html>
<head>
<title>Error: 502 Bad Gateway</title>
<style type="text/css">
html {background-color: #eee; font-family: sans;}
body {background-color: #fff; border: 1px solid #ddd;
padding: 15px; margin: 15px;}
pre {background-color: #eee; border: 1px solid #ddd; padding: 5px;}
</style>
</head>
<body>
<h1>Error: 502 Bad Gateway</h1>
<p>Sorry, the requested URL <tt>'http://127.0.0.1/hello/502'</tt>
caused an error:</p>
<pre>Unknown Error.</pre>
</body>
</html>
[root@web-1 ~]#
此時(shí)5555端口的服務(wù)節(jié)點(diǎn)的響應(yīng)也是502:
<bottle.FormsDict object at 0x7f39e0279e80>
127.0.0.1 - - [29/Oct/2020 13:27:27] "GET /hello/502 HTTP/1.0" 502 718
6666服務(wù)節(jié)點(diǎn)沒任何的響應(yīng):
查看ngin日志:
127.0.0.1 - 127.0.0.1:5555 [29/Oct/2020:13:27:27 +0800-1603949247.669] "GET /hello/502 HTTP/1.1" [0.006] [0.005]502 718 "" "curl/7.29.0" "" ""
修改Nginx配置信息:(啟用recursive error pages 的情況下)
修改Nginx配置信息:
upstream ceshsihii_test {
server 127.0.0.1:5555 weight=1 max_fails=0 fail_timeout=12s;
}
upstream ceshsihii6666_test {
server 127.0.0.1:6666 weight=1 max_fails=0 fail_timeout=12s;
}
server {
listen 5554;
charset utf-8;
server_name 120.77.63.115;
proxy_intercept_errors on;
recursive_error_pages on;
location / {
proxy_pass http://ceshsihii_test;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 300; #nginx跟后端服務(wù)器連接超時(shí)時(shí)間(代理連接超時(shí))
proxy_send_timeout 300; #后端服務(wù)器數(shù)據(jù)回傳時(shí)間(代理發(fā)送超時(shí))
proxy_read_timeout 300; #連接成功后,后端服務(wù)器響應(yīng)時(shí)間(代理接收超時(shí))
error_page 502 = @fetch;
}
location @fetch {
proxy_pass http://ceshsihii6666_test;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 300; #nginx跟后端服務(wù)器連接超時(shí)時(shí)間(代理連接超時(shí))
proxy_send_timeout 300; #后端服務(wù)器數(shù)據(jù)回傳時(shí)間(代理發(fā)送超時(shí))
proxy_read_timeout 300; #連接成功后,后端服務(wù)器響應(yīng)時(shí)間(代理接收超時(shí))
}
access_log /data/logs/nginx/ceshsihii_test.log main;
}
關(guān)鍵修改點(diǎn),新增:
proxy_intercept_errors on;
recursive_error_pages on;
說明: proxy_intercept_errors on; 當(dāng)上游服務(wù)器響應(yīng)頭回來后,可以根據(jù)響應(yīng)狀態(tài)碼的值進(jìn)行攔截錯(cuò)誤處理,
通常是結(jié)合error_page 指令進(jìn)行使用。用在訪問上游服務(wù)器出現(xiàn)錯(cuò)誤的情況下。
recursive_error_pages on; 可以讓下面的location @fetch生效
再進(jìn)行服務(wù)的測試:
訪問的經(jīng)過的Nginx的路由節(jié)點(diǎn):
[root@web-1 ~]# curl http://127.0.0.1:5554/hello/502?5467456=345345
[root@web-1 ~]#
此時(shí):5555服務(wù)的節(jié)點(diǎn)響應(yīng)的是502的信息
<bottle.FormsDict object at 0x7fcfb9a88c50>
127.0.0.1 - - [29/Oct/2020 13:35:53] "GET /hello/502?5467456=345345 HTTP/1.0" 502 733
此時(shí):6666服務(wù)的節(jié)點(diǎn)響應(yīng)的是200的響應(yīng)信息
<bottle.FormsDict object at 0x7f9a54317400>
127.0.0.1 - - [29/Oct/2020 13:35:53] "GET /hello/502?5467456=345345 HTTP/1.0" 200 0
查看的最終的nginx日志信息為:
27.0.0.1 - 127.0.0.1:5555 [29/Oct/2020:13:27:27 +0800-1603949247.669] "GET /hello/502 HTTP/1.1" [0.006] [0.005]502 718 "" "curl/7.29.0" "" ""
127.0.0.1 - 127.0.0.1:5555 : 127.0.0.1:6666 [29/Oct/2020:13:31:24 +0800-1603949484.675] "GET /hello/502 HTTP/1.1" [0.005] [0.002 : 0.003]200 0 "" "curl/7.29.0" "" ""
127.0.0.1 - 127.0.0.1:5555 : 127.0.0.1:6666 [29/Oct/2020:13:32:31 +0800-1603949551.442] "GET /hello/502 HTTP/1.1" [0.004] [0.003 : 0.001]200 0 "" "curl/7.29.0" "" ""
127.0.0.1 - 127.0.0.1:5555 : 127.0.0.1:6666 [29/Oct/2020:13:33:26 +0800-1603949606.396] "GET /hello/502?5467456=345345 HTTP/1.1" [0.005] [0.003 : 0.001]200 0 "" "curl/7.29.0" "" ""
127.0.0.1 - 127.0.0.1:5555 : 127.0.0.1:6666 [29/Oct/2020:13:35:53 +0800-1603949753.523] "GET /hello/502?5467456=345345 HTTP/1.1" [0.009] [0.008 : 0.001]200 0 "" "curl/7.29.0" ""
實(shí)踐結(jié)果
說明,錯(cuò)誤的響應(yīng)的時(shí)候,可以進(jìn)行再次的轉(zhuǎn)發(fā)了!