当网页无法正常访问,浏览器会及时通过数字代码(HTTP状态码)告知用户到底发生了什么,从而对问题开展排查并最终解决提供一定的帮助。
这些数字代码就是HTTP状态码,HTTP状态码分为5大家族,其中2xx、4xx、5xx家族是大家比较熟悉的,比如200、404、502等。
本文将结合HTTP 502/504 状态码学习nginx两项关键参数配置proxy_read_timeout、proxy_connect_timeout,当参数生效后,触发特定条件将会出现502/504两个状态码。
一、状态码的含义
-
502状态码
502 Bad Gateway:作为网关或者代理工作的服务器尝试向上游服务器发起请求时,收到了无效的响应。
-
504状态码
504 Gateway Time-out:作为网关或者代理工作的服务器向上游服务器发起请求时,未能在一定的时间内从上游服务器收到响应。
两者的区别就是,一个是收到响应但无效,一个是超时并未能收到响应。
二、nginx配置项的含义
-
proxy_connect_timeout
网关服务器向上游服务器建立连接的超时时间,默认60s。
-
proxy_read_timeout
网关服务器向上游服务器读取数据的超时时间,也可以理解为后端服务器处理请求的超时时间,默认为60s。
三、环境准备服务器环境
服务器用途 | IP地址 | OS版本 | 安装软件 |
---|---|---|---|
网关(代理)服务器 | 192.168.229.133 | Ubuntu 18.04.3 LTS | nginx/1.14.0 |
上游服务器(应用服务器) | 192.168.229.134 | Ubuntu 18.04.3 LTS | Tomcat7/JDK7 |
应用环境
- 将hello.jsp放置到tomcat目录下的webapps/ROOT/根目录下
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
String str = "hello world";
Thread.sleep(20000); //延时20秒
out.println(str);
%>
</body>
</html>
- 启动tomcat
四、实验过程
- nginx配置如下,并重载
server {
listen 8081;
server_name _;
location / {
proxy_connect_timeout 15s;
proxy_read_timeout 15s;
proxy_pass http://192.168.229.134:8080/hello.jsp;
}
}
2.模拟502的发生
第一步: 停掉上游服务器和关闭防火墙
第二步: 测试
lvzhiqiang@DESKTOP-F60S61M:/mnt/c/Users/Q$ date;time curl -I http://192.168.229.133:8081/hello.jsp;
Wed Feb 19 09:39:22 CST 2020
HTTP/1.1 502 Bad Gateway
Server: nginx/1.14.0 (Ubuntu)
Date: Wed, 19 Feb 2020 01:39:22 GMT
Content-Type: text/html
Content-Length: 182
Connection: keep-alive
real 0m0.053s
user 0m0.016s
sys 0m0.031s
第三步: 查看网关error日志
2020/02/19 09:39:22 [error] 22582#22582: *14 connect() failed (111: Connection refused) while connecting to upstream, client: 192.168.229.1, server: _, request: "HEAD /hello.jsp HTTP/1.1", upstream: "http://192.168.229.134:8080/hello.jsphello.jsp", host: "192.168.229.133:8081"
小结: 通过以上实验过程,可以看到502的出现和nginx两项配置(proxy_connect_timeout, proxy_read_timeout)并无关系,主要原因是上游服务器给回响应是无效的。
- 模拟2次 504的发生
- 1) 第一次,模拟504的发生
第一步: 上游服务器服务恢复和开启防火墙并拒绝端口访问
第二步: 测试
lvzhiqiang@DESKTOP-F60S61M:/mnt/c/Users/Q$ date;time curl -I http://192.168.229.133:8081/hello.jsp;
Wed Feb 19 09:50:14 CST 2020
HTTP/1.1 504 Gateway Time-out
Server: nginx/1.14.0 (Ubuntu)
Date: Wed, 19 Feb 2020 01:50:29 GMT
Content-Type: text/html
Content-Length: 192
Connection: keep-alive
real 0m15.079s
user 0m0.000s
sys 0m0.031s
第三步: 观察网关error日志
2020/02/19 09:50:29 [error] 22582#22582: *18 upstream timed out (110: Connection timed out) while connecting to upstream, client: 192.168.229.1, server: _, request: "HEAD /hello.jsp HTTP/1.1", upstream: "http://192.168.229.134:8080/hello.jsphello.jsp", host: "192.168.229.133:8081"
小结: 通过以上实验过程,可以看到504的出现和nginx配置(proxy_connect_timeout 15s;)有关系,主要原因是网关同上游服务器无法在指定时间(15s)内建立连接,导致超时发生。
- 2)第二次,模拟504的发生
第一步: 上游服务器服务恢复和关闭防火墙并允许访问
第二步: 测试
lvzhiqiang@DESKTOP-F60S61M:/mnt/c/Users/Q$ date;time curl -I http://192.168.229.133:8081/;
Wed Feb 19 10:15:41 CST 2020
HTTP/1.1 504 Gateway Time-out
Server: nginx/1.14.0 (Ubuntu)
Date: Wed, 19 Feb 2020 02:15:55 GMT
Content-Type: text/html
Content-Length: 192
Connection: keep-alive
real 0m15.062s
user 0m0.016s
sys 0m0.016s
第三步: 观察网关error日志
2020/02/19 10:15:55 [error] 24646#24646: *26 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 192.168.229.1, server: _, request: "HEAD / HTTP/1.1", upstream: "http://192.168.229.134:8080/hello.jsp", host: "192.168.229.133:8081"
小结: 通过以上实验过程,可以看到504的出现和nginx配置(proxy_read_timeout 15s;)有关系,主要原因是网关已经同上游服务器建立连接,但是在等待读取上游给回的数据的时候(上游服务器代码加入一个sleep,延迟25s给回数据)发生超时。
总结: 通过以上实验过程,一方面增进对nginx参数的意义理解, 另一方面透过数字代码深入了解WEB服务的世界到底发生了什么!