Nginx 下 504 Gateway Time-out 解决方案

当Nginx作为反向代理,SpringBoot作为后端服务时,长时间处理的请求可能导致504 Gateway Time-out错误。本文介绍了两种解决方案:1) 不推荐关闭超时设置;2) 通过后台持续向响应中写入数据,防止Nginx超时。实现方法包括创建一个线程,在后台处理数据时周期性地向响应写入数据,确保nginx与后台连接不超时。

背景:Nginx做反向代理,springboot为后端服务。

问题:通过浏览器向后台发起请求够,由于后台处理时间长,出现504 Gateway Time-out,实际后台程序依然在执行。如何解决?

如果你恰好在寻找这种问题的解决方案,并且不喜欢啰嗦,直接移动到:两种解决方案

目录

两种解决方案


504从哪来:本文的场景下504是nginx返回的。

nginx配置中控制该超时时间的属性:

Syntax:proxy_read_timeout time;
Default:
proxy_read_timeout 60s;
Context:httpserverlocation

官方地址:Module ngx_http_proxy_module (nginx.org)

官方描述如下:Defines a timeout for reading a response from the proxied server. The timeout is set only between two successive read operations, not for the transmission of the whole response. If the proxied server does not transmit anything within this time, the connection is closed.

一个请求有三方参与:浏览器,nginx,后台服务器。

504的错误码是有nginx返回的。结合官网的解释,我们可以得出结论:

当nginx与后台的链接两次读取有效数据之间超过配置的时间时,就会产生504超时。nginx会主动关闭与后台服务器的链接。注意是两次成功读取的间隔,不是整个reponse的时间。

默认情况下proxy_read_timeout时60s。

如果你百度或google,通常解决方式有两种:提高后台处理效率增大proxy_read_timeout

增大方法很简单,proxy_read_timeout  [你期望的时间]。

But,后台效率提升总是有极限的。而proxy_read_timeout是固定值。总会有些正常业务场景,超过了设置的timeout值。

两种解决方案

本人解决的问题:上传excel文件后,由于文件大小无法预计,所以后台处理时间也无法预计。同时还要支持大文件的上传。上传后由后台解析处理。post请求,返回的是json。

一,关闭read-timout,可以实现,但是生产环境下你敢不设置超时时间么?所以不建议。

二,既然nginx只要从reponse成功读取数据两次的间隔在proxy_read_timeout设置的时间内,就不会超时。那么我们是不是可以通过持续的向response中写入数据来保证不超时呢。

答案是肯定的。

想通了这一点,实现就十分简单。

1,正常上传文件。

2,新建一个线程。持有response的引用,含有标志位,满足条件时循环执行,程序开始处理数据前,启动线程。

3,线程的功能只有一个,以固定间隔向response中写入数据。使nginx与后台链接不超时。

4,这里就需要注意,我的方法是返回json,同时要持续向response写入数据,所以我手动拼装json字符串。相当于在之前返回的json中增加一个属性,名称随意,我的叫pending,值随意,非空即可。我是用英文半角的句号" . "。

5,数据处理完后,回调线程的stop方法,终止线程中的循环。

注意:如有雷同纯属巧合。如果已经有大佬讲过这种解决方式,请艾特我,我立即删除本文。

保持线程代码如下:

#上下文代码
//获取鲜橙池executor,具体方式看个人。不会的直接百度,有很多
response.setContentType(ContentType.APPLICATION_JSON.getMimeType());
ResponseKeeper responseKeeper = new ResponseKeeper(response);
executorService.execute(responseKeeper);
#上下文代码


public class ResponseKeeper implements Runnable {

        /**
        * 循环标志:true时停止循环,终止线程
        */
        private boolean done = false;
        
        private HttpServletResponse response;

        public void stop(){
            done = true;
        }

        public ResponseKeeper(HttpServletResponse response) {
            this.response = response;
        }

