nginx设置连接超时解决504 gateway timeout

发布时间 2023-04-14 17:34:36作者: cps666

本文由 简悦 SimpRead 转码, 原文地址 blog.csdn.net

nginx做反向代理,默认请求是有一个60秒的超时,如果http请求超过了60秒,再返回,连接就会被nginx中断,前端就会得到504的错误:gateway time-out。

如下,我们可以通过实验验证,默认的超时时间是60秒:

1、我们在页面上,做一个耗时的请求,后台线程sleep(70*1000),模拟这个耗时操作,让这个耗时操作撑过60秒。默认情况下,不使用nginx做反向代理,请求会在70秒后,正常返回。

2、我们使用nginx反向代理,将http://127.0.0.1/struts2hack的请求,代理到http://127.0.0.1:8080上,就是默认正常的请求服务上。

接着,我们点击页面的测试按钮,我们等待1分钟,会出现如下图所示的结果:

请求在一分钟后,即60秒时连接被断开,返回504。这个结果符合预期,说明了nginx默认超时时间是60s,超过60s,连接会被断开,为此,我们需要解决这个问题,就需要设置nginx超时时间了,这里我们将超时时间设置为3600,就是一个小时,这个值可以灵活设置,就是不让他在默认60秒断开链接。

location ~ /struts2hack {
    proxy_pass  http://127.0.0.1:8080;
    proxy_read_timeout  3600;
}

设置之后,我们再次点击页面的测试按钮,我们得到的结果就和最初一样了,经过70秒,服务端返回了数据,请求完成。

前端页面代码:



1.  <%@ page language="java" contentType="text/html; charset=UTF-8"%>
2.  <!DOCTYPE html>
3.  <html>
4.      <head>
5.          <meta charset="UTF-8"/>
6.          <link rel="stylesheet" type="text/css" href="css/base.css"/>
7.          <script type="text/javascript" src="js/libs/jquery-1.12.4.min.js"></script>
8.      </head>
9.  	<body>
10.  		<h2>nginx timeout!</h2>
11.  		<div class="box">
12.  		     <input type="button" value="timeout测试" id="btn-test"/>
13.  		</div>
14.  		<div class="box">
15.  		     开始时间:<input type="text" >
16.  		</div>	
17.  		<div class="box">
18.  		     结束时间:<input type="text" >
19.  		</div>
20.  		<div class="box">
21.  		     返回数据:<input type="text" >
22.  		</div>	
23.  	</body>
24.  	<script type="text/javascript">
25.  	    $(function(){
26.  	    	$("#btn-test").click(function(e){
27.  	    		$.ajax({
28.  	    			url:"timeout!test.action",
29.  	    			type:"get",
30.  	    			beforeSend:function(){
31.  	    				$("#start").val(new Date());
32.  	    			},
33.  	    			success:function(data){
34.  	    				$("#data").val(data.message);
35.  	    				$("#end").val(new Date());
36.  	    			},
37.  	    			error:function(XMLHttpRequest,textStatus,errorThrown){
38.  	    				$("#end").val(new Date());
39.  	    				$("#data").val("timeout");
40.  	    			}
41.  	    		});
42.  	    	});
43.  	    });
44.  	</script>
45.  </html>


后端模拟70秒的耗时请求:



1.  package com.xxx.action;
2.  import java.io.PrintWriter;
3.  import javax.servlet.http.HttpServletResponse;
4.  import org.apache.struts2.ServletActionContext;
5.  public class TimeoutAction {
6.  	public String test() {
7.  		HttpServletResponse response = ServletActionContext.getResponse();
8.  		response.setContentType("application/json;charset=UTF-8");
9.  		PrintWriter out = null;
10.  		try {
11.  			Thread.sleep(70*1000);
12.  			out = response.getWriter();
13.  			String content = "{\"code\":200,\"message\":\"ok\"}";
14.  			out.write(content);
15.  		} catch (Exception e) {
16.  			e.printStackTrace();
17.  		}finally {
18.  			if(out!=null) {
19.  				out.close();
20.  			}
21.  		}
22.  		return null;
23.  	}
24.  }


最初,我以为使用了jQuery的ajax请求超时,那么需要对ajax做一个超时设置,给参数timeout 设置上一个值,但是最终,发现问题不在ajax超时上,因为默认ajax是不会有超时的,就是永不超时,timeout:0就是默认值。这些可以在JQuery源码中找到。