负载均衡详解:从四层、七层到 LVS、Keepalived、Nginx 与 HAProxy

负载均衡详解:从四层、七层到 LVS、Keepalived、Nginx 与 HAProxy

在单体应用的早期阶段,一台服务器通常就能处理全部请求。随着用户量、并发量和数据规模不断增长,单机逐渐会遇到 CPU、内存、网络带宽、连接数等方面的瓶颈。

最直接的扩展方式不是无限升级单台服务器,而是部署多台服务器共同处理请求。此时便需要一个流量调度入口,根据一定规则将请求分配给不同的后端节点,这就是负载均衡。

负载均衡解决的不只是"把请求平均分配"这一件事,它通常还承担以下职责:

  • 提升系统整体吞吐量;
  • 避免单台服务器过载;
  • 自动摘除故障节点;
  • 支持应用扩容和缩容;
  • 提高系统可用性;
  • 实现灰度发布、流量切分和容灾;
  • 隐藏后端服务器的真实地址;
  • 统一处理 TLS、访问日志、限流和安全策略。

需要注意,负载均衡并不会自动解决所有高并发问题。如果数据库、缓存、消息队列或某个第三方接口仍是单点瓶颈,即使增加再多应用服务器,系统吞吐量也不会线性增长。

1. 四层负载均衡与七层负载均衡

1.1 什么是四层负载均衡

四层负载均衡工作在 OSI 模型的传输层,主要根据以下信息分配连接:

  • 源 IP;
  • 源端口;
  • 目标 IP;
  • 目标端口;
  • TCP、UDP 等传输层协议。

这几个字段通常被称为"五元组"。

四层负载均衡一般不需要理解 HTTP URI、Cookie、请求头等应用层内容。只要能够识别连接,就可以将流量转发到某个后端服务器。

典型应用场景包括:

  • MySQL、PostgreSQL 等数据库连接;
  • Redis、Memcached 等缓存连接;
  • TCP 长连接;
  • MQTT、SMTP 等非 HTTP 协议;
  • 大规模 HTTP 或 HTTPS 连接的入口转发;
  • 对吞吐量和转发性能要求较高的服务。

其基本结构如下:
#mermaid-svg-TzKpNP6AN99kcCLl{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-TzKpNP6AN99kcCLl .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-TzKpNP6AN99kcCLl .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-TzKpNP6AN99kcCLl .error-icon{fill:#552222;}#mermaid-svg-TzKpNP6AN99kcCLl .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-TzKpNP6AN99kcCLl .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-TzKpNP6AN99kcCLl .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-TzKpNP6AN99kcCLl .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-TzKpNP6AN99kcCLl .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-TzKpNP6AN99kcCLl .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-TzKpNP6AN99kcCLl .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-TzKpNP6AN99kcCLl .marker{fill:#333333;stroke:#333333;}#mermaid-svg-TzKpNP6AN99kcCLl .marker.cross{stroke:#333333;}#mermaid-svg-TzKpNP6AN99kcCLl svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-TzKpNP6AN99kcCLl p{margin:0;}#mermaid-svg-TzKpNP6AN99kcCLl .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-TzKpNP6AN99kcCLl .cluster-label text{fill:#333;}#mermaid-svg-TzKpNP6AN99kcCLl .cluster-label span{color:#333;}#mermaid-svg-TzKpNP6AN99kcCLl .cluster-label span p{background-color:transparent;}#mermaid-svg-TzKpNP6AN99kcCLl .label text,#mermaid-svg-TzKpNP6AN99kcCLl span{fill:#333;color:#333;}#mermaid-svg-TzKpNP6AN99kcCLl .node rect,#mermaid-svg-TzKpNP6AN99kcCLl .node circle,#mermaid-svg-TzKpNP6AN99kcCLl .node ellipse,#mermaid-svg-TzKpNP6AN99kcCLl .node polygon,#mermaid-svg-TzKpNP6AN99kcCLl .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-TzKpNP6AN99kcCLl .rough-node .label text,#mermaid-svg-TzKpNP6AN99kcCLl .node .label text,#mermaid-svg-TzKpNP6AN99kcCLl .image-shape .label,#mermaid-svg-TzKpNP6AN99kcCLl .icon-shape .label{text-anchor:middle;}#mermaid-svg-TzKpNP6AN99kcCLl .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-TzKpNP6AN99kcCLl .rough-node .label,#mermaid-svg-TzKpNP6AN99kcCLl .node .label,#mermaid-svg-TzKpNP6AN99kcCLl .image-shape .label,#mermaid-svg-TzKpNP6AN99kcCLl .icon-shape .label{text-align:center;}#mermaid-svg-TzKpNP6AN99kcCLl .node.clickable{cursor:pointer;}#mermaid-svg-TzKpNP6AN99kcCLl .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-TzKpNP6AN99kcCLl .arrowheadPath{fill:#333333;}#mermaid-svg-TzKpNP6AN99kcCLl .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-TzKpNP6AN99kcCLl .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-TzKpNP6AN99kcCLl .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TzKpNP6AN99kcCLl .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-TzKpNP6AN99kcCLl .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TzKpNP6AN99kcCLl .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-TzKpNP6AN99kcCLl .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-TzKpNP6AN99kcCLl .cluster text{fill:#333;}#mermaid-svg-TzKpNP6AN99kcCLl .cluster span{color:#333;}#mermaid-svg-TzKpNP6AN99kcCLl div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-TzKpNP6AN99kcCLl .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-TzKpNP6AN99kcCLl rect.text{fill:none;stroke-width:0;}#mermaid-svg-TzKpNP6AN99kcCLl .icon-shape,#mermaid-svg-TzKpNP6AN99kcCLl .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TzKpNP6AN99kcCLl .icon-shape p,#mermaid-svg-TzKpNP6AN99kcCLl .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-TzKpNP6AN99kcCLl .icon-shape .label rect,#mermaid-svg-TzKpNP6AN99kcCLl .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TzKpNP6AN99kcCLl .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-TzKpNP6AN99kcCLl .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-TzKpNP6AN99kcCLl :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 客户端
四层负载均衡器

VIP:Port
后端服务器 1
后端服务器 2
后端服务器 3

例如,客户端访问:

text 复制代码
192.168.10.100:3306

负载均衡器可以根据连接调度算法,将该 TCP 连接转发到:

text 复制代码
192.168.10.11:3306
192.168.10.12:3306
192.168.10.13:3306

四层负载均衡关心的是"这个连接应该交给哪台服务器",通常不会根据 /user/list/order/create 这样的 HTTP 路径分流。

不过,"四层负载均衡"并不等于"永远不会建立代理连接"。例如:

  • LVS 可以在内核中进行数据包调度;
  • HAProxy 的 TCP 模式通常会在代理两侧分别维护连接;
    -云厂商提供的四层负载均衡,其内部实现也可能不同。

因此,四层描述的是调度时所依据的协议层次,并不唯一决定底层实现方式。

1.2 什么是七层负载均衡

七层负载均衡工作在应用层,能够理解 HTTP、HTTPS 等应用层协议。

它不仅可以根据 IP 和端口分配请求,还可以读取以下内容:

  • 域名;
  • URI;
  • HTTP 方法;
  • Query 参数;
  • Cookie;
  • 请求头;
  • Content-Type;
  • 用户身份或租户标识;
  • 请求来源;
  • 灰度标记。

例如:

