在 flask 应用程序子 class 中调用 requests.get() 导致 uwsgi 分段错误和 nginx 上的 502

Invoking requests.get() within flask application sub-class is causing uwsgi segmentation fault and 502 on nginx

我当前的 Flask 应用程序设置存在问题,非常感谢对此提供一些意见。谢谢!

流量

user --> nginx --> uwsgi --> flask app --> https调用外部系统(处理响应并将相关数据返回给客户端)

工作流程

Intent 我的 flask view/route 调用另一个 class,其中一个 https (GET) 调用是对外部系统进行检索数据。然后处理(分析)此数据并将适当的响应发送给用户。

实际 用户在调用基于 Flask 的端点时从网络服务器收到 502 Bad Gateway。这只有在将 nginx 和 uwsgi 服务器放在我的烧瓶应用程序前面时才会发生。直接使用 Flask 的内置服务器在服务器上进行的初步测试似乎有效。

注意:那个分析位确实占用了一些时间所以我增加了所有相关的超时(无济于事)

配置

Nginx(尝试使用和不使用 TLS)

worker_processes  4;

error_log  /path/to/error.log;
pid        /path/to/nginx.pid;

events {
    worker_connections  1024;
}

http {
    default_type  application/json;
    access_log  /path/to/access.log;
    sendfile        on;
    keepalive_timeout  0; [multiple values tried]
    # HTTPS server
    server {
        listen       5555 ssl;
        server_name  my_host.domain.com;

        ssl_certificate      /path/to/server.crt;
        ssl_certificate_key  /path/to/server.key;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location /my_route {
            uwsgi_connect_timeout 60s;
            uwsgi_read_timeout 300s;
            client_body_timeout 300s;
            include uwsgi_params;
            uwsgi_pass unix:/path/to/my/app.sock;
        }

    }
}

uWSGI(作为故障排除尝试的一部分,线程减少到 1)

[uwsgi]
module = wsgi:app

harakiri = 300 [also added as part of troubleshooting steps]
logto = /path/to/logs/uwsgi_%n.log

master = true
processes = 1
threads = 1

socket = app.sock
chmod-socket = 766
vacuum = true
socket-timeout = 60

die-on-term = true

代码片段

主烧瓶Class(查看)

@app.route(my_route, methods=['POST'])
def my_view():
    request_json = request.json
    app.logger.debug(f"Request Received: {request_json}")
    schema = MySchema()
    try:
        schema.load(request_json)
        var1 = request_json["var1"]
        var2 = request_json["var2"]
        var3 = request_json["var3"]
        var4 = request_json["var4"]
        # begin
        execute = AnotherClass(client_home, config, var1, var2, var3, var4, mime_type)
        return jsonify(execute.result)
    except ValidationError as exception:
        error_message = json.dumps(exception.messages)
        abort(Response(error_message, 400, mimetype=mime_type))

Class 在外部系统上执行 HTTPS GET

custom_adapter = HTTPAdapter(max_retries=3)
session = requests.Session()
session.proxies = self.proxies
session.mount("https://", custom_adapter)
try:
    json_data = json.loads(session.get(process_endpoint, headers=self.headers, timeout=(3, 6)).text)

错误

Nginx

error] 22680#0: *1 upstream prematurely closed connection while reading response header from upstream, client: client_ip, server: server_name, request: "POST /my_route HTTP/1.1", upstream: "uwsgi://unix:/path/to/my/app.sock:", host: "server_name:5555"

用户收到 502(错误网关)

uWSGI

2020-04-24 16:57:23,873 - app.module.module_class - DEBUG - Endpoint: https://external_system.com/endpoint_details 2020-04-24 16:57:23,876 - urllib3.connectionpool - DEBUG - Starting new HTTPS connection (1): external_system.com:443 !!! uWSGI process #### got Segmentation Fault !!! * backtrace of #### /path/to/anaconda3/bin/uwsgi(uwsgi_backtrace+0x2e) [0x610e8e] /path/to/anaconda3/bin/uwsgi(uwsgi_segfault+0x21) [0x611221] /usr/lib64/libc.so.6(+0x363f0) [0x7f6c22b813f0] /path/to/anaconda3/lib/python3.7/lib-dynload/../../libssl.so.1.0.0(ssl3_ctx_ctrl+0x170) [0x7f6c191b77b0] /path/to/anaconda3/lib/python3.7/site-packages/cryptography/hazmat/bindings/_openssl.abi3.so(+0x5a496) [0x7f6c16de2496] .... end of backtrace * DAMN ! worker 1 (pid: ####) died :( trying respawn ... Respawned uWSGI worker 1 (new pid: ####)

已解决

步数

更新密码

更新请求

更新 urllib3

将缺少的 TLS 密码添加到 Py HTTP 适配器(遵循此 guide