一文帮你彻底弄清楚【负载均衡】的概念、配通俗易懂案例演示讲解(Python/Nginx/FastAPI).
1. 负载均衡的概念
负载均衡(Load Balancing)是一种技术,用于将网络流量或计算任务合理地分配到多个服务器、进程或资源上,以避免单一节点过载,提高系统的性能、可靠性和可用性。它通常用于分布式系统或高并发场景。
简单来说,负载均衡就像一个“交通指挥员”,负责把请求分发到不同的“工人”(服务器),确保每个工人不会太忙或太闲。
2. 负载均衡的作用
- 提高性能:通过分担负载,避免单台服务器压力过大,加快响应速度。
- 增强可靠性:如果一台服务器宕机,负载均衡器可以将流量转发到其他可用服务器,避免服务中断。
- 扩展性:当流量增加时,可以方便地添加更多服务器,负载均衡器会自动分配任务。
- 优化资源利用:让每台服务器的资源(CPU、内存等)都被充分利用,避免浪费。
3. 通俗解释
想象一下,你去一家餐厅吃饭,门口有个服务员。如果所有顾客都挤到一张桌子旁点餐,那这张桌子肯定忙不过来,其他桌子却闲着。服务员要是聪明点,就会把顾客均匀分到不同的桌子,这样大家都能快速吃上饭,不会有人等太久。这里的服务员就是“负载均衡器”,桌子就是“服务器”。
在互联网中,负载均衡器把用户的请求(比如打开网页)分到不同的服务器上,确保网站不会因为人太多而崩溃。
下面我将为你提供一个真实生产环境的负载均衡示例,使用 Nginx 作为负载均衡器,后端基于 FastAPI 实现一个简单的中文翻译成英文的服务。这个例子会包括完整的配置和代码,模拟一个高并发场景下的翻译服务。
场景描述
假设你运营一个在线翻译服务,用户通过 HTTP 请求发送中文文本,服务器返回英文翻译。
为了应对高并发访问,你部署了多个 FastAPI 后端实例(例如 3 个实例运行在不同端口),并使用 Nginx 将请求分发到这些实例上。
1. 后端 FastAPI 代码
我们使用一个简单的翻译库(googletrans 或模拟翻译)来实现中文到英文的翻译功能。以下是 FastAPI 的实现:
环境准备
- Windows 10:确保已安装 Python 3.8+ 和 Nginx。
- 工具安装:
- Python:从官网下载安装。
- Nginx:从 Nginx 官网 下载 Windows 版(如 nginx-1.24.0.zip),解压到 C:\nginx。
-
- 安装依赖:
-
pip install fastapi uvicorn googletrans==3.1.0a0 locust
# 文件名: app.py from fastapi import FastAPI import uvicorn from pydantic import BaseModel from googletrans import Translator app = FastAPI() translator = Translator() class TranslationRequest(BaseModel): text: str @app.post("/translate") async def translate_text(request: TranslationRequest): result = translator.translate(request.text, src="zh-cn", dest="en") return {"translation": result.text} if __name__ == "__main__": import sys port = int(sys.argv[1]) if len(sys.argv) > 1 else 8000 uvicorn.run(app, host="0.0.0.0", port=port)
python app.py 8000 # 实例 1 python app.py 8001 # 实例 2 python app.py 8002 # 实例 3
https://127.0.0.1:8000 https://127.0.0.1:8001 https://127.0.0.1:8002
2. 配置 Nginx 负载均衡
Windows 下 Nginx 的配置文件默认在解压目录的 conf 文件夹中,
例如:
C:\nginx\conf\nginx.conf
编辑它,添加以下内容:【可以把nginx.conf中默认的内容清除掉,用如下代码覆盖即可】
# 工作进程数,根据你的 CPU 核心数调整(Windows 下通常设为 1) worker_processes 1; # 事件模型配置 events { worker_connections 1024; # 每个进程的最大连接数 } # HTTP 服务配置 http { include mime.types; # 引入 MIME 类型定义 default_type application/octet-stream; # 默认内容类型 # 日志配置(可选,Windows 下路径使用反斜杠) # access_log logs\access.log; # error_log logs\error.log; sendfile on; # 启用高效文件传输 keepalive_timeout 65; # 保持连接超时时间(秒) # 定义上游服务器组(负载均衡的目标) upstream translation_backend { server 127.0.0.1:8000; # FastAPI 实例 1 server 127.0.0.1:8001; # FastAPI 实例 2 server 127.0.0.1:8002; # FastAPI 实例 3 } # 主服务器块 server { listen 80; # 监听 80 端口 server_name localhost; # 服务器名称 # 根路径代理到后端 location / { proxy_pass http://translation_backend; # 转发到上游服务器组 proxy_set_header Host $host; # 传递主机头 proxy_set_header X-Real-IP $remote_addr; # 传递客户端 IP proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 传递代理链 IP } # 错误页面(可选) error_page 500 502 503 504 /50x.html; location = /50x.html { root html; # 错误页面位于 C:\nginx\html } } }
启动 Nginx:
打开命令提示符(CMD),进入 Nginx 目录:
然后浏览器输入:
http://localhost
返回如下结果,即表明nginx已经成功启动了!
nginx -s stop
3. 模拟高并发
我们使用 locust 工具来模拟大量用户并发请求。
Locust 脚本
创建一个新文件 locustfile.py:
from locust import HttpUser, task, between class TranslationUser(HttpUser): wait_time = between(1, 3) # 每个用户等待 1-3 秒 @task def translate(self): self.client.post("/translate", json={"text": "你好,世界"})
运行 Locust
- 打开 CMD,进入包含 locustfile.py 的目录。
- 启动 Locust:【注意这里要把 locustfile.py这个文件放到虚拟环境的Scripts目录下,具体见后面追问】
-
接下来可以进入到上图所示的目录中,执行
locust
或者把上面的路径添加到环境变量中,
然后在Pycharm中执行如下命令,也会有类似效果。
python -m locust
点击Enter键,或者打开浏览器,访问 http://localhost:8089,就会进入 Locust 的 Web 界面。
配置参数:
- Number of users:50(模拟 50 个并发用户)。
- Spawn rate:5(每秒新增 5 个用户)。
- Host:http://localhost。
- 点击 "Start " 开始测试。
Locust 会发送大量请求到 http://localhost/translate,Nginx 会将这些请求分发到 8000、8001 和 8002 端口的 FastAPI 实例。
4. 验证负载均衡效果
- 观察 CMD/Pycharm 输出:在每个 FastAPI 实例的命令行窗口中,你会看到请求被轮流处理。例如:
- 8000 窗口:收到 "你好,世界" 请求。
- 8001 窗口:收到下一个请求。
- 8002 窗口:收到再下一个请求。
- Locust 界面:查看请求成功率、响应时间等指标,确认负载均衡是否正常工作。
页面内容很多,都是常见的性能测试参数和指标,可以自己去探索,都不算难理解。
5. 注意事项
- Windows 限制:Windows 下的 Nginx 性能不如 Linux,可能无法处理超高并发。如果测试效果不明显,可以减少模拟用户数(例如 20 个)。
- 防火墙:确保 Windows 防火墙允许 80、8000、8001、8002 和 8089 端口的访问。
- 资源占用:单机模拟多个实例会占用较多 CPU 和内存,建议关闭无关程序。
6. 完整工作流程
- 用户(Locust)发送大量翻译请求到 http://localhost/translate。
- Nginx 监听 80 端口,收到请求后按轮询方式分发到 8000、8001 或 8002。
- FastAPI 实例处理请求,返回翻译结果。
- Nginx 将结果返回给 Locust,用户看到 "Hello, World"。
通过这种方式,你可以在 Windows 10 单机上模拟出高并发的负载均衡场景。
至此,就完成了负载均衡的整个流程。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
附报错及注意点-:
这里要注意:
netstat -aon | findstr :8000
检查防火墙
- Windows 防火墙可能阻止了 80 端口。
- 测试:
telnet localhost 80
解决方案:
- 临时关闭防火墙测试:
netsh advfirewall set allprofiles state off
netsh advfirewall firewall add rule name="Allow Nginx" dir=in action=allow protocol=TCP localport=80
之间第一次配置错误,原因是发生在nginx.conf的配置上:
从你的 nginx.conf 文件来看,你在默认配置的基础上追加了负载均衡相关的配置,但这确实存在问题。
问题的核心在于 Nginx 配置中出现了两个监听相同端口(80 端口)的 server 块,这会导致冲突。
Nginx 不允许在同一端口上定义多个 server 块,除非通过 server_name 区分不同的虚拟主机,而你的两个 server 块都用了 server_name localhost,因此第二个 server 块可能被忽略,导致负载均衡配置没有生效。
这就是为什么 Locust 测试 /translate 时返回 404 的原因:请求可能被路由到了第一个 server 块(默认返回静态 HTML 文件),而不是你的负载均衡配置。
追问:这个locustfile.py是不是一定得命名成这样,并且放在这个指定的文件目录下才行呢?
关于 locustfile.py 的命名和存放位置,确实有一些规则和灵活性。
下面是详细解释
1. locustfile.py 是否必须命名成这样?
不一定,但这是 Locust 的默认约定。
- 默认文件名:
- Locust 在启动时会默认寻找当前目录下的 locustfile.py 文件作为测试脚本。
- 如果你直接运行 python -m locust 或 locust,它会自动加载这个文件。
- 自定义文件名:
- 如果你想用其他文件名(例如 test.py 或 my_locust_test.py),可以通过命令行参数 --locustfile 指定:
python -m locust -f my_locust_test.py
-
- -f 是 --locustfile 的缩写,效果相同。
- 文件扩展名:
- 必须是 Python 文件(.py),因为 Locust 需要加载其中的 Python 代码。
结论:不一定非叫 locustfile.py,但如果叫这个名字且放在当前目录,可以省去额外的命令行参数,更加方便。
2. 是否必须放在指定的文件目录下?
不一定,但需要与运行命令的当前目录匹配。
- 默认行为:
- Locust 会从你运行命令的当前工作目录(Current Working Directory, CWD)查找 locustfile.py。
- 例如,如果你运行:
cd E:\Devs\backends\python\LoadBalancePro
locust
-
- Locust 会查找 E:\Devs\backends\python\LoadBalancePro\locustfile.py。
- 自定义路径:
- 如果 locustfile.py 不在当前目录,你可以用绝对路径或相对路径指定:
locust --locustfile E:\Devs\backends\python\test\my_locust_test.py
cd E:\Devs\backends\python\test
locust
-
- 只要目标目录下有 locustfile.py,Locust 就能找到。
- 运行时的灵活性:
- 你甚至可以把 Locust 文件放在任意位置,只要告诉 Locust 文件路径即可。例如:
cd C:\Users\YourName
locust --locustfile E:\Devs\backends\python\LoadBalancePro\locustfile.py
- “是不是一定得命名成这样?”
不是,但叫 locustfile.py 是最省事的默认选项。 - “是不是一定得放在指定的文件目录下?”
不是,但默认需要放在运行命令的当前目录,或者通过参数指定路径。
最佳实践建议
- 命名:建议使用 locustfile.py,因为这是社区惯例,别人看到文件名就知道是 Locust 测试脚本。
- 位置:建议放在项目根目录或一个专门的测试目录(例如 tests/),与你的 FastAPI 项目代码放在一起,方便管理和版本控制。
- 验证:运行前可以用 --version 检查 Locust 是否正常工作: