使用Spring Cloud Gateway和Nginx作为反向代理的网关超时

Nit*_*iya 11 java nginx spring-cloud nginx-reverse-proxy spring-cloud-gateway

我为我的应用程序创建了API网关,它将充当其他微服务的前端控制器。在生产设置中,我将Nginx用户用作网关的反向代理

API网关在端口8080上运行

Nginx的配置如下

gateway-api.conf:

server {
    listen 80;
    server_name api.example.com;
    location / {
        proxy_set_header        X-Real-IP       $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_pass http://localhost:30010/;
        keepalive_timeout 500s;
    }
    keepalive_timeout 500s;
    access_log /var/log/nginx/api.log;  
    error_log /var/log/nginx/api_error.log;
}
Run Code Online (Sandbox Code Playgroud)

nginx.conf中的超时设置

proxy_connect_timeout 300;
proxy_send_timeout 300;
proxy_read_timeout 300;
send_timeout 300;
Run Code Online (Sandbox Code Playgroud)

Spring Cloud Gateway Gradle文件:

compile('org.springframework.cloud:spring-cloud-starter-gateway')
 compile('org.springframework.cloud:spring-cloud-starter-openfeign')
 compile("org.springframework.boot:spring-boot-starter-actuator")
 compile('org.springframework.boot:spring-boot-starter-security')

springBootVersion=2.0.3.RELEASE
springDMPVersion=1.0.4.RELEASE
springPlatformBomVersion=Cairo-SR2
springCloudVersion=Finchley.RELEASE
Run Code Online (Sandbox Code Playgroud)

网关应用程序:

@SpringBootApplication
@ComponentScan(basePackages = {"com.example"})
@EntityScan(basePackages = {"com.example"})
@EnableFeignClients(basePackages = "com.example")
public class GatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}
Run Code Online (Sandbox Code Playgroud)

问题陈述:

在我的一项微服务中,一个REST API花费了3分钟以上的时间才能完成。如果我通过nginx(api.example.com)调用此API,则它恰好在1分钟后失败并给出HTTP状态504

卷曲:

curl --request GET \
  --url http://api.example.com/hellomicroservice/api/take/moretime
Run Code Online (Sandbox Code Playgroud)

错误:

504 Timeout while reading the response from Server
Run Code Online (Sandbox Code Playgroud)

Nginx和API网关中没有错误日志

来自Nginx的访问日志:

203.129.213.102 - - [01/Apr/2019:08:14:33 +0000] "GET hellomicroservice/api/take/moretime HTTP/1.1" 499 0 "-" "PostmanRuntime/7.3.0"
Run Code Online (Sandbox Code Playgroud)

但是,当我直接向网关(在网关端口8080上)调用相同的API时,请求过程成功

卷曲与网关端口:

curl --request GET \
  --url http://api.example.com:8080/hellomicroservice/api/take/moretime
Run Code Online (Sandbox Code Playgroud)

编辑:如果我将Nginx超时设置应用为少于60秒(例如30秒),则请求将在指定的时间间隔内超时。但是,如果我将Nginx超时设置为60秒以上,则设为300秒,则60秒后请求将超时。

Kri*_*ris 1

看来请求超时对您来说不是问题。其连接超时。我认为我们需要看看标题

联系

AFAIK,Connection标头定义,连接应该是持久的或者谁有权维护/关闭它。如果连接是keep-alive,那么该连接将是持久的。对于保持活动连接,客户端偶尔会发送 TCP ping 以确保服务器仍然活动并保持连接。根据curl,此时间默认为每60 秒一次。

现在nginx必须配置为接受连接并使用该指令使其保持活动状态一段时间keepalive_timeout。如果不存在,则nginx不会保持连接活动

这应该就是 nginx在日志中显示499的原因。HTTP499是 nginx 中的一个常见错误,表示客户端关闭了连接。在你的情况下curl关闭了它。为什么curl关闭它?因为nginx没有响应60秒的TCP ping,因为keep-alive没有启用。

添加keepalive_timeout~500 或比应用程序超时更高的值应该可以解决您的问题。

那么,为什么它直接与tomcat一起工作呢?我认为 spring 使活动超时可以是无限的或非常高的值。通常在 tomcat 中也是 60 秒。

我希望这能解决您的问题。