        @Override
        public void run() {
            try {
                response.getWriter().write("{\"pending\":\"");
                while(!done){
                    response.getWriter().write(".");
                    response.getWriter().flush();
                    LOGGER.error("flush-{}", System.currentTimeMillis());
                    Thread.sleep(1000);
                }
                response.getWriter().write("\", \"status\": \"0\", \"msg\":\"success\"}");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

其他问题:

如果你遇到异常

IllegalStateException – if the getOutputStream method has already been called for this response object

那就说明你的程序中有地方调用过了,response.getOutputStream();

只需要与已有程序保持一致使用outputStream即可。

即将response.getWriter() 提换成 response.getOutputStream();

原因简单来讲就是这两个方法互斥。调用了一个就不能调用另一个。

补充:

如果你的应用前端不止一层nginx,整体组成是:客户端,nginx,nginx,服务端,本方案可能会失效,此时需要在第二个nginx中增加配置:

具体位置为:localtion / {} 中增加 proxy_buffering off; 

proxy_buffering关闭后可能会影响性能。具体位置应该可以再细化到具体的请求,有兴趣的可以自己试试。

欢迎打赏!

### 回答1: 504 Gateway Time-out是一种网络错误,通常发生在客户端(如您的浏览器)向服务器发送请求时的中间代理服务器(如Nginx服务器)无法从后端服务器(如应用服务器)收到响应时发生。这可能是因为后端服务器未能在一定时间内响应请求,或中间代理服务器出现故障或超时,或是网络连接出现问题等原因所导致。 要解决这个问题,您可以尝试以下几个步骤: 1. 刷新页面:由于这可能是一个暂时的错误,您可以尝试通过重新加载当前页面来解决问题。 2. 清除浏览器缓存:有时浏览器缓存可能会导致问题,您可以尝试清除浏览器缓存并重新加载页面。 3. 检查网络连接:您可以检查您的网络连接是否正常,以确定是否出现连接问题。 4.联系网站管理员:如果这个问题持续存在,您可以联系网站管理员,以获取更多信息和可能的解决方案。 总之,504 Gateway Time-out错误通常是由后端服务器或中间代理服务器出现故障或连接问题导致的,通过尝试以上方法来解决问题,可以更好地了解和解决问题。 ### 回答2: 504 Gateway Time-out是一种常见的错误,通常出现在网页无法加载或无法访问时。它意味着用户的请求被代理服务器或网关服务器转发到目标服务器时发生了超时。这种错误通常是由于代理服务器或网关服务器与目标服务器之间的连接超时或中断所致。 NGINX是一种流行的代理服务器和网关服务器,是构建高性能Web应用程序的理想选择。但是,在使用NGINX作为代理服务器时,可能会出现504 Gateway Time-out错误。这通常是由于以下原因之一导致的: 1. 服务器过载:当服务器无法处理太多的请求时,可能会导致访问请求超时以及出现504 Gateway Time-out错误。 2. DNS问题:如果代理服务器无法解析目标服务器的DNS,则代理服务器无法将请求路由到目标服务器。 3. 网络问题:当代理服务器与目标服务器之间的网络连接中断时,可能会导致504 Gateway Time-out错误。 4. 响应超时:当目标服务器无法在指定时间内响应请求时,代理服务器将超时,导致出现504 Gateway Time-out错误。 如果您遇到504 Gateway Time-out错误,可以尝试以下方法来解决它: 1. 重新加载网页:有时候这种错误是暂时的,重新加载网页可能会解决问题。 2. 检查网络连接:检查代理服务器与目标服务器之间的网络连接,确保它们之间没有任何中断或故障。 3. 扩展服务器资源:如果服务器过载,则可能需要增加服务器资源,例如增加带宽或CPU。 4. 检查DNS设置:确保代理服务器可以正确解析目标服务器的DNS。 5. 增加响应时间:如果目标服务器的响应时间过长,则可能需要增加响应时间,以确保代理服务器不会超时。 总之,504 Gateway Time-out错误是常见的网络错误之一,通常是由于代理服务器或网关服务器与目标服务器之间的连接超时或中断所致。如果您遇到这种错误,可以采取上述方法来解决问题。 ### 回答3: 504 Gateway Timeout是一个服务器错误代码,常见于Nginx服务器。它意味着客户端(如浏览器)已经能够连接到服务器,但服务器花费的时间过长,超过了等待时间限制导致请求超时。 简单来说,当你尝试访问一个网站时,如果该网站的Nginx服务器在处理请求时花费的时间超过了设定的时间限制,你就会遇到504错误。这种错误可能由于服务器负载过大、网络问题、程序错误等原因造成。 如果你遇到了504 Gateway Time-out错误,你可以从以下几个方面来尝试解决: 1.刷新网页。在一些情况下,网站服务器可能只是暂时无法响应请求,而刷新网页后会正常工作。 2.尝试连接其他网站。如果你只在一个特定的网站上遇到问题,那么问题可能只是从服务器端而来,而不是你的计算机或互联网连接的问题。 3.清除浏览器缓存。清除浏览器缓存可能会清除一些错误,使您的浏览器刷新并重新连接到服务器。 4.联系网站管理员。如果这个问题长时间存在,你可以联系网站管理员并报告这个问题。 为了避免这种错误,网站服务器应该进行正确的配置和优化,以确保服务器能够在处理大量请求时正常工作。此外,使用负载均衡和缓存模块也有助于减少服务器超时的情况出现。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fox_mt

真的帮助了你,而你又签好有钱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值