python - Nginx - 从上游读取响应标头时上游过早关闭连接
问题描述
我有一个关于 nginx 的问题,它可能比看起来更复杂。我有一个用烧瓶编写的应用程序,它在本地工作得很好。我在 Ubuntu 16.04.6 LTS 上设置它。我安装了 Nginx 1.10.3 并将其配置为代理。数据库是 MongoDB v4.2.3 我在本教程中设置了 Gunicorn:https ://www.digitalocean.com/community/tutorials/how-to-serve-flask-applications-with-gunicorn-and-nginx-on- ubuntu-18-04
问题是,当我尝试从 mongo 加载数据时,它会尝试处理请求 30 秒,然后抛出502 Bad Gateway。我查看了nginx 的 error.log:
[error] 12361#12361: *28 upstream prematurely closed connection while reading response header from upstream, client: 123.123.123.123, server: example.com, request: "GET /example_route/view_database/ HTTP/1.1", upstream: "http://unix:/home/user/flaskapp/src/application.sock:/example_route/view_database/", host: "example.com", referrer: "http://example.com/example_route"
至于mongod.log:
2020-04-09T22:18:29.534+0200 W QUERY [conn89] Plan executor error during distinct command: FAILURE, status: ClientDisconnect: operation was interrupted because a client disconnected, stats: { stage: "COLLSCAN", nReturned: 2745, executionTimeMillisEstimate: 24703, works: 2746, advanced: 2745, needTime: 1, needYield: 0, saveState: 1378, restoreState: 1377, isEOF: 0, direction: "forward", docsExamined: 2745 }
2020-04-09T22:18:29.534+0200 W COMMAND [conn89] Unable to gather storage statistics for a slow operation due to lock aquire timeout
2020-04-09T22:18:29.534+0200 I COMMAND [conn89] command db_name.col_name command: distinct { distinct: "elem", key: "some_key", lsid: { id: UUID("someid") }, $db: "db_name", $readPreference: { mode: "primaryPreferred" } } planSummary: COLLSCAN numYields:1378 ok:0 errMsg:"Executor error during distinct command :: caused by :: operation was interrupted because a client disconnected" errName:ClientDisconnect errCode:279 reslen:202 locks:{ ReplicationStateTransition: { acquireCount: { w: 1379 } }, Global: { acquireCount: { r: 1379 } }, Database: { acquireCount: { r: 1378 } }, Collection: { acquireCount: { r: 1378 } }, Mutex: { acquireCount: { r: 1 } } } protocol:op_msg 30475ms
2020-04-09T22:18:29.535+0200 I NETWORK [conn89] end connection 127.0.0.1:40296 (5 connections now open)
2020-04-09T22:18:29.614+0200 I NETWORK [conn88] end connection 127.0.0.1:40294 (4 connections now open)
2020-04-09T22:18:30.136+0200 I NETWORK [listener] connection accepted from 127.0.0.1:40310 #96 (5 connections now open)
2020-04-09T22:18:30.137+0200 I NETWORK [conn96] received client metadata from 127.0.0.1:40310 conn96: { driver: { name: "PyMongo", version: "3.10.1" }, os: { type: "Linux", name: "Linux", architecture: "x86_64", version: "4.4.0-165-generic" }, platform: "CPython 3.5.2.final.0" }
2020-04-09T22:18:30.160+0200 I NETWORK [listener] connection accepted from 127.0.0.1:40312 #97 (6 connections now open)
2020-04-09T22:18:30.160+0200 I NETWORK [conn97] received client metadata from 127.0.0.1:40312 conn97: { driver: { name: "PyMongo", version: "3.10.1" }, os: { type: "Linux", name: "Linux", architecture: "x86_64", version: "4.4.0-165-generic" }, platform: "CPython 3.5.2.final.0" }
另一件事是,当我尝试将数据上传到服务器时(上传对我来说更重要),我得到的只是一个弹出窗口,如下所示:
example.com says
INTERNAL SERVER ERROR
nginx 的 error.log中没有关于它的数据。当我在浏览器中查看开发控制台时,我只看到:
POST http://example.com/example_route/send 500 (INTERNAL SERVER ERROR)
这两件事都在我的笔记本电脑上本地运行得很好。
nginx服务器配置:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
client_max_body_size 100M;
location /static {
alias /home/user/flaskapp/src/app_here/static;
}
location / {
include proxy_params;
proxy_pass http://unix:/home/user/flaskapp/src/application.sock;
proxy_redirect off;
proxy_max_temp_file_size 16400M;
proxy_buffering off;
proxy_http_version 1.1;
proxy_read_timeout 36000s;
}
}
Gunicorn 进程配置:
[Unit]
Description=Gunicorn instance to serve flaskapp
After=network.target
[Service]
User=user
Group=www-data
WorkingDirectory=/home/user/flaskapp
Environment="PATH=/home/user/flaskapp/venv/bin"
ExecStart=/home/user/flaskapp/venv/bin/gunicorn --workers 3 --bind unix:application.sock -m 007 wsgi:app
[Install]
WantedBy=multi-user.target
在python中向服务器发送数据的函数:
@main.route('/example_route/send', methods=['POST'])
@login_required
def send():
data = request.json
new_data = Data_model(
timestamp = data['Timestamp'],
area = data["Area"],
image = data["Image"]
).save()
return redirect(url_for('main.data_viewer'))
和客户端的js:
$.ajax({
url: '/example_route/send',
type: "POST",
data: JSON.stringify(sendDict),
contentType: "application/json",
success: function (data) {
// success code
},
error: function (request, status, error) {
alert(request.statusText);
},
});
至于从服务器读取数据是:
@db_viewer.route('/example_route/view_database/')
@login_required
def view_database():
data = Data.objects.only('UID').distinct('UID')
return render_template('example_app/view_database.html', ids=data, user=current_user)
总而言之,有两个问题会带来噩梦,而我就是无法解决它们:
- 当我尝试将 json 数据发送到服务器时出现 500 内部服务器错误
- 当我尝试从数据库读取时出现上游错误
只是服务器上的问题,在本地都可以正常工作。
解决方案
推荐阅读
- c++ - 如何知道在这种情况下要编译什么?
- c# - 查询 System.Xml.Linq.XElement 中的元素
- python - 如何使用配置文件更改 Flask 服务器主机/端口?
- laravel - 存储在 laravel 上的奇怪问题
- ibm-doors - 传递给跳过列表的空参数
- c# - c# error cannot convert collection.generic.lists to classes
- r - 如何根据滑块输入选择过滤闪亮的日期(年份)?
- c++ - 从 PC 访问与声音相关的数据
- powershell - 尝试使用 Powershell 在 VSTS 中创建工作项时出现错误的请求错误
- python - 如何在 PyQt5 中将函数连接到动态创建的 QPushButtons