使用 Nginx 反向代理 Docker 内部容器 空闲链接超时分析及解决

阅读时长 6 分钟读完

前言

随着容器化技术的普及,Docker 已经成为了开发和运维的常用工具。在常见的 Docker 应用场景中,经常使用到反向代理来对内部的多个容器进行统一访问。而 Nginx 作为一款高性能的反向代理服务器,成为了众多选择之一。然而,在实际的应用中,我们会发现 Nginx 和 Docker 结合后,会遇到一些问题。本文就是希望分享一下使用 Nginx 反向代理 Docker 内部容器时,如何避免空闲链接超时的问题。

背景

在使用 Docker 部署多个容器时,我们经常会使用 Nginx 进行反向代理,统一对外服务。而这个过程中,我们会发现有一些问题:

  1. 空闲链接超时
  2. 无法获取真实 IP 地址
  3. 无法加密连接

本文主要解决空闲链接超时的问题。

空闲链接超时

在 Nginx 中,有一个参数 proxy_read_timeout,默认值是 60 秒。如果在 60 秒内没有从后端服务器接收到任何数据,就会报错 "upstream timed out (110: Connection timed out) while reading response header from upstream",意思就是超时了。

如果后端服务器返回的内容很慢,在默认的 timeout 内没有返回完,会导致 Nginx 在返回的数据中出现一些缺失或异常比如一些字体或图片加载异常等视觉上的问题。

但是,如果我们将 proxy_read_timeout 改得越小,那么就会越容易因为延迟或者网络问题而出现错误,而我们实际上又不能一味地降低 timeout。这时,就需要换个思路,从如何保持背后的服务长时间活跃的角度考虑问题。

空闲链接超时原因

空闲链接超时是因为反向代理服务器在一段时间内没有接收到任何响应,导致连接中断。这种情况通常发生在后端容器在长时间闲置后,一段时间内没有任何响应。

这与 Docker 容器的内部网络有关。容器之间的网络是虚拟的,从容器内部看,容器之间的通信是直接的,但从宿主机器的角度看,docker0 接口为多个容器提供了虚拟的网关 IP,同时也给容器外部的主机提供了一个访问容器的接入点。和容器外部的世界保持联通,依赖于 Docker 的路由机制,该机制是基于 IPtables 实现的。由于容器数量变化多端,可以想象这条路由规则列表会非常长。当然这些路由规则也是可以重新加载的,而流量转发、负载均衡都是在路由阶段实现的,联通已经建立,容器之间的通信具备了始终出现的条件。然而这个过程不是实时的,可能会出现短暂的不可达性。

解决方案

为了解决这个问题,我们需要让 Nginx 定期往后端容器服务器发送一些请求,保持连接处于活跃状态,避免空闲连接超时。

方案一:定时 Nginx 请求

可以在 Nginx 的配置文件中通过 HTTP 模块实现定期向后端容器服务器发送一个类似心跳的请求,保持连接处于活跃状态。

示例代码:

-- -------------------- ---- -------
---- -
    -------- ------- -
        ------ ---------------
    -
    
    ------ -
        ------ ---
        ----------- ------------
        -------- - -
            ---------- ---------------
            ---------------- ---- ------
            ---------------- --------- -------------
            ---------------- --------------- ---------------------------

            - ------------
            ------------------ ----
            ---------------- ---------- ---
            ---------------- ---- ------
            ------------------------- ----
            --------------- ----
            ------------------ -------------
            ---------------------- ---
            ----------- ----
            ------------------ -----
            ------------------ -----
            ------------ -----

            -------------- -------------
            - ------------ ----
            - ----- ---- -----------
            ----------------- -----
        -
    -
-

这样就可以避免空闲连接超时问题,但有一个缺点是,在请求过程中会占用额外的带宽。

方案二:使用 TCP Keepalive

Nginx 提供了一种更优雅的方法来解决这个问题,就是使用 TCP Keepalive。TCP Keepalive 是 TCP 协议中的一种机制,用于检测长时间没有数据交换的连接,发送一个空闲探测包以确定连接是否仍然保持活动状态。

首先在 Nginx 配置文件中开启 keepalive 模块:

其中 keepalive_timeout 参数设置的是空闲连接的时间,我们可以把这个值设得足够大,比如 300 秒。

在服务端也需要进行相应的配置,来定期发送 TCP Keepalive 空闲探测包。在 CentOS 上配置 TCP Keepalive 如下:

这样,Nginx 客户端和服务端之间的空闲连接就可以被保持活跃了。

总结

本文介绍了如何使用 Nginx 反向代理 Docker 内部容器时,避免空闲链接超时的问题。我们可以通过定时发送请求或使用 TCP Keepalive 机制来保持连接处于活跃状态,避免因空闲链接超时而出现的错误。

在实际的生产环境中,我们需要选择合适的方法来解决问题,以便提高服务的可靠性和稳定性。同时,还需要针对不同的问题进行深入的分析和解决方案的优化,才能取得更好的效果。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64c8e7a15ad90b6d04150507

纠错
反馈