首页  /  Web 应用服务  /  正文

Nginx 负载均衡及其配置

Web 应用服务 2026-10-01📖 15 分钟👁 —
🌐 Web 应用服务 · Nginx第 4 / 8 页12345678📖 完整导航 →

一、负载均衡介绍

应用场景:请求转到一台服务器上,如果它挂了,业务会受到影响。为了避免这样的情况,需要多台服务器提供一样的服务,还能分担流量压力。

被负载均衡的服务器称为服务器的集群。

负载均衡的时候可以设置一些算法,比如每台服务器都承受一样大的流量(轮询),或者访问过去发现挂了就换别的(retry)。


二、反向代理到外网和内网主机的配置

需要在 location 块配置。

补充一下专业术语:块(block)就是用 {} 包裹的一组配置,像 http { ... }、server { ... };上下文(context)是块的官方名称,表示配置生效的范围,比如 server 上下文、location 上下文;指令(directive)是块里的具体配置项,比如 listen 80;、root /var/www;;模块(module)是实现某个功能的代码单元,比如 ngx_http_proxy_module。

location 块下的 root 目录 和要配置的 proxy_pass 是二选一的,可以注释掉其中一个(一般都注释掉 root,因为要配置负载均衡嘛)。

正确写法 —— root 和 index 在 server 块下是全局生效,在 location 块下是局部覆盖。

proxy_pass 后面是代理地址(写 IP/url),可以是多个。

