Nginx 下的 recursive error pages 命令的实践(多级错误重试)

说明

部分的服务节点经常再经过了nginx已经进入到了上游服务器服务内部之后,因为一些未知的原因,如第三方接口的请求超时等,也会引起的服务的502的响应异常,如何再此类的情况解决节点不直接的响应返回的502的状态码和结果信息,或者重试。
本实践主要是尝试这种方案的可行性。

应用场景

此场景仅限于自己业务中,比如当某个业务进行到内部服务器且经过第三方接口直充成功的之后,突然的莫名成的程序进程崩溃或无响应的时候,此时重新提交一下相关的接口进行分发核对一下具体的充值接口情况,避免返回给第三方服务商的的接口状态是502的响应。
正常来说充值类的业务最好不要进行二次的确认提交,不过我这边进行加锁处理,目前暂时先这样处理!

环境

首先配置一下具体的服务

nginx 的配置环境
127.0.0.1:5555用于引发502状态码的服务测试。
127.0.0.1:6666 用于引发502状态码引发之后,Nginx 下的 recursive error pages 之后的代理转发到的服务节点

步骤:

PS:因当前服务已安装响应的模块bottle.所以直接的使用它来启动一个简单的服务即可
搭建服务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():
    """写客户端访问路由的日志记录"""
    # 记录客户端提交的参数
    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)

搭建服务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():
    """写客户端访问路由的日志记录"""
    # 记录客户端提交的参数
    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('我是服务2')
    write_request_headers_log()
    print(request.query_string)
    print(request.forms)
    return "你好"

@route('/hello/502')
def index():
    print('我是服务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跟后端服务器连接超时时间(代理连接超时)
        proxy_send_timeout         300; #后端服务器数据回传时间(代理发送超时)
        proxy_read_timeout         300; #连接成功后,后端服务器响应时间(代理接收超时)
        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跟后端服务器连接超时时间(代理连接超时)
        proxy_send_timeout         300; #后端服务器数据回传时间(代理发送超时)
        proxy_read_timeout         300; #连接成功后,后端服务器响应时间(代理接收超时)
    }
    
    access_log  /data/logs/nginx/ceshsihii_test.log  main;
}

测试启动

[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.

测试服务响应正常:

[root@web-1 ~]# curl http://127.0.0.1:5554/
你好[root@web-1 ~]#

测试502响应

[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>&#039;http://127.0.0.1/hello/502&#039;</tt>
               caused an error:</p>
            <pre>Unknown Error.</pre>
        </body>
    </html>
[root@web-1 ~]# 

此时5555端口的服务节点的响应也是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服务节点没任何的响应:

查看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跟后端服务器连接超时时间(代理连接超时)
        proxy_send_timeout         300; #后端服务器数据回传时间(代理发送超时)
        proxy_read_timeout         300; #连接成功后,后端服务器响应时间(代理接收超时)
        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跟后端服务器连接超时时间(代理连接超时)
        proxy_send_timeout         300; #后端服务器数据回传时间(代理发送超时)
        proxy_read_timeout         300; #连接成功后,后端服务器响应时间(代理接收超时)
    }
    
    access_log  /data/logs/nginx/ceshsihii_test.log  main;
}



关键修改点,新增:

    proxy_intercept_errors on; 
    recursive_error_pages on; 


说明: proxy_intercept_errors on; 当上游服务器响应头回来后,可以根据响应状态码的值进行拦截错误处理,
通常是结合error_page 指令进行使用。用在访问上游服务器出现错误的情况下。

recursive_error_pages on; 可以让下面的location @fetch生效

再进行服务的测试:

访问的经过的Nginx的路由节点:
[root@web-1 ~]# curl http://127.0.0.1:5554/hello/502?5467456=345345
[root@web-1 ~]# 
此时:5555服务的节点响应的是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
此时:6666服务的节点响应的是200的响应信息
<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" ""

实践结果

说明,错误的响应的时候,可以进行再次的转发了!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343