问题描述
Spring Cloud Gateway依赖于Netty实现请求的转发,由于TCP连接建立和释放都较为消耗资源,其内部会维护一个连接池,新请求会优先使用连接池内部的连接,但是由于以下原因,连接池中的连接可能是不可用的:
- 云服务器厂商提供的环境中,不同服务之间的网络请求会先经过防火墙,防火墙会杀掉空闲过久的连接,没有通知调用的双方,导致请求发起者再使用该连接时,发送的数据会被防火墙直接丢弃。
- Tomcat默认
keepAliveTimeout
为20s,如果刚好在Tomcat关闭连接的途中,发起方使用该连接写数据,则会提示请求已关闭的错误,具体异常为:reactor.netty.http.client.PrematureCloseException
解决方案
可以改变Netty从连接池取连接的策略为后进先出:-D reactor.netty.pool.leasingStrategy=lifo
,并修改连接的最大空闲时间,让其小于下游Tomcat的keepAliveTimeout
:spring.cloud.gateway.httpclient.pool.maxIdleTime=10000
tomcat还有个参数配置一个连接最大处理请求的个数,超过这个值也会断开连接,默认是100,可以通过设置server.tomcat.maxKeepAliveRequests=-1
来不限制请求个数。