这里用 www 的站点测试(http://senrenbanka.art:8081/):

server {
            listen 8081;
            root /var/www/www;
            index www.html;

            server_name _;

            location / {
            proxy_pass http://senrenbanka.art;
            }
}

reload 之后访问站点,1.14.137.231 会跳转到 www.senrenbanka.art:

proxy_pass 转发出去,挂了还能 retry,算法是轮询

如图所示,用户请求到 Nginx,Nginx 转发到 proxy_pass 的目标,目标返回数据给 Nginx,Nginx 再返回给用户(这个配置就包括了反向代理)。

假设我们设置的 pass 是 senrenbanka.art,访问 IP 时会跳到 www.senrenbanka.art(默认 80 端口)这个站点是堡垒机,可以打开控制台查 - Network 查看流量。

HTTP 数据包中又 Nginx 的信息如图:

响应头里的 Server 是 nginx/1.18.0 (Ubuntu)

正常是在响应中能看到 302 的,但是我的服务器 80 配置了 JumpServer,本身不返回 302,所以没有。

验证:把 proxy_pass 的配置换成 qq.com 的 url,浏览器就能看到 302 了(如下图):

状态码 302 Moved Temporarily

不支持反向代理到 HTTPS,后面会提到。

以上就配置好了一个简单的 proxy_pass。

如果跳到本机呢?参数改为服务器的 url,自然就是 80 端口了。

在内网做反向代理,配置参数写一个 IP 的 utl 即可,这样访问本机,就会跳到配置 IP。

如图,在 192.168.44.102 配置代理到 192.168.44.101 访问 102 的结果如图:

访问 101 显示的是 102 上的 Hello world

以上就是代理到一台服务器的简单介绍。


三、负载均衡 1 —— 基本配置

又 101,102,103 三台同一网段的主机,想要实现:访问 101 不只是跳到 102,还能是 103(轮询--雨露均沾),可在 101 配置 upstream。

云服务器的内网 IP 是固定的。

upstream httpd {
  server 10.1.0.12:8080;
  server 10.1.0.12:80;
}
# 可以写公网IP但是不推荐,有各种问题
# 假设原始监听的就是8081,又负载了8081会死循环的
server {
  listen 8081;
  root /var/www/www;
  index www.html;
  
  location / {
  
  proxy_pass http://httpd; # 需要用到虚拟域名
  # 域名可以随意起,但是要和upstream对应

  }
}
# 当然这样配置肯定不合理,只是作为演示

四、负载均衡 2 —— 权重、down 和 backup

刚才提到了轮询,由于服务器的配置是不一样的,所以需要调整轮询的比例,谁多谁少。

down 就是关闭的意思,不会负载到配置的服务。

backup 是备用机的配置,只有其他机器不能用了,才会负载到这里(想要验证可以把其他的服务都 down 然后选一个配置 backup)。

默认配置就是 up,不写。

这些配置都是不常用的,因为我们工作需要的是动态配置,只是单单依靠命令配置还是太简单了,当然 backup 可以适当使用。

upstream httpd {
  server 10.1.0.12:8080 weight=8;
  server 10.1.0.12:80 weight=2 backup;
  server 10.1.0.12:81 weight=1 down;# 后面写down就是不参与轮询
}
# 如果配置的主机没启动就很可能卡住的
server {
  listen 8081;
  root /var/www/www;
  index www.html;
  
  location / {
  
  proxy_pass http://httpd;

  }

}

五、负载均衡 3 —— ip_hash、fair、least_conn 和无状态会话

这里讲一些不太常用的策略(不会在生产环境使用),不需要花太多时间研究。

无法保持会话状态:在用户登录时会给服务器发包,得到 Cookie 值,服务器端存储 Session 值,但是由于轮询机制,在其中一台机器登录后会话被转移到另外的机器上,会导致,另一台没有存储的 Session,用户就又需要登录了(一些需要保持会话的操作都会遇到这个问题,所以需要手段来保持会话)。

ip_hash 会判断 IP 地址,相同的 IP 指向相同的服务器,但是 IP 很可能是变化的,所以不常用这样的静态配置。

least_conn 最少连接数的访问,一个负载服务器的连接访问数过多,会转移到另外的负载服务器上。但是这样是不合理的,分配少的原因就是轮询的时候没有轮询到更多的用户,也就是权重低,也就是存在一些问题,可能是硬件差,所以理论上就不应该给他分配更多的用户(流量倾斜的配置)。

而且上新的服务肯定会经历 reload 过程:停掉原来的工作进程,新的进程起来。监测后端的服务会在短时间内完成,后端服务基本归零,比较耗时的需要就久一些。

假设一个功能:用户提交了数据,后端需要处理 2min,然后才返回请求,这时候我们不会选择 least_conn,而是异步化处理,写到消息中间件里面,等到负责处理缓慢服务的服务器处理完成后以异步消息存储的方式通知用户。

fair 根据后端服务器响应时间转发请求(需要第三方插件),此操作会将流量倾斜给响应短的服务器,这是不合理的:可能只是因为硬件过热(交换机),瞬时响应慢,然后流量倾斜给配置差的,可能瞬间冲垮服务器,造成损失。

url_hash 需要第三方插件,来保持会话,可以完成定向流量转发(不是定向用户),假设用户访问注册页面,会生成一个哈希值,相同的哈希值会转发到相同的服务器上,如果再次访问登录功能,转发到了另一个服务器,就会无法不能登录。

适合固定资源不在同一服务器的情况:文件散落不同服务器,找文件必须到指定服务器,这时候可以通过 url 定位进行流量转发。

上述参数不能进行动态改变,基本无法在实际生产环境中使用,动态上下线服务器都做不到的(应当用脚本变成管理服务列表、检测后端服务、配置参数、定向流量转发)。

流量倾斜的后果是非常严重的,可能挂掉服务器。


只要有轮询,基本无法做到有状态,即存储状态信息,比如 Session。

现在的主流方式

只能做无状态的,即不存储状态信息,可以把 Session 存储到独立的服务器,比如 Redis 服务器,所有的 Cookie 都去 Redis 找 Session(集群化 Session 共享),但不适用高 QPS 场景,高并发需要优化无状态会话:比如下发 token 鉴权字段,用户请求到 Nginx 服务器,Nginx 代理到负责校验权限的服务器,校验完成下发权限。

token 在请求头中作为字段出现。

token 的鉴权方式:下发到客户端,记录了用户信息并进行双端加密(客户端改不了),用户访问服务器,服务器用 token 解开(相当于 Session 和 Cookie 整合到了一个"文件",服务器不存储,只做校验)。

应用:假设服务器有一个 tar 压缩包,加了密码(密码在服务端),客户端不需要知道 token 的内容,只需要携带访问即可,改了 token 肯定就解不开密码了。