text 复制代码
/api/user/**   -> 用户服务
/api/order/**  -> 订单服务
/static/**     -> 静态资源服务器

其基本结构如下:
#mermaid-svg-Hfqo5JdBgdiZ1skH{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Hfqo5JdBgdiZ1skH .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Hfqo5JdBgdiZ1skH .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Hfqo5JdBgdiZ1skH .error-icon{fill:#552222;}#mermaid-svg-Hfqo5JdBgdiZ1skH .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Hfqo5JdBgdiZ1skH .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Hfqo5JdBgdiZ1skH .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Hfqo5JdBgdiZ1skH .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Hfqo5JdBgdiZ1skH .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Hfqo5JdBgdiZ1skH .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Hfqo5JdBgdiZ1skH .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Hfqo5JdBgdiZ1skH .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Hfqo5JdBgdiZ1skH .marker.cross{stroke:#333333;}#mermaid-svg-Hfqo5JdBgdiZ1skH svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Hfqo5JdBgdiZ1skH p{margin:0;}#mermaid-svg-Hfqo5JdBgdiZ1skH .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Hfqo5JdBgdiZ1skH .cluster-label text{fill:#333;}#mermaid-svg-Hfqo5JdBgdiZ1skH .cluster-label span{color:#333;}#mermaid-svg-Hfqo5JdBgdiZ1skH .cluster-label span p{background-color:transparent;}#mermaid-svg-Hfqo5JdBgdiZ1skH .label text,#mermaid-svg-Hfqo5JdBgdiZ1skH span{fill:#333;color:#333;}#mermaid-svg-Hfqo5JdBgdiZ1skH .node rect,#mermaid-svg-Hfqo5JdBgdiZ1skH .node circle,#mermaid-svg-Hfqo5JdBgdiZ1skH .node ellipse,#mermaid-svg-Hfqo5JdBgdiZ1skH .node polygon,#mermaid-svg-Hfqo5JdBgdiZ1skH .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Hfqo5JdBgdiZ1skH .rough-node .label text,#mermaid-svg-Hfqo5JdBgdiZ1skH .node .label text,#mermaid-svg-Hfqo5JdBgdiZ1skH .image-shape .label,#mermaid-svg-Hfqo5JdBgdiZ1skH .icon-shape .label{text-anchor:middle;}#mermaid-svg-Hfqo5JdBgdiZ1skH .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Hfqo5JdBgdiZ1skH .rough-node .label,#mermaid-svg-Hfqo5JdBgdiZ1skH .node .label,#mermaid-svg-Hfqo5JdBgdiZ1skH .image-shape .label,#mermaid-svg-Hfqo5JdBgdiZ1skH .icon-shape .label{text-align:center;}#mermaid-svg-Hfqo5JdBgdiZ1skH .node.clickable{cursor:pointer;}#mermaid-svg-Hfqo5JdBgdiZ1skH .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Hfqo5JdBgdiZ1skH .arrowheadPath{fill:#333333;}#mermaid-svg-Hfqo5JdBgdiZ1skH .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Hfqo5JdBgdiZ1skH .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Hfqo5JdBgdiZ1skH .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Hfqo5JdBgdiZ1skH .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Hfqo5JdBgdiZ1skH .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Hfqo5JdBgdiZ1skH .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Hfqo5JdBgdiZ1skH .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Hfqo5JdBgdiZ1skH .cluster text{fill:#333;}#mermaid-svg-Hfqo5JdBgdiZ1skH .cluster span{color:#333;}#mermaid-svg-Hfqo5JdBgdiZ1skH div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Hfqo5JdBgdiZ1skH .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Hfqo5JdBgdiZ1skH rect.text{fill:none;stroke-width:0;}#mermaid-svg-Hfqo5JdBgdiZ1skH .icon-shape,#mermaid-svg-Hfqo5JdBgdiZ1skH .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Hfqo5JdBgdiZ1skH .icon-shape p,#mermaid-svg-Hfqo5JdBgdiZ1skH .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Hfqo5JdBgdiZ1skH .icon-shape .label rect,#mermaid-svg-Hfqo5JdBgdiZ1skH .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Hfqo5JdBgdiZ1skH .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Hfqo5JdBgdiZ1skH .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Hfqo5JdBgdiZ1skH :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} /api/user/**
/api/order/**
/static/**
客户端
七层负载均衡器
用户服务集群
订单服务集群
静态资源集群

七层负载均衡常见能力包括:

  • 按域名转发;
  • 按 URI 转发;
  • 按 Cookie 或请求头进行灰度发布;
  • TLS 终止;
  • HTTP 重定向;
  • 请求头添加、删除或重写;
  • 响应压缩;
  • 缓存;
  • 限流;
  • Web 应用防火墙;
  • HTTP 访问日志;
  • 更精确的应用层健康检查。

因为七层负载均衡需要解析应用层协议,所以能够实现更加灵活的路由策略,但也会消耗更多 CPU 和内存。

1.3 四层与七层负载均衡对比

对比项 四层负载均衡 七层负载均衡
工作层次 传输层 应用层
主要依据 IP、端口、TCP、UDP 域名、URI、请求头、Cookie 等
协议理解能力 不理解具体 HTTP 业务语义 能够解析 HTTP 等应用协议
转发粒度 连接级 请求级或连接级
性能开销 通常较低 通常较高
路由能力 相对简单 非常灵活
TLS 处理 可透传,也可能终止 经常在负载均衡器终止 TLS
健康检查 TCP 端口、连接状态 HTTP 状态码、响应内容等
常见实现 LVS、云厂商网络负载均衡 Nginx、HAProxy、API Gateway
典型场景 数据库、缓存、长连接、高吞吐入口 Web、微服务、灰度发布、内容路由

1.4 HTTPS 场景下的区别

HTTPS 流量可以采用两种主要方式。

TLS 透传

负载均衡器不解密 HTTPS 流量,而是根据 TCP 连接进行转发。

text 复制代码
客户端 --HTTPS--> 四层负载均衡器 --HTTPS--> 后端服务器

优点:

  • 负载均衡器不承担加解密开销;
  • 数据一直保持加密;
  • 后端可以直接获得和管理证书。

缺点:

  • 负载均衡器通常无法读取 URI、Cookie 和大部分请求头;
  • 无法方便地实现基于 HTTP 内容的路由;
  • 每台后端都需要管理证书。
TLS 终止

负载均衡器负责与客户端建立 HTTPS 连接,解密后再转发请求。

text 复制代码
客户端 --HTTPS--> 七层负载均衡器 --HTTP或HTTPS--> 后端服务器

优点:

  • 统一管理证书;
  • 可以读取 HTTP 请求内容;
  • 可以实现路径路由、灰度发布、限流和安全检查;
  • 减少后端服务器的 TLS 计算压力。

缺点:

  • 负载均衡器需要承担加解密开销;
  • 如果后端使用 HTTP,负载均衡器到后端之间是明文传输;
  • 负载均衡器上会出现明文数据,需要加强安全控制。

安全要求较高时,可以采用"前端终止 TLS,后端重新加密"的方式:

text 复制代码
客户端 --HTTPS--> 负载均衡器 --HTTPS--> 后端服务器

1.5 如何选择四层或七层负载均衡

适合选择四层负载均衡的情况:

  • 需要代理 TCP、UDP 等非 HTTP 协议;
  • 对吞吐量和连接处理能力要求很高;
  • 不需要根据 URI、Cookie 等内容路由;
  • 希望尽量减少应用层解析开销;
  • 需要处理数据库、缓存或大量长连接。

适合选择七层负载均衡的情况:

  • 需要按域名、URI 或请求头转发;
  • 需要统一管理 HTTPS 证书;
  • 需要灰度发布、A/B 测试;
  • 需要记录 HTTP 访问日志;
  • 需要限流、鉴权、缓存或安全防护;
  • 需要进行应用层健康检查。

在大型系统中,四层和七层经常组合使用:
#mermaid-svg-uUMYbxx8UELZO8Be{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-uUMYbxx8UELZO8Be .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-uUMYbxx8UELZO8Be .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-uUMYbxx8UELZO8Be .error-icon{fill:#552222;}#mermaid-svg-uUMYbxx8UELZO8Be .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-uUMYbxx8UELZO8Be .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-uUMYbxx8UELZO8Be .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-uUMYbxx8UELZO8Be .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-uUMYbxx8UELZO8Be .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-uUMYbxx8UELZO8Be .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-uUMYbxx8UELZO8Be .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-uUMYbxx8UELZO8Be .marker{fill:#333333;stroke:#333333;}#mermaid-svg-uUMYbxx8UELZO8Be .marker.cross{stroke:#333333;}#mermaid-svg-uUMYbxx8UELZO8Be svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-uUMYbxx8UELZO8Be p{margin:0;}#mermaid-svg-uUMYbxx8UELZO8Be .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-uUMYbxx8UELZO8Be .cluster-label text{fill:#333;}#mermaid-svg-uUMYbxx8UELZO8Be .cluster-label span{color:#333;}#mermaid-svg-uUMYbxx8UELZO8Be .cluster-label span p{background-color:transparent;}#mermaid-svg-uUMYbxx8UELZO8Be .label text,#mermaid-svg-uUMYbxx8UELZO8Be span{fill:#333;color:#333;}#mermaid-svg-uUMYbxx8UELZO8Be .node rect,#mermaid-svg-uUMYbxx8UELZO8Be .node circle,#mermaid-svg-uUMYbxx8UELZO8Be .node ellipse,#mermaid-svg-uUMYbxx8UELZO8Be .node polygon,#mermaid-svg-uUMYbxx8UELZO8Be .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-uUMYbxx8UELZO8Be .rough-node .label text,#mermaid-svg-uUMYbxx8UELZO8Be .node .label text,#mermaid-svg-uUMYbxx8UELZO8Be .image-shape .label,#mermaid-svg-uUMYbxx8UELZO8Be .icon-shape .label{text-anchor:middle;}#mermaid-svg-uUMYbxx8UELZO8Be .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-uUMYbxx8UELZO8Be .rough-node .label,#mermaid-svg-uUMYbxx8UELZO8Be .node .label,#mermaid-svg-uUMYbxx8UELZO8Be .image-shape .label,#mermaid-svg-uUMYbxx8UELZO8Be .icon-shape .label{text-align:center;}#mermaid-svg-uUMYbxx8UELZO8Be .node.clickable{cursor:pointer;}#mermaid-svg-uUMYbxx8UELZO8Be .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-uUMYbxx8UELZO8Be .arrowheadPath{fill:#333333;}#mermaid-svg-uUMYbxx8UELZO8Be .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-uUMYbxx8UELZO8Be .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-uUMYbxx8UELZO8Be .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uUMYbxx8UELZO8Be .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-uUMYbxx8UELZO8Be .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uUMYbxx8UELZO8Be .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-uUMYbxx8UELZO8Be .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-uUMYbxx8UELZO8Be .cluster text{fill:#333;}#mermaid-svg-uUMYbxx8UELZO8Be .cluster span{color:#333;}#mermaid-svg-uUMYbxx8UELZO8Be div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-uUMYbxx8UELZO8Be .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-uUMYbxx8UELZO8Be rect.text{fill:none;stroke-width:0;}#mermaid-svg-uUMYbxx8UELZO8Be .icon-shape,#mermaid-svg-uUMYbxx8UELZO8Be .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uUMYbxx8UELZO8Be .icon-shape p,#mermaid-svg-uUMYbxx8UELZO8Be .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-uUMYbxx8UELZO8Be .icon-shape .label rect,#mermaid-svg-uUMYbxx8UELZO8Be .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uUMYbxx8UELZO8Be .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-uUMYbxx8UELZO8Be .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-uUMYbxx8UELZO8Be :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 客户端
四层负载均衡集群
七层负载均衡器 1
七层负载均衡器 2
应用服务集群

四层负责高性能连接入口,七层负责业务路由和应用层治理。


2. 负载均衡算法与调度策略

负载均衡的核心问题是:

当前请求或连接应该分配给哪一台后端服务器?

不同算法适用于不同的业务流量模型。没有一种算法适合所有系统,选择时需要综合考虑请求耗时、服务器配置、连接长度、会话状态和扩缩容频率。

2.1 轮询算法

轮询算法按照固定顺序将请求依次分配给后端服务器。

假设有三台服务器:

text 复制代码
请求 1 -> 服务器 A
请求 2 -> 服务器 B
请求 3 -> 服务器 C
请求 4 -> 服务器 A

优点:

  • 实现简单;
  • 分配结果相对均匀;
  • 不需要维护复杂的性能指标;
  • 适合服务器配置和请求成本相近的场景。

缺点:

  • 不考虑服务器当前负载;
  • 不考虑请求执行时间;
  • 如果某些请求特别耗时,仍可能造成节点负载不均。

2.2 加权轮询

如果服务器配置不同,可以给服务器设置不同权重。

例如:

text 复制代码
服务器 A:weight=5
服务器 B:weight=3
服务器 C:weight=2

长期来看,三台服务器获得的流量比例大约为:

text 复制代码
5 : 3 : 2

加权轮询适合以下场景:

  • 新旧服务器配置不同;
  • 部分服务器 CPU 或内存更强;
  • 灰度发布时只希望新版本接收少量流量;
  • 需要逐步放量。

需要注意,权重表示的是调度倾向,不代表精确的瞬时流量比例。短时间内的请求数量、长连接和请求耗时仍可能造成偏差。

2.3 随机算法

随机算法从可用后端中随机选择一个节点。

当请求量足够大时,流量通常会趋于均匀,但在短时间窗口内可能出现明显波动。

随机算法的优点是实现简单、状态少,适合后端数量较多且节点能力接近的场景。

一种常见改进是"随机选择两个节点,再选择其中负载较低的节点",也叫 Power of Two Choices。它只需要比较少量节点,就能获得比纯随机更好的负载效果。

2.4 最少连接算法

最少连接算法将新连接分配给当前活动连接数最少的服务器。

它适合:

  • WebSocket;
  • 数据库连接;
  • TCP 长连接;
  • 请求持续时间差异较大的业务;
  • 文件上传和下载。

例如:

text 复制代码
服务器 A:100 个活动连接
服务器 B:40 个活动连接
服务器 C:60 个活动连接

新连接优先分配给服务器 B。

它比轮询更能反映服务器当前繁忙程度,但"连接数少"并不一定等于"负载低"。一个连接可能只是空闲等待,也可能正在执行高 CPU 计算。

2.5 加权最少连接

加权最少连接同时考虑:

  • 当前活动连接数;
  • 节点权重;
  • 节点处理能力。

一种便于理解的近似思路是计算:

text 复制代码
负载得分 = 当前活动连接数 / 权重

负载均衡器优先选择得分较低的节点。

实际产品的具体计算方式可能有所不同,但核心思想都是避免仅根据连接数量做出判断。

2.6 最短响应时间

最短响应时间算法根据节点的历史响应时间、连接数或实时延迟选择服务器。

优点:

  • 能够感知节点性能变化;
  • 请求更倾向于发送到响应更快的节点;
  • 适合响应时间波动较大的服务。

缺点:

  • 需要收集和维护实时指标;
  • 短时间抖动可能导致流量快速迁移;
  • 如果没有平滑机制,可能出现节点之间反复切换。

2.7 IP Hash

IP Hash 根据客户端 IP 计算哈希值,并将请求映射到固定服务器。

text 复制代码
serverIndex = hash(clientIp) % serverCount

优点:

  • 同一个客户端通常会访问同一台服务器;
  • 可以在一定程度上实现会话保持。

缺点:

  • 大量用户共享同一个 NAT 出口时,流量可能集中到少数节点;
  • 移动网络中的客户端 IP 可能变化;
  • 增加或删除服务器时,大量映射关系可能改变;
  • 不能替代真正的分布式 Session 方案。

2.8 普通哈希与一致性哈希

除了客户端 IP,还可以使用以下字段计算哈希:

  • 用户 ID;
  • 租户 ID;
  • URI;
  • Cookie;
  • 缓存 Key;
  • 请求头中的业务标识。

普通取模哈希存在一个明显问题:

text 复制代码
serverIndex = hash(key) % serverCount

当服务器数量变化时,取模结果会大面积改变,导致大量 Key 被重新映射。

一致性哈希将服务器和业务 Key 映射到一个哈希环上。节点增加或删除时,通常只有相邻区域的一部分 Key 需要迁移。

一致性哈希适合:

  • 分布式缓存;
  • 分片存储;
  • 同一用户请求需要稳定落到同一处理节点;
  • 节点经常扩容或缩容的场景。

一致性哈希并不天然保证绝对均匀。生产环境通常还需要虚拟节点、权重和热点治理机制。

2.9 常见算法对比

算法 是否感知负载 是否支持权重 会话稳定性 适用场景
轮询 同配置服务器、短请求
加权轮询 部分 服务器配置不同、灰度放量
随机 可选 大规模同质节点
最少连接 可选 长连接、请求耗时差异较大
最短响应时间 可选 延迟敏感业务
IP Hash 通常有限 较高 简单会话保持
一致性哈希 可结合权重 缓存、分片、稳定路由

2.10 健康检查策略

调度算法只能决定"如何分配",健康检查负责决定"哪些节点可以参与分配"。

主动健康检查

负载均衡器定期主动探测后端,例如:

text 复制代码
TCP 连接检查
HTTP GET /health
HTTP GET /health/ready
数据库协议检查
自定义请求与响应检查

健康检查最好区分:

  • liveness:进程是否存活;
  • readiness:节点是否已经准备好接收流量;
  • startup:应用是否仍处于启动阶段。

生产环境通常应该使用 readiness 结果决定是否接收业务流量。一个 Java 进程还活着,并不表示数据库连接池、缓存、线程池和关键依赖都正常。

被动健康检查

被动健康检查通过真实请求判断节点状态,例如统计:

  • 连接失败;
  • 连接超时;
  • 读取超时;
  • HTTP 502、503、504;
  • 连续请求失败次数。

主动检查发现故障更稳定,被动检查能够感知真实业务错误。两者结合通常效果更好。

防抖参数

健康检查不应因为一次偶发失败就立即摘除节点,常见参数包括:

  • interval:检查间隔;
  • timeout:单次检查超时;
  • fall:连续失败多少次后判定故障;
  • rise:连续成功多少次后恢复;
  • slow start:节点恢复后逐步增加流量。

例如:

text 复制代码
每 2 秒检查一次
连续失败 3 次后摘除
连续成功 2 次后恢复

这样可以避免网络瞬时抖动造成频繁上下线。

2.11 会话保持与无状态设计

如果用户登录状态保存在某台应用服务器的本地内存中,那么下一次请求被分配到另一台服务器时,用户可能会变成未登录状态。

常见解决方案有:

  1. 使用 IP Hash;
  2. 使用负载均衡器生成的粘性 Cookie;
  3. 将 Session 统一存储到 Redis;
  4. 使用 JWT 等无状态身份凭证;
  5. 将业务设计为无状态服务。

通常更推荐将应用节点设计成无状态节点。因为粘性会话会带来以下问题:

  • 某台服务器可能聚集大量用户;
  • 节点故障后会话仍然丢失;
  • 扩容后新节点可能分不到足够流量;
  • 发布、迁移和故障恢复更加困难。

2.12 超时、重试与请求放大

负载均衡器通常需要配置:

  • 连接超时;
  • 请求发送超时;
  • 响应读取超时;
  • 空闲连接超时;
  • 总请求超时;
  • 重试次数;
  • 最大连接数;
  • 排队长度。

超时设置过长会让故障请求长期占用连接、线程和内存;设置过短则会误伤正常慢请求。

重试也不是越多越好。如果后端已经过载,负载均衡器自动重试可能进一步放大流量:

text 复制代码
1000 个原始请求 × 3 次重试 = 最多 3000 次后端尝试

对于支付、下单、扣款等非幂等操作,随意重试还可能造成重复执行。安全的做法包括:

  • 优先只重试幂等请求;
  • 为业务请求设计幂等键;
  • 限制重试次数;
  • 使用指数退避和随机抖动;
  • 设置完整的超时预算;
  • 避免每一层代理都独立重试;
  • 配合限流、熔断和降级。

2.13 容量规划与监控指标

可以使用 Little's Law 粗略理解并发量:

text 复制代码
平均并发数 ≈ 每秒请求数 × 平均响应时间

例如:

text 复制代码
请求速率:2000 RPS
平均响应时间:0.2 秒
平均并发数约为:2000 × 0.2 = 400

负载均衡系统应重点监控:

  • 每秒请求数或新建连接数;
  • 当前活动连接数;
  • 连接建立时间;
  • 后端响应时间;
  • P50、P95、P99 延迟;
  • 2xx、4xx、5xx 比例;
  • 超时次数;
  • 重试次数;
  • 健康节点数量;
  • 节点上下线频率;
  • 队列长度;
  • 网络带宽;
  • 丢包率和重传率;
  • CPU、内存和文件描述符使用量。

容量规划不能只看平均值,应根据高峰流量、故障冗余和发布期间的容量变化进行压测。


3. LVS

3.1 LVS 是什么

LVS 是 Linux Virtual Server 的缩写。其核心能力由 Linux 内核中的 IPVS 提供,可以在 Linux 内核层面对 TCP、UDP 等流量进行高性能调度。

常见组件包括:

  • IPVS:Linux 内核中的虚拟服务器调度模块;
  • ipvsadm:管理 IPVS 规则的用户空间工具;
  • Director:负载均衡调度节点;
  • Real Server:真正处理请求的后端节点;
  • VIP:客户端访问的虚拟 IP;
  • RIP:Real Server 的真实 IP;
  • DIP:Director 与 Real Server 通信所使用的 IP。

其结构如下:
#mermaid-svg-LWDTnKUwXyPpFL65{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-LWDTnKUwXyPpFL65 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-LWDTnKUwXyPpFL65 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-LWDTnKUwXyPpFL65 .error-icon{fill:#552222;}#mermaid-svg-LWDTnKUwXyPpFL65 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-LWDTnKUwXyPpFL65 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-LWDTnKUwXyPpFL65 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-LWDTnKUwXyPpFL65 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-LWDTnKUwXyPpFL65 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-LWDTnKUwXyPpFL65 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-LWDTnKUwXyPpFL65 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-LWDTnKUwXyPpFL65 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-LWDTnKUwXyPpFL65 .marker.cross{stroke:#333333;}#mermaid-svg-LWDTnKUwXyPpFL65 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-LWDTnKUwXyPpFL65 p{margin:0;}#mermaid-svg-LWDTnKUwXyPpFL65 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-LWDTnKUwXyPpFL65 .cluster-label text{fill:#333;}#mermaid-svg-LWDTnKUwXyPpFL65 .cluster-label span{color:#333;}#mermaid-svg-LWDTnKUwXyPpFL65 .cluster-label span p{background-color:transparent;}#mermaid-svg-LWDTnKUwXyPpFL65 .label text,#mermaid-svg-LWDTnKUwXyPpFL65 span{fill:#333;color:#333;}#mermaid-svg-LWDTnKUwXyPpFL65 .node rect,#mermaid-svg-LWDTnKUwXyPpFL65 .node circle,#mermaid-svg-LWDTnKUwXyPpFL65 .node ellipse,#mermaid-svg-LWDTnKUwXyPpFL65 .node polygon,#mermaid-svg-LWDTnKUwXyPpFL65 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-LWDTnKUwXyPpFL65 .rough-node .label text,#mermaid-svg-LWDTnKUwXyPpFL65 .node .label text,#mermaid-svg-LWDTnKUwXyPpFL65 .image-shape .label,#mermaid-svg-LWDTnKUwXyPpFL65 .icon-shape .label{text-anchor:middle;}#mermaid-svg-LWDTnKUwXyPpFL65 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-LWDTnKUwXyPpFL65 .rough-node .label,#mermaid-svg-LWDTnKUwXyPpFL65 .node .label,#mermaid-svg-LWDTnKUwXyPpFL65 .image-shape .label,#mermaid-svg-LWDTnKUwXyPpFL65 .icon-shape .label{text-align:center;}#mermaid-svg-LWDTnKUwXyPpFL65 .node.clickable{cursor:pointer;}#mermaid-svg-LWDTnKUwXyPpFL65 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-LWDTnKUwXyPpFL65 .arrowheadPath{fill:#333333;}#mermaid-svg-LWDTnKUwXyPpFL65 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-LWDTnKUwXyPpFL65 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-LWDTnKUwXyPpFL65 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LWDTnKUwXyPpFL65 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-LWDTnKUwXyPpFL65 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LWDTnKUwXyPpFL65 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-LWDTnKUwXyPpFL65 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-LWDTnKUwXyPpFL65 .cluster text{fill:#333;}#mermaid-svg-LWDTnKUwXyPpFL65 .cluster span{color:#333;}#mermaid-svg-LWDTnKUwXyPpFL65 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-LWDTnKUwXyPpFL65 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-LWDTnKUwXyPpFL65 rect.text{fill:none;stroke-width:0;}#mermaid-svg-LWDTnKUwXyPpFL65 .icon-shape,#mermaid-svg-LWDTnKUwXyPpFL65 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LWDTnKUwXyPpFL65 .icon-shape p,#mermaid-svg-LWDTnKUwXyPpFL65 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-LWDTnKUwXyPpFL65 .icon-shape .label rect,#mermaid-svg-LWDTnKUwXyPpFL65 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LWDTnKUwXyPpFL65 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-LWDTnKUwXyPpFL65 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-LWDTnKUwXyPpFL65 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 客户端
VIP
LVS Director
Real Server 1
Real Server 2
Real Server 3

LVS 的优势是:

  • 数据包调度主要在内核中完成;
  • 性能较高;
  • 适合大并发连接;
  • 支持多种调度算法;
  • 支持 NAT、DR、TUN 等转发模式;
  • 可以与 Keepalived 组合实现高可用和健康检查。

它的不足是:

  • 不理解 HTTP URI、Cookie 等应用层内容;
  • 配置和网络拓扑要求较高;
  • 日志和应用层可观测性不如七层代理;
  • DR、TUN 模式需要额外的网络配置。

3.2 LVS-NAT 模式

NAT 模式中,客户端请求先到达 Director。Director 修改数据包的目标地址,将其发送给 Real Server。

响应数据也需要经过 Director 返回客户端。
Real Server LVS Director 客户端 Real Server LVS Director 客户端 #mermaid-svg-PafGSpsC4xp6GaA6{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-PafGSpsC4xp6GaA6 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-PafGSpsC4xp6GaA6 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-PafGSpsC4xp6GaA6 .error-icon{fill:#552222;}#mermaid-svg-PafGSpsC4xp6GaA6 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-PafGSpsC4xp6GaA6 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-PafGSpsC4xp6GaA6 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-PafGSpsC4xp6GaA6 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-PafGSpsC4xp6GaA6 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-PafGSpsC4xp6GaA6 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-PafGSpsC4xp6GaA6 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-PafGSpsC4xp6GaA6 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-PafGSpsC4xp6GaA6 .marker.cross{stroke:#333333;}#mermaid-svg-PafGSpsC4xp6GaA6 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-PafGSpsC4xp6GaA6 p{margin:0;}#mermaid-svg-PafGSpsC4xp6GaA6 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-PafGSpsC4xp6GaA6 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-PafGSpsC4xp6GaA6 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-PafGSpsC4xp6GaA6 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-PafGSpsC4xp6GaA6 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-PafGSpsC4xp6GaA6 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-PafGSpsC4xp6GaA6 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-PafGSpsC4xp6GaA6 .sequenceNumber{fill:white;}#mermaid-svg-PafGSpsC4xp6GaA6 #sequencenumber{fill:#333;}#mermaid-svg-PafGSpsC4xp6GaA6 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-PafGSpsC4xp6GaA6 .messageText{fill:#333;stroke:none;}#mermaid-svg-PafGSpsC4xp6GaA6 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-PafGSpsC4xp6GaA6 .labelText,#mermaid-svg-PafGSpsC4xp6GaA6 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-PafGSpsC4xp6GaA6 .loopText,#mermaid-svg-PafGSpsC4xp6GaA6 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-PafGSpsC4xp6GaA6 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-PafGSpsC4xp6GaA6 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-PafGSpsC4xp6GaA6 .noteText,#mermaid-svg-PafGSpsC4xp6GaA6 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-PafGSpsC4xp6GaA6 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-PafGSpsC4xp6GaA6 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-PafGSpsC4xp6GaA6 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-PafGSpsC4xp6GaA6 .actorPopupMenu{position:absolute;}#mermaid-svg-PafGSpsC4xp6GaA6 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-PafGSpsC4xp6GaA6 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-PafGSpsC4xp6GaA6 .actor-man circle,#mermaid-svg-PafGSpsC4xp6GaA6 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-PafGSpsC4xp6GaA6 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 请求 VIP 修改目标地址后转发 响应返回 Director 修改源地址后返回

特点:

  • 请求和响应都经过 Director;
  • Real Server 可以使用私有地址;
  • Real Server 通常需要将 Director 设置为返回路径上的网关;
  • 配置相对容易理解;
  • Director 容易成为出口带宽瓶颈。

适合:

  • 中小规模集群;
  • 后端服务器没有直接对外路由;
  • 对网络拓扑改动有控制权的环境。

3.3 LVS-DR 模式

DR 是 Direct Routing,即直接路由。

客户端请求到达 Director 后,Director 主要修改二层目标 MAC 地址,将数据包发送到选定的 Real Server。数据包中的 VIP 通常保持不变。

Real Server 处理请求后直接响应客户端,返回流量不再经过 Director。
Real Server LVS Director 客户端 Real Server LVS Director 客户端 #mermaid-svg-isIn6Ta27aQjw5JT{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-isIn6Ta27aQjw5JT .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-isIn6Ta27aQjw5JT .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-isIn6Ta27aQjw5JT .error-icon{fill:#552222;}#mermaid-svg-isIn6Ta27aQjw5JT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-isIn6Ta27aQjw5JT .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-isIn6Ta27aQjw5JT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-isIn6Ta27aQjw5JT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-isIn6Ta27aQjw5JT .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-isIn6Ta27aQjw5JT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-isIn6Ta27aQjw5JT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-isIn6Ta27aQjw5JT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-isIn6Ta27aQjw5JT .marker.cross{stroke:#333333;}#mermaid-svg-isIn6Ta27aQjw5JT svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-isIn6Ta27aQjw5JT p{margin:0;}#mermaid-svg-isIn6Ta27aQjw5JT .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-isIn6Ta27aQjw5JT text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-isIn6Ta27aQjw5JT .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-isIn6Ta27aQjw5JT .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-isIn6Ta27aQjw5JT .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-isIn6Ta27aQjw5JT .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-isIn6Ta27aQjw5JT #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-isIn6Ta27aQjw5JT .sequenceNumber{fill:white;}#mermaid-svg-isIn6Ta27aQjw5JT #sequencenumber{fill:#333;}#mermaid-svg-isIn6Ta27aQjw5JT #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-isIn6Ta27aQjw5JT .messageText{fill:#333;stroke:none;}#mermaid-svg-isIn6Ta27aQjw5JT .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-isIn6Ta27aQjw5JT .labelText,#mermaid-svg-isIn6Ta27aQjw5JT .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-isIn6Ta27aQjw5JT .loopText,#mermaid-svg-isIn6Ta27aQjw5JT .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-isIn6Ta27aQjw5JT .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-isIn6Ta27aQjw5JT .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-isIn6Ta27aQjw5JT .noteText,#mermaid-svg-isIn6Ta27aQjw5JT .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-isIn6Ta27aQjw5JT .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-isIn6Ta27aQjw5JT .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-isIn6Ta27aQjw5JT .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-isIn6Ta27aQjw5JT .actorPopupMenu{position:absolute;}#mermaid-svg-isIn6Ta27aQjw5JT .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-isIn6Ta27aQjw5JT .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-isIn6Ta27aQjw5JT .actor-man circle,#mermaid-svg-isIn6Ta27aQjw5JT line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-isIn6Ta27aQjw5JT :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 请求 VIP 修改目标 MAC 后转发 直接返回响应

特点:

  • 入站请求经过 Director;
  • 出站响应由 Real Server 直接返回;
  • Director 的带宽压力较小;
  • 性能和扩展能力较强;
  • Director 与 Real Server 通常需要处于同一二层网络;
  • Real Server 需要配置 VIP;
  • 需要处理 Real Server 对 VIP 的 ARP 响应问题。

DR 模式特别适合响应流量明显大于请求流量的场景,例如图片、文件和视频下载。

3.4 LVS-TUN 模式

TUN 模式通过 IP 隧道将请求封装后发送到 Real Server。

Real Server 解封装并处理请求,然后直接向客户端返回响应。

特点:

  • Real Server 可以和 Director 不在同一个二层网络;
  • 可以跨机房或跨网段;
  • 响应流量不经过 Director;
  • Director 和 Real Server 需要支持相应的隧道协议;
  • 需要处理 MTU、分片、防火墙和路由问题;
  • 运维复杂度高于 NAT 和 DR。

3.5 LVS 三种模式对比

对比项 NAT DR TUN
请求是否经过 Director
响应是否经过 Director
Real Server 是否可使用私网地址 可以 取决于路由设计 取决于路由设计
是否要求同一二层网络 通常不强制 通常需要 不需要
配置复杂度 较低 中等 较高
Director 出口压力 较大 较小 较小
常见场景 中小规模集群 高性能同机房集群 跨网段或跨地域调度

3.6 LVS 常见调度算法

LVS/IPVS 支持多种调度算法,常见的包括:

算法 ipvsadm 标识 说明
轮询 rr 按顺序分配连接
加权轮询 wrr 根据权重分配连接
最少连接 lc 选择活动连接较少的节点
加权最少连接 wlc 同时考虑连接数与权重
源地址哈希 sh 根据源地址进行映射
目标地址哈希 dh 根据目标地址进行映射
最短期望延迟 sed 根据连接和权重估算延迟
永不排队 nq 优先选择当前没有活动连接的节点

在大多数普通业务中,可以优先从以下算法中选择:

  • 同配置节点、短连接:rr
  • 节点配置不同:wrr
  • 长连接或耗时差异较大:wlc
  • 需要一定来源稳定性:sh

3.7 使用 ipvsadm 配置 LVS-DR

下面是一个测试环境示例:

text 复制代码
VIP:192.168.10.100
Director:192.168.10.10
Real Server 1:192.168.10.11
Real Server 2:192.168.10.12
服务端口:80

加载 IPVS 模块:

bash 复制代码
modprobe ip_vs
modprobe ip_vs_wlc

在 Director 上添加 VIP:

bash 复制代码
ip addr add 192.168.10.100/32 dev eth0

创建虚拟服务:

bash 复制代码
ipvsadm -A -t 192.168.10.100:80 -s wlc

添加 Real Server,并使用 DR 模式:

bash 复制代码
ipvsadm -a -t 192.168.10.100:80 \
  -r 192.168.10.11:80 -g -w 1

ipvsadm -a -t 192.168.10.100:80 \
  -r 192.168.10.12:80 -g -w 1

其中:

text 复制代码
-A:添加虚拟服务
-a:添加 Real Server
-t:TCP 服务
-s:调度算法
-r:Real Server 地址
-g:DR 模式
-w:权重

查看规则:

bash 复制代码
ipvsadm -Ln

查看连接、统计和速率:

bash 复制代码
ipvsadm -Ln --stats
ipvsadm -Ln --rate

在 Real Server 的回环接口上配置 VIP:

bash 复制代码
ip addr add 192.168.10.100/32 dev lo

DR 模式下还要避免 Real Server 在物理网络中抢答 VIP 的 ARP 请求。下面只是常见思路,具体参数应根据内核、网卡和网络拓扑在测试环境验证:

bash 复制代码
sysctl -w net.ipv4.conf.all.arp_ignore=1
sysctl -w net.ipv4.conf.lo.arp_ignore=1
sysctl -w net.ipv4.conf.all.arp_announce=2
sysctl -w net.ipv4.conf.lo.arp_announce=2

正式环境应将确认后的配置写入 /etc/sysctl.d/,而不是只依赖临时命令。

3.8 LVS 的生产注意事项

Director 仍可能是单点

只部署一台 LVS Director 时,后端即使有很多节点,入口仍然存在单点故障。通常需要两台 Director,并使用 Keepalived 管理 VIP 漂移。

长连接状态需要考虑同步

主备 Director 切换后,旧连接状态可能只存在于原主节点。对于大量长连接业务,需要评估 IPVS 连接同步机制,否则切换时可能造成存量连接中断。

DR 模式要重点排查 ARP

常见故障包括:

  • VIP 被 Real Server 对外响应;
  • Director 收不到客户端请求;
  • Real Server 可以收到请求但响应路径错误;
  • 交换机 ARP 缓存未及时更新;
  • 回环接口没有配置 VIP。
TUN 模式要关注 MTU

隧道封装会增加额外报文头。如果链路 MTU 没有正确设置,可能出现分片、丢包或"大包不通、小包正常"的问题。

不要把端口健康等同于业务健康

TCP 端口能够建立连接,只能证明进程正在监听,并不代表:

  • 数据库可访问;
  • 缓存可访问;
  • 线程池未耗尽;
  • 应用初始化完成;
  • 核心业务可以正常执行。

LVS 本身负责内核调度,生产环境通常使用 Keepalived 或其他控制程序维护健康节点列表。


4. Keepalived

4.1 Keepalived 是什么

Keepalived 是 Linux 环境中常见的高可用和负载均衡辅助软件,主要提供两类能力:

  1. 基于 VRRP 的高可用;
  2. 对 IPVS/LVS 后端进行健康检查和规则维护。

需要特别区分:

  • LVS/IPVS 负责实际的四层流量调度;
  • Keepalived 可以配置和维护 IPVS;
  • VRRP 负责在多台负载均衡器之间漂移 VIP;
  • Keepalived 也可以只提供 VRRP,而不使用 LVS。

4.2 VRRP 的基本原理

VRRP 是 Virtual Router Redundancy Protocol,即虚拟路由冗余协议。

多个节点共同组成一个虚拟路由器,对外提供同一个 VIP。正常情况下,由 MASTER 节点持有 VIP;MASTER 故障后,BACKUP 节点通过选举接管 VIP。
#mermaid-svg-pPQRN71DxZcdhzdH{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-pPQRN71DxZcdhzdH .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-pPQRN71DxZcdhzdH .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-pPQRN71DxZcdhzdH .error-icon{fill:#552222;}#mermaid-svg-pPQRN71DxZcdhzdH .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-pPQRN71DxZcdhzdH .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-pPQRN71DxZcdhzdH .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-pPQRN71DxZcdhzdH .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-pPQRN71DxZcdhzdH .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-pPQRN71DxZcdhzdH .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-pPQRN71DxZcdhzdH .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-pPQRN71DxZcdhzdH .marker{fill:#333333;stroke:#333333;}#mermaid-svg-pPQRN71DxZcdhzdH .marker.cross{stroke:#333333;}#mermaid-svg-pPQRN71DxZcdhzdH svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-pPQRN71DxZcdhzdH p{margin:0;}#mermaid-svg-pPQRN71DxZcdhzdH .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-pPQRN71DxZcdhzdH .cluster-label text{fill:#333;}#mermaid-svg-pPQRN71DxZcdhzdH .cluster-label span{color:#333;}#mermaid-svg-pPQRN71DxZcdhzdH .cluster-label span p{background-color:transparent;}#mermaid-svg-pPQRN71DxZcdhzdH .label text,#mermaid-svg-pPQRN71DxZcdhzdH span{fill:#333;color:#333;}#mermaid-svg-pPQRN71DxZcdhzdH .node rect,#mermaid-svg-pPQRN71DxZcdhzdH .node circle,#mermaid-svg-pPQRN71DxZcdhzdH .node ellipse,#mermaid-svg-pPQRN71DxZcdhzdH .node polygon,#mermaid-svg-pPQRN71DxZcdhzdH .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-pPQRN71DxZcdhzdH .rough-node .label text,#mermaid-svg-pPQRN71DxZcdhzdH .node .label text,#mermaid-svg-pPQRN71DxZcdhzdH .image-shape .label,#mermaid-svg-pPQRN71DxZcdhzdH .icon-shape .label{text-anchor:middle;}#mermaid-svg-pPQRN71DxZcdhzdH .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-pPQRN71DxZcdhzdH .rough-node .label,#mermaid-svg-pPQRN71DxZcdhzdH .node .label,#mermaid-svg-pPQRN71DxZcdhzdH .image-shape .label,#mermaid-svg-pPQRN71DxZcdhzdH .icon-shape .label{text-align:center;}#mermaid-svg-pPQRN71DxZcdhzdH .node.clickable{cursor:pointer;}#mermaid-svg-pPQRN71DxZcdhzdH .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-pPQRN71DxZcdhzdH .arrowheadPath{fill:#333333;}#mermaid-svg-pPQRN71DxZcdhzdH .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-pPQRN71DxZcdhzdH .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-pPQRN71DxZcdhzdH .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pPQRN71DxZcdhzdH .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-pPQRN71DxZcdhzdH .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pPQRN71DxZcdhzdH .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-pPQRN71DxZcdhzdH .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-pPQRN71DxZcdhzdH .cluster text{fill:#333;}#mermaid-svg-pPQRN71DxZcdhzdH .cluster span{color:#333;}#mermaid-svg-pPQRN71DxZcdhzdH div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-pPQRN71DxZcdhzdH .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-pPQRN71DxZcdhzdH rect.text{fill:none;stroke-width:0;}#mermaid-svg-pPQRN71DxZcdhzdH .icon-shape,#mermaid-svg-pPQRN71DxZcdhzdH .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pPQRN71DxZcdhzdH .icon-shape p,#mermaid-svg-pPQRN71DxZcdhzdH .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-pPQRN71DxZcdhzdH .icon-shape .label rect,#mermaid-svg-pPQRN71DxZcdhzdH .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pPQRN71DxZcdhzdH .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-pPQRN71DxZcdhzdH .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-pPQRN71DxZcdhzdH :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 故障切换
客户端访问 VIP

192.168.10.100
当前 MASTER
LB01

priority=120
LB02

priority=100
后端服务集群

VRRP 常见概念包括:

  • state:初始状态;
  • interface:发送 VRRP 报文的网卡;
  • virtual_router_id:虚拟路由器标识;
  • priority:节点优先级;
  • advert_int:通告间隔;
  • virtual_ipaddress:需要漂移的 VIP;
  • track_script:跟踪健康检查脚本;
  • track_interface:跟踪网络接口状态。

需要注意,配置中的 state MASTER 只是初始状态,最终由 VRRP 选举结果决定谁持有 VIP。

4.3 Keepalived 双机配置示例

假设:

text 复制代码
LB01:192.168.10.11
LB02:192.168.10.12
VIP:192.168.10.100
网卡:eth0

在两台服务器上创建健康检查脚本:

bash 复制代码
#!/usr/bin/env bash

curl --fail \
  --silent \
  --show-error \
  --max-time 1 \
  http://127.0.0.1/healthz >/dev/null

保存为:

text 复制代码
/usr/local/bin/check_nginx.sh

并设置执行权限:

bash 复制代码
chmod 750 /usr/local/bin/check_nginx.sh

生产环境应限制脚本文件和其父目录的写权限,避免低权限用户修改由 Keepalived 执行的脚本。

LB01 配置示例:

conf 复制代码
global_defs {
    router_id LB01
    enable_script_security
    script_user root
}

vrrp_script chk_nginx {
    script "/usr/local/bin/check_nginx.sh"
    interval 2
    timeout 2
    fall 3
    rise 2
    weight -30
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 120
    advert_int 1

    unicast_src_ip 192.168.10.11
    unicast_peer {
        192.168.10.12
    }

    virtual_ipaddress {
        192.168.10.100/24 dev eth0
    }

    track_script {
        chk_nginx
    }
}

LB02 配置示例:

conf 复制代码
global_defs {
    router_id LB02
    enable_script_security
    script_user root
}

vrrp_script chk_nginx {
    script "/usr/local/bin/check_nginx.sh"
    interval 2
    timeout 2
    fall 3
    rise 2
    weight -30
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1

    unicast_src_ip 192.168.10.12
    unicast_peer {
        192.168.10.11
    }

    virtual_ipaddress {
        192.168.10.100/24 dev eth0
    }

    track_script {
        chk_nginx
    }
}

这里 LB01 的正常优先级是 120。当健康检查连续失败后,权重减少 30,实际优先级变为 90,低于 LB02 的 100,因此 LB02 可以接管 VIP。

实际生产环境建议为健康检查脚本设置专用低权限用户,示例使用 root 主要是为了展示完整配置结构。

4.4 Keepalived 故障切换过程

正常状态:

text 复制代码
LB01:MASTER,持有 VIP
LB02:BACKUP,不持有 VIP

LB01 故障后:

  1. LB02 收不到 LB01 的 VRRP 通告;
  2. LB02 进入 MASTER 状态;
  3. LB02 将 VIP 添加到本机网卡;
  4. LB02 发送 Gratuitous ARP;
  5. 交换机和客户端更新 VIP 对应的 MAC;
  6. 新请求进入 LB02。

LB01 恢复后,如果没有配置禁止抢占,并且 LB01 优先级更高,LB01 可能重新成为 MASTER。

是否允许恢复后自动抢占,需要根据业务决定:

  • 允许抢占:主备角色固定,但恢复时会再次切换;
  • 禁止抢占:减少流量抖动,但主备角色可能长期反转。

4.5 Keepalived 常用检查命令

检查配置:

bash 复制代码
keepalived --config-test \
  --use-file=/etc/keepalived/keepalived.conf

查看服务状态:

bash 复制代码
systemctl status keepalived

查看日志:

bash 复制代码
journalctl -u keepalived -f

查看 VIP:

bash 复制代码
ip addr show dev eth0

查看 IPVS 规则:

bash 复制代码
ipvsadm -Ln

抓取 VRRP 报文:

bash 复制代码
tcpdump -ni eth0 proto 112

如果使用 VRRP 单播,可以进一步限制源地址:

bash 复制代码
tcpdump -ni eth0 proto 112 and host 192.168.10.12

4.6 Keepalived 常见问题

两台服务器同时成为 MASTER

这通常被称为脑裂,常见原因包括:

  • VRRP 组播或单播报文被防火墙拦截;
  • 配置了错误的网卡;
  • virtual_router_id 不一致;
  • 单播对端地址配置错误;
  • 网络发生隔离;
  • 虚拟化平台限制了 VRRP 或 Gratuitous ARP。

脑裂可能导致两台机器同时持有 VIP,出现流量随机漂移、ARP 冲突等问题。

VIP 已切换但客户端仍访问旧节点

常见原因:

  • 交换机或客户端 ARP 缓存未更新;
  • Gratuitous ARP 被网络设备过滤;
  • 云平台不允许直接漂移私有 IP;
  • VIP 没有绑定到正确网卡;
  • 安全组、路由表没有同步。

在公有云环境中,不应默认认为传统二层 VRRP 一定可用。可能需要使用云厂商提供的虚拟 IP、路由切换或负载均衡服务。

只检查进程是否存在

下面这种检查能力有限:

bash 复制代码
pidof nginx

它只能证明进程存在,无法证明请求能够被正常处理。更合理的健康检查应该访问真实 readiness 接口,并验证状态码和必要的依赖状态。

健康检查过于敏感

如果一次失败就降低优先级或切换 VIP,短暂网络抖动会导致主备频繁切换。应合理配置:

text 复制代码
interval
timeout
fall
rise
weight

5. Nginx 反向代理负载均衡

5.1 Nginx 负载均衡原理

Nginx 是常见的 Web 服务器和反向代理服务器,可以接收客户端请求,再把请求转发给上游服务。
#mermaid-svg-9LgJJYaXT06ptco5{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-9LgJJYaXT06ptco5 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-9LgJJYaXT06ptco5 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-9LgJJYaXT06ptco5 .error-icon{fill:#552222;}#mermaid-svg-9LgJJYaXT06ptco5 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-9LgJJYaXT06ptco5 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-9LgJJYaXT06ptco5 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-9LgJJYaXT06ptco5 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-9LgJJYaXT06ptco5 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-9LgJJYaXT06ptco5 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-9LgJJYaXT06ptco5 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-9LgJJYaXT06ptco5 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-9LgJJYaXT06ptco5 .marker.cross{stroke:#333333;}#mermaid-svg-9LgJJYaXT06ptco5 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-9LgJJYaXT06ptco5 p{margin:0;}#mermaid-svg-9LgJJYaXT06ptco5 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-9LgJJYaXT06ptco5 .cluster-label text{fill:#333;}#mermaid-svg-9LgJJYaXT06ptco5 .cluster-label span{color:#333;}#mermaid-svg-9LgJJYaXT06ptco5 .cluster-label span p{background-color:transparent;}#mermaid-svg-9LgJJYaXT06ptco5 .label text,#mermaid-svg-9LgJJYaXT06ptco5 span{fill:#333;color:#333;}#mermaid-svg-9LgJJYaXT06ptco5 .node rect,#mermaid-svg-9LgJJYaXT06ptco5 .node circle,#mermaid-svg-9LgJJYaXT06ptco5 .node ellipse,#mermaid-svg-9LgJJYaXT06ptco5 .node polygon,#mermaid-svg-9LgJJYaXT06ptco5 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-9LgJJYaXT06ptco5 .rough-node .label text,#mermaid-svg-9LgJJYaXT06ptco5 .node .label text,#mermaid-svg-9LgJJYaXT06ptco5 .image-shape .label,#mermaid-svg-9LgJJYaXT06ptco5 .icon-shape .label{text-anchor:middle;}#mermaid-svg-9LgJJYaXT06ptco5 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-9LgJJYaXT06ptco5 .rough-node .label,#mermaid-svg-9LgJJYaXT06ptco5 .node .label,#mermaid-svg-9LgJJYaXT06ptco5 .image-shape .label,#mermaid-svg-9LgJJYaXT06ptco5 .icon-shape .label{text-align:center;}#mermaid-svg-9LgJJYaXT06ptco5 .node.clickable{cursor:pointer;}#mermaid-svg-9LgJJYaXT06ptco5 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-9LgJJYaXT06ptco5 .arrowheadPath{fill:#333333;}#mermaid-svg-9LgJJYaXT06ptco5 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-9LgJJYaXT06ptco5 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-9LgJJYaXT06ptco5 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-9LgJJYaXT06ptco5 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-9LgJJYaXT06ptco5 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-9LgJJYaXT06ptco5 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-9LgJJYaXT06ptco5 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-9LgJJYaXT06ptco5 .cluster text{fill:#333;}#mermaid-svg-9LgJJYaXT06ptco5 .cluster span{color:#333;}#mermaid-svg-9LgJJYaXT06ptco5 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-9LgJJYaXT06ptco5 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-9LgJJYaXT06ptco5 rect.text{fill:none;stroke-width:0;}#mermaid-svg-9LgJJYaXT06ptco5 .icon-shape,#mermaid-svg-9LgJJYaXT06ptco5 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-9LgJJYaXT06ptco5 .icon-shape p,#mermaid-svg-9LgJJYaXT06ptco5 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-9LgJJYaXT06ptco5 .icon-shape .label rect,#mermaid-svg-9LgJJYaXT06ptco5 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-9LgJJYaXT06ptco5 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-9LgJJYaXT06ptco5 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-9LgJJYaXT06ptco5 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 客户端
Nginx
应用服务器 1
应用服务器 2
应用服务器 3

客户端通常只知道 Nginx 的地址,而不知道后端服务器的真实地址。

Nginx 常见用途包括:

  • HTTP/HTTPS 反向代理;
  • 静态资源服务;
  • 七层负载均衡;
  • TLS 终止;
  • 域名和路径路由;
  • 响应压缩;
  • 缓存;
  • 限流;
  • 访问日志;
  • TCP/UDP 代理。

5.2 Nginx 基本负载均衡配置

nginx 复制代码
upstream app_backend {
    least_conn;

    server 10.0.0.11:8080 weight=5 max_fails=3 fail_timeout=10s;
    server 10.0.0.12:8080 weight=3 max_fails=3 fail_timeout=10s;
    server 10.0.0.13:8080 weight=2 max_fails=3 fail_timeout=10s;

    keepalive 64;
}

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://app_backend;

        proxy_http_version 1.1;
        proxy_set_header Connection "";

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_connect_timeout 2s;
        proxy_send_timeout 30s;
        proxy_read_timeout 30s;

        proxy_next_upstream error timeout http_502 http_503 http_504;
        proxy_next_upstream_tries 2;
        proxy_next_upstream_timeout 5s;
    }
}

配置说明:

  • upstream:定义后端服务器组;
  • least_conn:使用最少连接算法;
  • weight:设置服务器权重;
  • max_fails:允许的失败次数;
  • fail_timeout:统计失败和暂时不可用的时间窗口;
  • keepalive:缓存到上游的空闲连接;
  • proxy_pass:将请求转发到上游;
  • proxy_connect_timeout:连接后端的超时时间;
  • proxy_read_timeout:等待后端响应数据的超时时间;
  • proxy_next_upstream:在哪些错误下尝试其他节点;
  • proxy_next_upstream_tries:限制尝试次数。

upstream keepalive 表示每个 Worker 可以缓存一定数量的空闲上游连接,不等于限制全部活动连接数。

5.3 Nginx 常见调度算法

默认轮询

不指定算法时,Nginx 默认使用轮询:

nginx 复制代码
upstream app_backend {
    server 10.0.0.11:8080;
    server 10.0.0.12:8080;
}
加权轮询
nginx 复制代码
upstream app_backend {
    server 10.0.0.11:8080 weight=5;
    server 10.0.0.12:8080 weight=2;
}
最少连接
nginx 复制代码
upstream app_backend {
    least_conn;

    server 10.0.0.11:8080;
    server 10.0.0.12:8080;
}
IP Hash
nginx 复制代码
upstream app_backend {
    ip_hash;

    server 10.0.0.11:8080;
    server 10.0.0.12:8080;
}

IP Hash 可以实现简单的会话保持,但在 NAT、大型企业出口和移动网络场景中容易分布不均。

一致性哈希
nginx 复制代码
upstream cache_backend {
    hash $request_uri consistent;

    server 10.0.0.21:8080;
    server 10.0.0.22:8080;
    server 10.0.0.23:8080;
}

它适合按照 URI、缓存 Key 或其他稳定变量进行路由。

5.4 Nginx 备用服务器

可以将某个节点设置为备用节点:

nginx 复制代码
upstream app_backend {
    server 10.0.0.11:8080;
    server 10.0.0.12:8080;
    server 10.0.0.13:8080 backup;
}

正常情况下,流量只进入前两个节点。当主要节点不可用时,Nginx 才会使用备用节点。

5.5 按路径进行负载均衡

nginx 复制代码
upstream user_service {
    server 10.0.1.11:8080;
    server 10.0.1.12:8080;
}

upstream order_service {
    server 10.0.2.11:8080;
    server 10.0.2.12:8080;
}

server {
    listen 80;
    server_name api.example.com;

    location /api/users/ {
        proxy_pass http://user_service;
    }

    location /api/orders/ {
        proxy_pass http://order_service;
    }
}

需要特别注意 locationproxy_pass 末尾是否带 /,因为它会影响 URI 的替换规则。修改配置后应使用实际请求验证后端最终收到的路径。

5.6 按域名进行负载均衡

nginx 复制代码
server {
    listen 80;
    server_name user.example.com;

    location / {
        proxy_pass http://user_service;
    }
}

server {
    listen 80;
    server_name order.example.com;

    location / {
        proxy_pass http://order_service;
    }
}

同一个 Nginx 实例可以根据不同域名将请求转发到不同服务集群。

5.7 Nginx 健康检查边界

Nginx 开源版常见的 max_failsfail_timeout 主要属于被动故障判断:只有真实请求访问节点并发生失败后,Nginx 才会更新其状态。

它与周期性主动访问 /health 的健康检查不是一回事。

如果需要更完整的主动健康检查、运行时状态管理等能力,应根据所使用的 Nginx 产品、版本和模块核对官方文档。不要把商业版本或第三方模块能力误认为开源版默认能力。

5.8 重试的安全边界

Nginx 可以在连接失败、超时或部分网关错误时切换到其他上游,但需要注意:

  • 后端可能已经收到请求;
  • 客户端虽然没有收到响应,业务操作却可能已经完成;
  • POST、支付、下单等请求可能不是幂等的;
  • 多层重试会形成流量放大。

不要为了提高"成功率"而随意开启非幂等请求重试。核心写操作应使用业务幂等键、唯一索引、状态机或请求记录防止重复执行。

5.9 客户端真实 IP

经过反向代理后,后端看到的 TCP 来源地址通常是 Nginx,而不是最终客户端。

因此常通过以下请求头传递客户端地址:

nginx 复制代码
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

后端不能无条件信任任何客户端直接提交的 X-Forwarded-For。正确做法是:

  • 只信任来自已知代理节点的转发头;
  • 配置可信代理地址范围;
  • 明确多级代理链的解析规则;
  • 避免直接取最左侧或最右侧地址而不校验代理链。

5.10 Nginx 配置验证与平滑加载

检查配置:

bash 复制代码
nginx -t

重新加载:

bash 复制代码
nginx -s reload

使用 systemd 时也可以执行:

bash 复制代码
systemctl reload nginx

推荐流程:

text 复制代码
修改配置
   ↓
nginx -t
   ↓
测试环境验证
   ↓
灰度或平滑加载
   ↓
观察错误率、延迟、连接数
   ↓
确认流量稳定

5.11 Nginx 常见问题

没有设置合理超时

超时过长会让故障连接长期占用资源;超时过短会误伤正常慢请求。应根据真实延迟分布和接口类型分类配置。

所有接口共用一个超时

普通查询、文件上传、流式响应、WebSocket 的连接模型不同,不应该强制共用一套超时。

忽略连接复用

如果每次请求都重新连接后端,会增加 TCP 握手、TLS 握手和端口资源开销。

负载均衡器只有一台

一台 Nginx 前面没有其他高可用机制时,它本身就是单点。可以使用:

  • Keepalived;
  • 云负载均衡;
  • DNS/GSLB;
  • Kubernetes Service;
  • 多可用区入口。
只看平均响应时间

平均值可能掩盖长尾问题,应同时监控 P95、P99、超时率和错误率。


6. HAProxy

6.1 HAProxy 是什么

HAProxy 是专业的开源负载均衡器和代理软件,支持 TCP 和 HTTP 等场景。

它可以同时承担:

  • 四层 TCP 代理;
  • 七层 HTTP 代理;
  • TLS 终止;
  • 后端健康检查;
  • 多种负载均衡算法;
  • ACL 路由;
  • 会话保持;
  • 连接数控制;
  • 运行状态统计;
  • 日志记录;
  • 故障摘除和恢复。

HAProxy 的主要配置结构包括:

  • global:进程级全局配置;
  • defaults:代理的默认配置;
  • frontend:接收客户端流量;
  • backend:定义后端服务器组;
  • listen:把 frontend 和 backend 写在同一个配置段中。

6.2 HAProxy HTTP 负载均衡配置

haproxy 复制代码
global
    log stdout format raw local0
    maxconn 50000

defaults
    log global
    mode http
    option httplog

    timeout connect 3s
    timeout client 30s
    timeout server 30s
    timeout http-request 10s

frontend fe_http
    bind :80

    http-request set-header X-Forwarded-Proto http

    default_backend be_app

backend be_app
    mode http
    balance leastconn

    option forwardfor
    option httpchk

    http-check send meth GET uri /health/ready ver HTTP/1.1 hdr Host app.internal
    http-check expect status 200

    server app1 10.0.0.11:8080 check inter 2s fall 3 rise 2 weight 100
    server app2 10.0.0.12:8080 check inter 2s fall 3 rise 2 weight 100
    server app3 10.0.0.13:8080 check inter 2s fall 3 rise 2 weight 50

其中:

  • bind :80:监听 80 端口;
  • mode http:使用 HTTP 模式;
  • balance leastconn:使用最少连接算法;
  • option forwardfor:添加 X-Forwarded-For
  • option httpchk:启用 HTTP 健康检查;
  • http-check send:定义健康检查请求;
  • http-check expect:定义预期响应;
  • inter 2s:每 2 秒检查一次;
  • fall 3:连续失败 3 次后摘除;
  • rise 2:连续成功 2 次后恢复;
  • weight:节点权重。

6.3 HAProxy TCP 负载均衡配置

下面以 MySQL TCP 连接为例:

haproxy 复制代码
frontend fe_mysql
    bind :3306
    mode tcp
    default_backend be_mysql

backend be_mysql
    mode tcp
    balance leastconn
    option tcp-check

    server db1 10.0.1.11:3306 check inter 2s fall 3 rise 2
    server db2 10.0.1.12:3306 check inter 2s fall 3 rise 2

TCP 模式适合:

  • MySQL;
  • PostgreSQL;
  • Redis;
  • SMTP;
  • MQTT;
  • 自定义 TCP 协议;
  • HTTPS 透传。

需要注意,数据库负载均衡不仅是连接转发问题。不能把数据库主节点和只读副本简单放进同一个后端池,否则写请求可能被发送到只读节点。

数据库代理还要考虑:

  • 主从角色;
  • 读写分离;
  • 事务一致性;
  • 主从延迟;
  • 故障转移;
  • 连接池;
  • 会话变量;
  • 预编译语句和事务粘性。

6.4 HAProxy ACL 路由

HAProxy 可以通过 ACL 根据请求内容选择不同后端。

haproxy 复制代码
frontend fe_api
    bind :80
    mode http

    acl is_user_api path_beg /api/users/
    acl is_order_api path_beg /api/orders/
    acl is_admin hdr(host) -i admin.example.com

    use_backend be_user if is_user_api
    use_backend be_order if is_order_api
    use_backend be_admin if is_admin

    default_backend be_default

ACL 可以基于:

  • 域名;
  • URI;
  • HTTP 方法;
  • 请求头;
  • Cookie;
  • 源 IP;
  • 查询参数;
  • TLS 信息;
  • 连接状态。

这使 HAProxy 可以用于灰度发布、租户路由和安全访问控制。

6.5 HAProxy 健康检查

HAProxy 支持 TCP 和 HTTP 主动健康检查。

TCP 健康检查
haproxy 复制代码
backend be_tcp
    mode tcp

    server node1 10.0.0.11:9000 check
    server node2 10.0.0.12:9000 check

基础 TCP 检查主要验证目标端口能否建立连接。

HTTP 健康检查
haproxy 复制代码
backend be_http
    mode http
    option httpchk

    http-check send meth GET uri /health/ready ver HTTP/1.1 hdr Host app.internal
    http-check expect status 200

    server node1 10.0.0.11:8080 check
    server node2 10.0.0.12:8080 check

HTTP 健康检查能够验证状态码和应用层响应,比单纯检查端口更接近真实业务状态。

不过,健康接口也不能执行过多昂贵操作。如果每秒检查多个依赖、执行复杂 SQL,健康检查本身就可能给系统制造压力。

6.6 HAProxy 状态页面

可以配置一个仅本机访问的统计页面:

haproxy 复制代码
listen stats
    bind 127.0.0.1:8404
    mode http

    stats enable
    stats uri /stats
    stats refresh 10s

访问:

text 复制代码
http://127.0.0.1:8404/stats

不要在没有鉴权和网络限制的情况下,将统计页面直接暴露到公网,因为其中可能包含:

  • 后端 IP;
  • 端口;
  • 节点状态;
  • 流量数据;
  • 会话数量;
  • 基础架构信息。

6.7 HAProxy 配置验证

检查配置文件:

bash 复制代码
haproxy -c -f /etc/haproxy/haproxy.cfg

重新加载:

bash 复制代码
systemctl reload haproxy

查看服务状态:

bash 复制代码
systemctl status haproxy

查看日志:

bash 复制代码
journalctl -u haproxy -f

配置变更后,应重点观察:

  • 前端连接数;
  • 后端连接数;
  • 后端节点状态;
  • 请求排队情况;
  • 连接失败次数;
  • 超时次数;
  • 重试次数;
  • HTTP 状态码;
  • P95、P99 响应时间。

6.8 LVS、Keepalived、Nginx 与 HAProxy 的区别

组件 主要定位 工作层次 主要优势 主要限制
LVS/IPVS 内核级负载调度 四层 性能高、连接处理能力强 不理解 HTTP 业务内容
Keepalived 高可用、VRRP、健康检查 控制层 VIP 漂移、维护 IPVS 节点 本身不是通用七层反向代理
Nginx Web 服务器、反向代理 主要是七层,也支持四层代理 Web 生态成熟、配置直观 复杂动态治理需结合版本和模块
HAProxy 专业负载均衡和代理 四层和七层 健康检查、ACL、连接治理能力强 不以静态资源和内容服务见长

6.9 常见组合方案

Keepalived + Nginx

#mermaid-svg-6yD6D2NLdKd1MFTz{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-6yD6D2NLdKd1MFTz .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-6yD6D2NLdKd1MFTz .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-6yD6D2NLdKd1MFTz .error-icon{fill:#552222;}#mermaid-svg-6yD6D2NLdKd1MFTz .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-6yD6D2NLdKd1MFTz .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-6yD6D2NLdKd1MFTz .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-6yD6D2NLdKd1MFTz .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-6yD6D2NLdKd1MFTz .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-6yD6D2NLdKd1MFTz .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-6yD6D2NLdKd1MFTz .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-6yD6D2NLdKd1MFTz .marker{fill:#333333;stroke:#333333;}#mermaid-svg-6yD6D2NLdKd1MFTz .marker.cross{stroke:#333333;}#mermaid-svg-6yD6D2NLdKd1MFTz svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-6yD6D2NLdKd1MFTz p{margin:0;}#mermaid-svg-6yD6D2NLdKd1MFTz .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-6yD6D2NLdKd1MFTz .cluster-label text{fill:#333;}#mermaid-svg-6yD6D2NLdKd1MFTz .cluster-label span{color:#333;}#mermaid-svg-6yD6D2NLdKd1MFTz .cluster-label span p{background-color:transparent;}#mermaid-svg-6yD6D2NLdKd1MFTz .label text,#mermaid-svg-6yD6D2NLdKd1MFTz span{fill:#333;color:#333;}#mermaid-svg-6yD6D2NLdKd1MFTz .node rect,#mermaid-svg-6yD6D2NLdKd1MFTz .node circle,#mermaid-svg-6yD6D2NLdKd1MFTz .node ellipse,#mermaid-svg-6yD6D2NLdKd1MFTz .node polygon,#mermaid-svg-6yD6D2NLdKd1MFTz .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-6yD6D2NLdKd1MFTz .rough-node .label text,#mermaid-svg-6yD6D2NLdKd1MFTz .node .label text,#mermaid-svg-6yD6D2NLdKd1MFTz .image-shape .label,#mermaid-svg-6yD6D2NLdKd1MFTz .icon-shape .label{text-anchor:middle;}#mermaid-svg-6yD6D2NLdKd1MFTz .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-6yD6D2NLdKd1MFTz .rough-node .label,#mermaid-svg-6yD6D2NLdKd1MFTz .node .label,#mermaid-svg-6yD6D2NLdKd1MFTz .image-shape .label,#mermaid-svg-6yD6D2NLdKd1MFTz .icon-shape .label{text-align:center;}#mermaid-svg-6yD6D2NLdKd1MFTz .node.clickable{cursor:pointer;}#mermaid-svg-6yD6D2NLdKd1MFTz .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-6yD6D2NLdKd1MFTz .arrowheadPath{fill:#333333;}#mermaid-svg-6yD6D2NLdKd1MFTz .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-6yD6D2NLdKd1MFTz .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-6yD6D2NLdKd1MFTz .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-6yD6D2NLdKd1MFTz .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-6yD6D2NLdKd1MFTz .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-6yD6D2NLdKd1MFTz .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-6yD6D2NLdKd1MFTz .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-6yD6D2NLdKd1MFTz .cluster text{fill:#333;}#mermaid-svg-6yD6D2NLdKd1MFTz .cluster span{color:#333;}#mermaid-svg-6yD6D2NLdKd1MFTz div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-6yD6D2NLdKd1MFTz .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-6yD6D2NLdKd1MFTz rect.text{fill:none;stroke-width:0;}#mermaid-svg-6yD6D2NLdKd1MFTz .icon-shape,#mermaid-svg-6yD6D2NLdKd1MFTz .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-6yD6D2NLdKd1MFTz .icon-shape p,#mermaid-svg-6yD6D2NLdKd1MFTz .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-6yD6D2NLdKd1MFTz .icon-shape .label rect,#mermaid-svg-6yD6D2NLdKd1MFTz .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-6yD6D2NLdKd1MFTz .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-6yD6D2NLdKd1MFTz .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-6yD6D2NLdKd1MFTz :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 故障切换
客户端
VIP
Nginx 主节点
Nginx 备节点
应用集群

适合:

  • 中小型 Web 系统;
  • 自建机房;
  • 需要基于 URI 或域名路由;
  • 需要解决单台 Nginx 的单点问题。
Keepalived + LVS

#mermaid-svg-QMqeJzf28Dk4sbp0{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-QMqeJzf28Dk4sbp0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-QMqeJzf28Dk4sbp0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-QMqeJzf28Dk4sbp0 .error-icon{fill:#552222;}#mermaid-svg-QMqeJzf28Dk4sbp0 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-QMqeJzf28Dk4sbp0 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-QMqeJzf28Dk4sbp0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-QMqeJzf28Dk4sbp0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-QMqeJzf28Dk4sbp0 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-QMqeJzf28Dk4sbp0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-QMqeJzf28Dk4sbp0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-QMqeJzf28Dk4sbp0 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-QMqeJzf28Dk4sbp0 .marker.cross{stroke:#333333;}#mermaid-svg-QMqeJzf28Dk4sbp0 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-QMqeJzf28Dk4sbp0 p{margin:0;}#mermaid-svg-QMqeJzf28Dk4sbp0 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-QMqeJzf28Dk4sbp0 .cluster-label text{fill:#333;}#mermaid-svg-QMqeJzf28Dk4sbp0 .cluster-label span{color:#333;}#mermaid-svg-QMqeJzf28Dk4sbp0 .cluster-label span p{background-color:transparent;}#mermaid-svg-QMqeJzf28Dk4sbp0 .label text,#mermaid-svg-QMqeJzf28Dk4sbp0 span{fill:#333;color:#333;}#mermaid-svg-QMqeJzf28Dk4sbp0 .node rect,#mermaid-svg-QMqeJzf28Dk4sbp0 .node circle,#mermaid-svg-QMqeJzf28Dk4sbp0 .node ellipse,#mermaid-svg-QMqeJzf28Dk4sbp0 .node polygon,#mermaid-svg-QMqeJzf28Dk4sbp0 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-QMqeJzf28Dk4sbp0 .rough-node .label text,#mermaid-svg-QMqeJzf28Dk4sbp0 .node .label text,#mermaid-svg-QMqeJzf28Dk4sbp0 .image-shape .label,#mermaid-svg-QMqeJzf28Dk4sbp0 .icon-shape .label{text-anchor:middle;}#mermaid-svg-QMqeJzf28Dk4sbp0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-QMqeJzf28Dk4sbp0 .rough-node .label,#mermaid-svg-QMqeJzf28Dk4sbp0 .node .label,#mermaid-svg-QMqeJzf28Dk4sbp0 .image-shape .label,#mermaid-svg-QMqeJzf28Dk4sbp0 .icon-shape .label{text-align:center;}#mermaid-svg-QMqeJzf28Dk4sbp0 .node.clickable{cursor:pointer;}#mermaid-svg-QMqeJzf28Dk4sbp0 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-QMqeJzf28Dk4sbp0 .arrowheadPath{fill:#333333;}#mermaid-svg-QMqeJzf28Dk4sbp0 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-QMqeJzf28Dk4sbp0 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-QMqeJzf28Dk4sbp0 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-QMqeJzf28Dk4sbp0 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-QMqeJzf28Dk4sbp0 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-QMqeJzf28Dk4sbp0 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-QMqeJzf28Dk4sbp0 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-QMqeJzf28Dk4sbp0 .cluster text{fill:#333;}#mermaid-svg-QMqeJzf28Dk4sbp0 .cluster span{color:#333;}#mermaid-svg-QMqeJzf28Dk4sbp0 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-QMqeJzf28Dk4sbp0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-QMqeJzf28Dk4sbp0 rect.text{fill:none;stroke-width:0;}#mermaid-svg-QMqeJzf28Dk4sbp0 .icon-shape,#mermaid-svg-QMqeJzf28Dk4sbp0 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-QMqeJzf28Dk4sbp0 .icon-shape p,#mermaid-svg-QMqeJzf28Dk4sbp0 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-QMqeJzf28Dk4sbp0 .icon-shape .label rect,#mermaid-svg-QMqeJzf28Dk4sbp0 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-QMqeJzf28Dk4sbp0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-QMqeJzf28Dk4sbp0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-QMqeJzf28Dk4sbp0 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 故障切换
客户端
VIP
LVS 主 Director
LVS 备 Director
Real Server 集群

适合:

  • 大规模四层流量;
  • 高连接数;
  • 对转发性能要求高;
  • 后端协议不局限于 HTTP。
Keepalived + HAProxy

适合:

  • 同时需要 TCP 和 HTTP 代理;
  • 需要详细健康检查;
  • 需要 ACL 和灵活流量控制;
  • 希望通过 VRRP 解决 HAProxy 入口单点。
云负载均衡 + Nginx 或 HAProxy

#mermaid-svg-wZSrbHWIDW13Nyqz{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-wZSrbHWIDW13Nyqz .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-wZSrbHWIDW13Nyqz .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-wZSrbHWIDW13Nyqz .error-icon{fill:#552222;}#mermaid-svg-wZSrbHWIDW13Nyqz .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-wZSrbHWIDW13Nyqz .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-wZSrbHWIDW13Nyqz .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-wZSrbHWIDW13Nyqz .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-wZSrbHWIDW13Nyqz .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-wZSrbHWIDW13Nyqz .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-wZSrbHWIDW13Nyqz .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-wZSrbHWIDW13Nyqz .marker{fill:#333333;stroke:#333333;}#mermaid-svg-wZSrbHWIDW13Nyqz .marker.cross{stroke:#333333;}#mermaid-svg-wZSrbHWIDW13Nyqz svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-wZSrbHWIDW13Nyqz p{margin:0;}#mermaid-svg-wZSrbHWIDW13Nyqz .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-wZSrbHWIDW13Nyqz .cluster-label text{fill:#333;}#mermaid-svg-wZSrbHWIDW13Nyqz .cluster-label span{color:#333;}#mermaid-svg-wZSrbHWIDW13Nyqz .cluster-label span p{background-color:transparent;}#mermaid-svg-wZSrbHWIDW13Nyqz .label text,#mermaid-svg-wZSrbHWIDW13Nyqz span{fill:#333;color:#333;}#mermaid-svg-wZSrbHWIDW13Nyqz .node rect,#mermaid-svg-wZSrbHWIDW13Nyqz .node circle,#mermaid-svg-wZSrbHWIDW13Nyqz .node ellipse,#mermaid-svg-wZSrbHWIDW13Nyqz .node polygon,#mermaid-svg-wZSrbHWIDW13Nyqz .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-wZSrbHWIDW13Nyqz .rough-node .label text,#mermaid-svg-wZSrbHWIDW13Nyqz .node .label text,#mermaid-svg-wZSrbHWIDW13Nyqz .image-shape .label,#mermaid-svg-wZSrbHWIDW13Nyqz .icon-shape .label{text-anchor:middle;}#mermaid-svg-wZSrbHWIDW13Nyqz .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-wZSrbHWIDW13Nyqz .rough-node .label,#mermaid-svg-wZSrbHWIDW13Nyqz .node .label,#mermaid-svg-wZSrbHWIDW13Nyqz .image-shape .label,#mermaid-svg-wZSrbHWIDW13Nyqz .icon-shape .label{text-align:center;}#mermaid-svg-wZSrbHWIDW13Nyqz .node.clickable{cursor:pointer;}#mermaid-svg-wZSrbHWIDW13Nyqz .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-wZSrbHWIDW13Nyqz .arrowheadPath{fill:#333333;}#mermaid-svg-wZSrbHWIDW13Nyqz .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-wZSrbHWIDW13Nyqz .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-wZSrbHWIDW13Nyqz .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wZSrbHWIDW13Nyqz .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-wZSrbHWIDW13Nyqz .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wZSrbHWIDW13Nyqz .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-wZSrbHWIDW13Nyqz .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-wZSrbHWIDW13Nyqz .cluster text{fill:#333;}#mermaid-svg-wZSrbHWIDW13Nyqz .cluster span{color:#333;}#mermaid-svg-wZSrbHWIDW13Nyqz div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-wZSrbHWIDW13Nyqz .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-wZSrbHWIDW13Nyqz rect.text{fill:none;stroke-width:0;}#mermaid-svg-wZSrbHWIDW13Nyqz .icon-shape,#mermaid-svg-wZSrbHWIDW13Nyqz .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wZSrbHWIDW13Nyqz .icon-shape p,#mermaid-svg-wZSrbHWIDW13Nyqz .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-wZSrbHWIDW13Nyqz .icon-shape .label rect,#mermaid-svg-wZSrbHWIDW13Nyqz .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wZSrbHWIDW13Nyqz .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-wZSrbHWIDW13Nyqz .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-wZSrbHWIDW13Nyqz :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 客户端
云负载均衡
Nginx/HAProxy 1
Nginx/HAProxy 2
应用服务

这种方式把基础设施入口高可用交给云平台,Nginx 或 HAProxy 负责业务层路由。

6.10 负载均衡选型建议

业务需求 推荐方向
超高并发四层转发 LVS/IPVS 或云四层负载均衡
普通 Web 反向代理 Nginx
复杂 TCP/HTTP 代理与健康检查 HAProxy
自建环境中的 VIP 高可用 Keepalived
按域名、URI 路由 Nginx 或 HAProxy
数据库、Redis 等 TCP 连接 HAProxy、LVS 或专业数据库代理
需要隐藏底层网络复杂度 云负载均衡
Kubernetes 服务入口 Service、Ingress 或 Gateway API
跨地域流量调度 DNS、GSLB、Anycast 或云全局负载均衡

选型时不应只比较理论性能,还要考虑:

  • 团队熟悉程度;
  • 配置和发布方式;
  • 监控能力;
  • 故障定位成本;
  • 多可用区能力;
  • 配置动态更新;
  • 证书管理;
  • 安全审计;
  • 自动扩缩容;
  • 预算和运维成本。

结语

负载均衡的本质是将流量合理、稳定地分配给多个服务节点,但生产环境中的负载均衡远不只是一个调度算法。

一个完整的负载均衡体系还需要解决:

  • 节点健康检查;
  • 单点故障;
  • 超时和重试;
  • 会话状态;
  • 灰度发布;
  • 限流与过载保护;
  • TLS 和客户端真实 IP;
  • 日志、指标与链路追踪;
  • 扩缩容和优雅下线;
  • 跨机房和跨可用区容灾。

可以用下面几句话概括常见组件的定位:

LVS 擅长高性能四层调度。
Keepalived 擅长 VIP 漂移、高可用和 IPVS 健康维护。
Nginx 擅长 Web 服务和 HTTP 反向代理。
HAProxy 擅长专业的四层、七层代理与连接治理。

真正合理的架构不是堆叠尽可能多的负载均衡组件,而是在满足性能、可用性和业务路由需求的前提下,选择最简单、最容易监控和维护的方案。

参考资料

相关推荐
用户9385156350714 小时前
Docker + Nginx + Node.js:从“我的电脑能跑,你的电脑跑不了”到一键部署
后端·nginx·docker
码云骑士21 小时前
110-多模型热切换-API网关-LiteLLM代理-负载均衡故障转移
运维·python·负载均衡
teak_on_my_way1 天前
外网通过 Nginx 访问 Doris Stream Load:一次 HTTP 307 疑难排查与完整代理方案
运维·数据库·nginx·http
想要成为老金高手1 天前
Nginx、PHP、Memcache、Tomcat 与 OpenResty 实验汇总
nginx·php·memcached
g10565591392 天前
LAMP博客平台Wordpress实战
android·mysql·nginx·php
-今昭-2 天前
HAProxy 负载均衡部署
运维·负载均衡
CDN3602 天前
流媒体加速实践:出海东南亚短视频点播频繁缓冲,HLS 分片与 Nginx 配置调优
java·网络·nginx·流媒体加速
月落汀兰2 天前
Linux Nginx全套实战通关|静态站点/虚拟主机/HTTPS/PHP/反向代理/七层负载均衡,每行命令逐参数拆解
linux·nginx·https
tryCbest2 天前
Vue3项目在Nginx中配置代理后端IP
nginx·vue3