一文帮你彻底弄清楚【负载均衡】的概念、配通俗易懂案例演示讲解(Python/Nginx/FastAPI).

1. 负载均衡的概念

负载均衡(Load Balancing)是一种技术,用于将网络流量或计算任务合理地分配到多个服务器、进程或资源上,以避免单一节点过载,提高系统的性能、可靠性和可用性。它通常用于分布式系统或高并发场景。

简单来说,负载均衡就像一个“交通指挥员”,负责把请求分发到不同的“工人”(服务器),确保每个工人不会太忙或太闲。


2. 负载均衡的作用

  • 提高性能:通过分担负载,避免单台服务器压力过大,加快响应速度。
  • 增强可靠性:如果一台服务器宕机,负载均衡器可以将流量转发到其他可用服务器,避免服务中断。
  • 扩展性:当流量增加时,可以方便地添加更多服务器,负载均衡器会自动分配任务。
  • 优化资源利用:让每台服务器的资源(CPU、内存等)都被充分利用,避免浪费。

3. 通俗解释

想象一下,你去一家餐厅吃饭,门口有个服务员。如果所有顾客都挤到一张桌子旁点餐,那这张桌子肯定忙不过来,其他桌子却闲着。服务员要是聪明点,就会把顾客均匀分到不同的桌子,这样大家都能快速吃上饭,不会有人等太久。这里的服务员就是“负载均衡器”,桌子就是“服务器”。

在互联网中,负载均衡器把用户的请求(比如打开网页)分到不同的服务器上,确保网站不会因为人太多而崩溃。

 

 

 Python 代码举例

下面我将为你提供一个真实生产环境的负载均衡示例,使用 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)
启动多个实例: 在不同的命令行窗口中运行以下命令,模拟 3 个后端服务器:
python app.py 8000  # 实例 1
python app.py 8001  # 实例 2
python app.py 8002  # 实例 3
每个窗口启动一个实例,分别监听 8000、8001 和 8002 端口。

 
在浏览器中分别输入
https://127.0.0.1:8000
https://127.0.0.1:8001 
https://127.0.0.1:8002
FastAPI页面如下:
这里只展示8000端口,其他2个端口也类似,不再赘述。

 

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(如果需要):
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

  1. 打开 CMD,进入包含 locustfile.py 的目录。
  2. 启动 Locust:【注意这里要把 locustfile.py这个文件放到虚拟环境的Scripts目录下,具体见后面追问

 

接下来可以进入到上图所示的目录中,执行

locust

或者把上面的路径添加到环境变量中,

然后在Pycharm中执行如下命令,也会有类似效果。

python -m locust

点击Enter键,或者打开浏览器,访问 http://localhost:8089,就会进入 Locust 的 Web 界面。

 配置参数:

  1. Number of users:50(模拟 50 个并发用户)。
  2. Spawn rate:5(每秒新增 5 个用户)。
  3. Host:http://localhost。
  4. 点击 "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. 完整工作流程

  1. 用户(Locust)发送大量翻译请求到 http://localhost/translate。
  2. Nginx 监听 80 端口,收到请求后按轮询方式分发到 8000、8001 或 8002。
  3. FastAPI 实例处理请求,返回翻译结果。
  4. Nginx 将结果返回给 Locust,用户看到 "Hello, World"。

通过这种方式,你可以在 Windows 10 单机上模拟出高并发的负载均衡场景。

至此,就完成了负载均衡的整个流程。

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

 

 

附报错及注意点-:

这里要注意:

如果端口被占用,用
netstat -aon | findstr :8000 
检查占用进程,杀掉(taskkill /PID 进程号 /F)后重启。

 检查防火墙

  • Windows 防火墙可能阻止了 80 端口。
  • 测试:
telnet localhost 80
如果连接失败:防火墙或 Nginx 未启动。

解决方案

  • 临时关闭防火墙测试:
netsh advfirewall set allprofiles state off
或添加规则允许 80 端口:
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 指定:
locust --locustfile my_locust_test.py
或者用 Python 模块方式运行:
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
结论不一定非得放在特定目录,但必须让 Locust 知道文件在哪里,默认是当前目录下的 locustfile.py。
 
回答追问:
  • “是不是一定得命名成这样?”
    不是,但叫 locustfile.py 是最省事的默认选项。
  • “是不是一定得放在指定的文件目录下?”
    不是,但默认需要放在运行命令的当前目录,或者通过参数指定路径。

最佳实践建议

  • 命名:建议使用 locustfile.py,因为这是社区惯例,别人看到文件名就知道是 Locust 测试脚本。
  • 位置:建议放在项目根目录或一个专门的测试目录(例如 tests/),与你的 FastAPI 项目代码放在一起,方便管理和版本控制。
  • 验证:运行前可以用 --version 检查 Locust 是否正常工作:

 

posted @ 2025-03-09 18:37  AlphaGeek  阅读(587)  评论(0)    收藏  举报