1 前言
1.1 什么是负载均衡
负载均衡时一种分布式系统设计技术,通过请求或任务均匀分配到多台服务器或服务实例上,来提高系统的并发能力、可用性和稳定性。
1.2 为什么需要负载均衡
在软件开发和系统架构中,单台服务器会面临:
- 性能瓶颈:CPU、内存、带宽有限。
- 单点故障:机器挂了,整个服务不可用。
- 扩展困难:业务增长快,单机撑不住。
负载均衡可以解决如下问题:
- 提高吞吐量(多台机器一起扛流量)
- 保证高可用性(某节点挂了,自动切换到其他节点)
- 支持水平扩展(加机器就能顶流量)
1.3 负载均衡算法策略分类
常见分配算法:
- 轮询(Round Robin):顺序把请求分给不同服务器。
- 加权轮询(Weighted Round Robin):给性能强的机器更多请求。
- 最少连接数(Least Connections):请求分配给当前连接最少的服务器。
- 源地址哈希(IP Hash):同一个客户端 IP 总是分配到同一台服务器。
- 一致性哈希(Consistent Hashing):常用于分布式缓存,减少节点变动带来的缓存失效。
2 基本配置
http {
upstream backend {
server 192.168.1.101;
server 192.168.1.102;
server 192.168.1.103;
}
server {
listen 80;
location / {
proxy_pass http://backend;
}
}
}
upstream backend
:定义一个后端服务器组。
server
:列出后端节点。
proxy_pass
:将客户端请求转发到 backend
组。
3 负载均衡策略
3.1 轮训(默认)
upstream backend {
server 192.168.56.20;
server 192.168.56.21;
}
- 每个请求依次分配给不同服务器。
- 简单易用,适合性能相近的服务器。
3.2 加权轮训
upstream backend {
server 192.168.56.20 weight=3;
server 192.168.56.21 weight=1;
}
192.168.56.20
的请求量是另一台的 3 倍。
- 适合性能差异较大的服务器。
3.3 IP Hash
upstream backend {
ip_hash;
server 192.168.56.20;
server 192.168.56.21;
}
- 同一个客户端 IP 会固定分配到同一台服务器。
- 适合有会话保持需求的应用(比如登录状态保存在本地内存)。
3.4 最少连接(least_conn)
upstream backend {
least_conn;
server 192.168.56.20;
server 192.168.56.21;
}
- 请求优先分配给连接最少得服务器。
- 适合长连接应用(WebSocket、上传下载)。
4 健康检查
nginx 社区默认只有被动健康检查(请求失败后才会标记节点不可用),配置如下:
upstream backend {
server 192.168.56.20 max_fails=3 fail_timeout=30s;
server 192.168.56.21;
}
max_fails=3
:连续失败 3 次,认为节点不可用。
fail_timeout=30s
:30 秒后重新尝试。
5 架构图
+
Client | https://www.couragesteak.com |
+
|
v
+
| Nginx |
| (负载均衡器) |
+
/ | \
v v v
+
| App #1 | | App #2 | | App #3 |
+
<h2><a id="1__0"></a>1 前言</h2>
<h3><a id="11__2"></a>1.1 什么是负载均衡</h3>
<p>负载均衡时一种分布式系统设计技术,通过请求或任务均匀分配到多台服务器或服务实例上,来提高系统的<strong>并发能力、可用性和稳定性。</strong></p>
<h3><a id="12__6"></a>1.2 为什么需要负载均衡</h3>
<p>在软件开发和系统架构中,单台服务器会面临:</p>
<ol>
<li>性能瓶颈:CPU、内存、带宽有限。</li>
<li>单点故障:机器挂了,整个服务不可用。</li>
<li>扩展困难:业务增长快,单机撑不住。</li>
</ol>
<p>负载均衡可以解决如下问题:</p>
<ul>
<li>提高吞吐量(多台机器一起扛流量)</li>
<li>保证高可用性(某节点挂了,自动切换到其他节点)</li>
<li>支持水平扩展(加机器就能顶流量)</li>
</ul>
<h3><a id="13__20"></a>1.3 负载均衡算法策略分类</h3>
<p>常见分配算法:</p>
<ol>
<li><strong>轮询(Round Robin)</strong>:顺序把请求分给不同服务器。</li>
<li><strong>加权轮询(Weighted Round Robin)</strong>:给性能强的机器更多请求。</li>
<li><strong>最少连接数(Least Connections)</strong>:请求分配给当前连接最少的服务器。</li>
<li><strong>源地址哈希(IP Hash)</strong>:同一个客户端 IP 总是分配到同一台服务器。</li>
<li><strong>一致性哈希(Consistent Hashing)</strong>:常用于分布式缓存,减少节点变动带来的缓存失效。</li>
</ol>
<h2><a id="2__30"></a>2 基本配置</h2>
<pre><div class="hljs"><code class="lang-nginx"><span class="hljs-section">http</span> {
<span class="hljs-section">upstream</span> backend {
<span class="hljs-attribute">server</span> <span class="hljs-number">192.168.1.101</span>;
<span class="hljs-attribute">server</span> <span class="hljs-number">192.168.1.102</span>;
<span class="hljs-attribute">server</span> <span class="hljs-number">192.168.1.103</span>;
}
<span class="hljs-section">server</span> {
<span class="hljs-attribute">listen</span> <span class="hljs-number">80</span>;
<span class="hljs-section">location</span> / {
<span class="hljs-attribute">proxy_pass</span> http://backend;
}
}
}
</code></div></pre>
<p><code>upstream backend</code>:定义一个后端服务器组。</p>
<p><code>server</code>:列出后端节点。</p>
<p><code>proxy_pass</code>:将客户端请求转发到 <code>backend</code> 组。</p>
<h2><a id="3__56"></a>3 负载均衡策略</h2>
<h3><a id="31__58"></a>3.1 轮训(默认)</h3>
<pre><div class="hljs"><code class="lang-nginx"><span class="hljs-section">upstream</span> backend {
<span class="hljs-attribute">server</span> <span class="hljs-number">192.168.56.20</span>;
<span class="hljs-attribute">server</span> <span class="hljs-number">192.168.56.21</span>;
}
</code></div></pre>
<ul>
<li>每个请求依次分配给不同服务器。</li>
<li>简单易用,适合性能相近的服务器。</li>
</ul>
<h3><a id="32__70"></a>3.2 加权轮训</h3>
<pre><div class="hljs"><code class="lang-nginx"><span class="hljs-section">upstream</span> backend {
<span class="hljs-attribute">server</span> <span class="hljs-number">192.168.56.20</span> weight=<span class="hljs-number">3</span>;
<span class="hljs-attribute">server</span> <span class="hljs-number">192.168.56.21</span> weight=<span class="hljs-number">1</span>;
}
</code></div></pre>
<ul>
<li><code>192.168.56.20</code> 的请求量是另一台的 3 倍。</li>
<li>适合性能差异较大的服务器。</li>
</ul>
<h3><a id="33_IP_Hash_82"></a>3.3 IP Hash</h3>
<pre><div class="hljs"><code class="lang-nginx"><span class="hljs-section">upstream</span> backend {
ip_hash;
<span class="hljs-attribute">server</span> <span class="hljs-number">192.168.56.20</span>;
<span class="hljs-attribute">server</span> <span class="hljs-number">192.168.56.21</span>;
}
</code></div></pre>
<ul>
<li>同一个客户端 IP 会固定分配到同一台服务器。</li>
<li>适合有会话保持需求的应用(比如登录状态保存在本地内存)。</li>
</ul>
<h3><a id="34_least_conn_95"></a>3.4 最少连接(least_conn)</h3>
<pre><div class="hljs"><code class="lang-nginx"><span class="hljs-section">upstream</span> backend {
least_conn;
<span class="hljs-attribute">server</span> <span class="hljs-number">192.168.56.20</span>;
<span class="hljs-attribute">server</span> <span class="hljs-number">192.168.56.21</span>;
}
</code></div></pre>
<ul>
<li>请求优先分配给连接最少得服务器。</li>
<li>适合长连接应用(WebSocket、上传下载)。</li>
</ul>
<h2><a id="4__108"></a>4 健康检查</h2>
<p>nginx 社区默认只有被动<strong>健康检查</strong>(请求失败后才会标记节点不可用),配置如下:</p>
<pre><div class="hljs"><code class="lang-nginx"><span class="hljs-section">upstream</span> backend {
<span class="hljs-attribute">server</span> <span class="hljs-number">192.168.56.20</span> max_fails=<span class="hljs-number">3</span> fail_timeout=<span class="hljs-number">30s</span>;
<span class="hljs-attribute">server</span> <span class="hljs-number">192.168.56.21</span>;
}
</code></div></pre>
<p><code>max_fails=3</code>:连续失败 3 次,认为节点不可用。</p>
<p><code>fail_timeout=30s</code>:30 秒后重新尝试。</p>
<h2><a id="5__123"></a>5 架构图</h2>
<pre><div class="hljs"><code class="lang-lua"> +<span class="hljs-comment">--------------------------------+</span>
Client | https://www.couragesteak.com |
+<span class="hljs-comment">--------------------------------+</span>
|
v
+<span class="hljs-comment">----------------+</span>
| Nginx |
| (负载均衡器) |
+<span class="hljs-comment">----------------+</span>
/ | \
v v v
+<span class="hljs-comment">-----------+ +-----------+ +-----------+</span>
| App #<span class="hljs-number">1</span> | | App #<span class="hljs-number">2</span> | | App #<span class="hljs-number">3</span> |
+<span class="hljs-comment">-----------+ +-----------+ +-----------+</span>
</code></div></pre>
评论区