连接到上游时 NGINX 和 nodejs 上游连接超时,但请求将在 60 秒后得到响应
NGINX and nodejs upstream connection timed out while connecting to upstream but request will get responded after exactly 60s
后续 HTTP 请求 GET 和 POST 有时会在 60 秒内得到响应,而其他时候请求在 100 毫秒内得到响应。我应该如何解决这个问题?我认为这与我的 nodejs 后端和 mysql 连接有关,不一定与 nginx 反向代理和 docker 这些都存在的容器有关。
这是我经常遇到的 nginx 错误:
2022/01/10 16:43:15 [error] 33#33: *985 upstream timed out (110: Connection timed out) while connecting to upstream, client: xxx.xxx.xxx.xxx, server: sub.domain.tld, request: "GET /getTemp?api_key=xxxxxxx HTTP/1.1", upstream: "http://127.0.0.1:8080/getTemp?api_key=xxxxxxx", host: "sub.domain.tld"
我曾尝试按照其他帖子的建议将 nginx proxy_read_timeout
增加到 120s,但这不是这里的解决方法。我也从 mysql.createConnection()
切换到 mysql.createPool()
但这并没有解决它。
这是我到 mysql 数据库的 nodejs 连接:
let pool = mysql.createPool({
connectionLimit: 10,
host: process.env.DB_HOST,
user: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
timezone: 'Europe/Helsinki'
});
这是 getTemp 端点的片段:
app.get('/getTemp', (req, res) =>{
console.log(req.path);
let ip = req.header('x-forwarded-for') || req.socket.remoteAddress;
let ua = req.get('user-agent');
console.log(ua);
let {api_key} = req.query;
console.log(req.query);
if(api_key == process.env.API_KEY){
console.log(`Authorized access from IP: '${ip}'`);
// if one of the variables are undefined then send 400 status code to the client
if(api_key == undefined){
return res.sendStatus(400).send({message:"One or more variables are undefined"});
}
sql_query = "SELECT * FROM tempData ORDER BY id DESC";
sql_query = mysql.format(sql_query);
// attempt to query mysql server with the sql_query
pool.query(sql_query, (error, result) =>{
if (error){
// on error log the error to console and send 500 status code to client
console.log(error);
return res.sendStatus(500);
};
// if temp is found we send 200 status code to client
if(result.length > 0){
let currentTemp = result[0].currentTemp;
console.log(`Temp: ${currentTemp}`);
return res.status(200).send({temperature:currentTemp});
}else{
// incase temp is not found then we send 500 status code to client
console.log('Temperature not found');
return res.status(500).send({error:"Temperature not found"});
}
});
}else{
// if client sends invalid api key then send 403 status code to the client
console.log(`Unauthorized access using API key '${api_key}' from IP: '${ip}'`);
return res.sendStatus(403);
}
})
这是我的 nginx 配置:
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 4096;
}
http {
server {
listen 80;
listen [::]:80;
listen 443 default_server ssl;
listen [::]:443 ssl;
ssl_certificate /cert.pem;
ssl_certificate_key /cert.key;
server_name sub.domain.tld;
location / {
proxy_read_timeout 120;
proxy_pass http://localhost:8080;
proxy_set_header X-Real-IP $http_cf_connecting_ip;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
}
}
}
我为端点分配了静态值,因此它不会从数据库中查询任何内容,而且它还需要一分钟的时间来响应,所以不是数据库连接或端点导致了问题。我在应用程序中禁用了速率限制,并且不再超时。所以我超时的原因是配置错误的速率限制。
后续 HTTP 请求 GET 和 POST 有时会在 60 秒内得到响应,而其他时候请求在 100 毫秒内得到响应。我应该如何解决这个问题?我认为这与我的 nodejs 后端和 mysql 连接有关,不一定与 nginx 反向代理和 docker 这些都存在的容器有关。
这是我经常遇到的 nginx 错误:
2022/01/10 16:43:15 [error] 33#33: *985 upstream timed out (110: Connection timed out) while connecting to upstream, client: xxx.xxx.xxx.xxx, server: sub.domain.tld, request: "GET /getTemp?api_key=xxxxxxx HTTP/1.1", upstream: "http://127.0.0.1:8080/getTemp?api_key=xxxxxxx", host: "sub.domain.tld"
我曾尝试按照其他帖子的建议将 nginx proxy_read_timeout
增加到 120s,但这不是这里的解决方法。我也从 mysql.createConnection()
切换到 mysql.createPool()
但这并没有解决它。
这是我到 mysql 数据库的 nodejs 连接:
let pool = mysql.createPool({
connectionLimit: 10,
host: process.env.DB_HOST,
user: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
timezone: 'Europe/Helsinki'
});
这是 getTemp 端点的片段:
app.get('/getTemp', (req, res) =>{
console.log(req.path);
let ip = req.header('x-forwarded-for') || req.socket.remoteAddress;
let ua = req.get('user-agent');
console.log(ua);
let {api_key} = req.query;
console.log(req.query);
if(api_key == process.env.API_KEY){
console.log(`Authorized access from IP: '${ip}'`);
// if one of the variables are undefined then send 400 status code to the client
if(api_key == undefined){
return res.sendStatus(400).send({message:"One or more variables are undefined"});
}
sql_query = "SELECT * FROM tempData ORDER BY id DESC";
sql_query = mysql.format(sql_query);
// attempt to query mysql server with the sql_query
pool.query(sql_query, (error, result) =>{
if (error){
// on error log the error to console and send 500 status code to client
console.log(error);
return res.sendStatus(500);
};
// if temp is found we send 200 status code to client
if(result.length > 0){
let currentTemp = result[0].currentTemp;
console.log(`Temp: ${currentTemp}`);
return res.status(200).send({temperature:currentTemp});
}else{
// incase temp is not found then we send 500 status code to client
console.log('Temperature not found');
return res.status(500).send({error:"Temperature not found"});
}
});
}else{
// if client sends invalid api key then send 403 status code to the client
console.log(`Unauthorized access using API key '${api_key}' from IP: '${ip}'`);
return res.sendStatus(403);
}
})
这是我的 nginx 配置:
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 4096;
}
http {
server {
listen 80;
listen [::]:80;
listen 443 default_server ssl;
listen [::]:443 ssl;
ssl_certificate /cert.pem;
ssl_certificate_key /cert.key;
server_name sub.domain.tld;
location / {
proxy_read_timeout 120;
proxy_pass http://localhost:8080;
proxy_set_header X-Real-IP $http_cf_connecting_ip;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
}
}
}
我为端点分配了静态值,因此它不会从数据库中查询任何内容,而且它还需要一分钟的时间来响应,所以不是数据库连接或端点导致了问题。我在应用程序中禁用了速率限制,并且不再超时。所以我超时的原因是配置错误的速率限制。