微信扫码
添加专属顾问
使用Nginx对LLM服务进行负载均衡,实现高并发场景下的性能优化。 核心内容: 1. Nginx作为高性能Web服务器的简介及其特点 2. Nginx的安装步骤及配置文件编辑 3. 负载均衡算法介绍及测试负载均衡的chat服务实例
需要将请求分发到不同的节点进行处理,让每个节点的负载在合适的水平,这就是负载均衡。
nginx 是一款开源的、高性能的 Web 服务器,同时也广泛用作 反向代理服务器、负载均衡器 和 HTTP 缓存。 它的设计目标是解决传统服务器(如 Apache)在高并发场景下的性能瓶颈,现已成为全球最流行的 Web 服务器之一。
特点:
高性能:基于事件驱动的异步架构,单机支持数万并发连接。
轻量级:内存占用低,配置简单。
算法灵活:轮询(Round Robin)、加权轮询(Weighted)、IP Hash、最少连接(Least Connections)等。
以 ubuntu 为例
sudo apt install nginx
编辑配置文件 /etc/nginx/nginx.conf,向 http 添加以下内容
http {
upstream backend {
least_conn; # 均衡算法
server 127.0.0.1:8001; # 后端服务1
server 127.0.0.1:8002; # 后端服务2
}
server {
listen 80;
location / {
proxy_pass http://backend;
}
}
log_format upstream_log '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'to: $upstream_addr';
access_log /var/log/nginx/upstream.log upstream_log;
}
完整配置如下:
# cat /etc/nginx/nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# Logging Settings
##
log_format upstream_log '$remote_addr:$remote_port $request_uri - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'to: $upstream_addr';
access_log /var/log/nginx/access.log upstream_log;
error_log /var/log/nginx/error.log;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
##
# Gzip Settings
##
gzip on;
# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
##
# Upstream Servers
##
upstream backend {
least_conn;
server 127.0.0.1:8001; # 后端服务1
server 127.0.0.1:8002; # 后端服务2
}
##
# Server Blocks
##
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://backend;
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_http_version 1.1; # 确保使用 HTTP/1.1 <button class="citation-flag" data-index="7">
#proxy_set_header Connection '';
}
}
add_header X-Upstream $upstream_addr always; # 在响应头中暴露后端地址
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
#mail {
# # See sample authentication script at:
# # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
# # auth_http localhost/auth.php;
# # pop3_capabilities "TOP" "USER";
# # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
# server {
# listen localhost:110;
# protocol pop3;
# proxy on;
# }
#
# server {
# listen localhost:143;
# protocol imap;
# proxy on;
# }
#}
编写完配置,systemctl reload nginx 重启,nginx -t 确认配置ok
以上配置中 least_conn 是均衡算法,可以有多种算法可选
upstream backend {
server 127.0.0.1:8001 weight=3; # 60%的请求
server 127.0.0.1:8002 weight=2; # 40%的请求
}
upstream backend {
least_conn;
server 127.0.0.1:8001;
server 127.0.0.1:8002;
}
upstream backend {
ip_hash;
server 127.0.0.1:8001;
server 127.0.0.1:8002;
}
❝一致性哈希通过哈希环和虚拟节点机制,有效解决了传统哈希算法在动态环境下的数据迁移和负载不均问题。 其核心在于减少节点变动的影响范围,并利用虚拟节点实现数据分布的平衡性,是分布式系统中实现高可用和可扩展性的关键技术
upstream backend {
hash $request_uri consistent; # 按请求URI分配
server 127.0.0.1:8001;
server 127.0.0.1:8002;
}
所有算法均可配合权重使用:
server 127.0.0.1:8001 weight=5 max_fails=3 fail_timeout=30s;
开启两个http服务(端口 8001,8002),使用python脚本 server.py 启动
# server.py
from http.server import BaseHTTPRequestHandler, HTTPServer
import socket
class DebugRequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
# 打印客户端信息
client_ip, client_port = self.client_address
print(f"\n--- 新请求 @{self.server.server_port} ---")
print(f"[客户端] {client_ip}:{client_port}")
print(f"[方法] {self.command}")
print(f"[路径] {self.path}")
print(f"[请求头] {self.headers}")
# 返回响应
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.end_headers()
self.wfile.write(f"响应来自: {self.server.server_port}".encode())
def do_POST(self):
# 处理 POST 请求
content_length = int(self.headers["Content-Length"])
post_data = self.rfile.read(content_length).decode("utf-8")
print(f"\n--- POST 请求 @{self.server.server_port} ---")
print(f"[数据] {post_data}")
self.do_GET() # 复用 GET 响应逻辑
def run(server_class=HTTPServer, handler_class=DebugRequestHandler, port=8001):
server_address = ("0.0.0.0", port) # 绑定到所有接口
httpd = server_class(server_address, handler_class)
print(f"服务启动于 0.0.0.0:{port}...")
httpd.serve_forever()
if __name__ == "__main__":
# 启动两个服务实例(分别在 8001 和 8002 端口)
import threading
threading.Thread(target=run, kwargs={"port": 8001}).start()
threading.Thread(target=run, kwargs={"port": 8002}).start()
python3 server.py
压力测试
apt install apache2-utils
ab -n 1000 -c 10 http://localhost/
ab 是 Apache Bench 的缩写,它是 Apache HTTP 服务器项目中的一个性能测试工具,用于对 Web 服务器发起压力测试。
命令分解
ab**:工具名称(Apache Bench)。-n 1000**:总请求数为 1000(-n 表示 number of requests)。-c 10**:并发用户数为 10(-c 表示 concurrency,即同时发送的请求数)。http://localhost/**:目标测试地址(可以是本地服务或远程 URL)。模拟 10 个并发用户 同时访问 http://localhost/,每个用户连续发送请求,直到总请求数达到 1000。通过该命令可以测试:
示例输出解读
运行命令后,输出结果示例如下:
This is ApacheBench, Version 2.3 <$Revision: 1879490 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests
Server Software: nginx/1.18.0
Server Hostname: localhost
Server Port: 80
Document Path: /
Document Length: 18 bytes
Concurrency Level: 10
Time taken for tests: 1.201 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 178000 bytes
HTML transferred: 18000 bytes
Requests per second: 832.30 [#/sec] (mean)
Time per request: 12.015 [ms] (mean)
Time per request: 1.201 [ms] (mean, across all concurrent requests)
Transfer rate: 144.68 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.0 0 1
Processing: 2 12 1.9 12 26
Waiting: 1 12 1.9 12 25
Total: 2 12 1.9 12 26
Percentage of the requests served within a certain time (ms)
50% 12
66% 12
75% 13
80% 13
90% 14
95% 15
98% 16
99% 18
100% 26 (longest request)
关键指标
Requests per second:813.01 [#/sec]
表示服务器每秒能处理 832 个请求(吞吐量越高,性能越好)。
Time per request:
12.015 [ms] (mean):每个请求的平均耗时(从用户角度看)。1.201 [ms] (mean, across all concurrent requests):服务器平均处理每个请求的时间。Connection Times:
显示连接、处理、等待时间的分布(单位:毫秒)。
Percentage served within a certain time:
响应时间的分布情况(如 90% 的请求在 14ms 内完成)。
服务端的日志输出:我们去统计下两个服务端的被请求次数:
tail -f /var/log/nginx/access.log
127.0.0.1:48878 / - - [02/Mar/2025:21:10:11 +0800] "GET / HTTP/1.0" 200 18 "-" "ApacheBench/2.3" "-" to: 127.0.0.1:8001
127.0.0.1:48882 / - - [02/Mar/2025:21:10:11 +0800] "GET / HTTP/1.0" 200 18 "-" "ApacheBench/2.3" "-" to: 127.0.0.1:8002
127.0.0.1:48892 / - - [02/Mar/2025:21:10:11 +0800] "GET / HTTP/1.0" 200 18 "-" "ApacheBench/2.3" "-" to: 127.0.0.1:8001
127.0.0.1:48904 / - - [02/Mar/2025:21:10:11 +0800] "GET / HTTP/1.0" 200 18 "-" "ApacheBench/2.3" "-" to: 127.0.0.1:8002
root@MichaelMing:~# cat /var/log/nginx/access.log | tail -n 1000 | grep ":8001" | wc -l
506
root@MichaelMing:~# cat /var/log/nginx/access.log | tail -n 1000 | grep ":8002" | wc -l
494
或者
root@MichaelMing:~# awk '{print $NF}' /var/log/nginx/access.log | sort | uniq -c
300 "ApacheBench/2.3"
3 "curl/7.81.0"
93576 -
984 127.0.0.1:8001
1018 127.0.0.1:8002
我们去查看两个端口号,发现两个端口的服务被请求的次数是基本均衡的(506/494),Nginx起到了负载均衡的作用
假设 MichaelAI有两个 api 接口 chat、completions
from http.server import BaseHTTPRequestHandler, HTTPServer
import json
from urllib.parse import urlparse, parse_qs
from datetime import datetime
class MultiAPIHandler(BaseHTTPRequestHandler):
def send_json_response(self, data, status=200):
self.send_response(status)
self.send_header("Content-type", "application/json")
self.end_headers()
self.wfile.write(json.dumps(data).encode("utf-8"))
def do_POST(self):
# 统一入口路由分发
parsed_path = urlparse(self.path)
path = parsed_path.path
try:
content_length = int(self.headers["Content-Length"])
post_data = self.rfile.read(content_length).decode("utf-8")
print(f"\n--- {path} 请求 @{self.server.server_port} ---")
print(f"[客户端] {self.client_address[0]}:{self.client_address[1]}")
print(f"[数据] {post_data}")
if path == "/chat":
self.handle_chat(post_data)
elif path == "/completions":
self.handle_completions(post_data)
else:
self.send_error(404, "API not found")
except Exception as e:
self.send_json_response({
"error": str(e),
"server": self.server.server_port,
"timestamp": datetime.now().isoformat()
}, 400)
def handle_chat(self, data):
# 模拟对话接口处理
try:
input_data = json.loads(data)
message = input_data.get("message", "")
response = {
"original": message,
"response": f"Processed by chat API: {message.upper()}",
"server": self.server.server_port,
"timestamp": datetime.now().isoformat()
}
self.send_json_response(response)
except json.JSONDecodeError:
raise ValueError("Invalid JSON format")
def handle_completions(self, data):
# 文本补全接口
response = {
"completions": [
{"text": f"Completion 1: {data[:5]}...", "index": 0},
{"text": f"Completion 2: {data[-5:]}...", "index": 1}
],
"server": self.server.server_port,
"timestamp": datetime.now().isoformat()
}
self.send_json_response(response)
def run(server_class=HTTPServer, handler_class=MultiAPIHandler, port=8001):
server_address = ("0.0.0.0", port)
httpd = server_class(server_address, handler_class)
print(f"多API服务启动于 0.0.0.0:{port}...")
httpd.serve_forever()
if __name__ == "__main__":
import threading
# 启动两个服务实例
threading.Thread(target=run, kwargs={"port": 8001}).start()
threading.Thread(target=run, kwargs={"port": 8002}).start()
❝chat_data.json 示例: {"message": "Hello, this is a test message"}
ab -n 100 -c 10 -T "application/json" -p json_data \
http://localhost:8001/chat
服务端日志
--- /chat 请求 @8001 ---
[客户端] 127.0.0.1:54724
[数据] {"message": "Hello, this is a test message"}
127.0.0.1 - - [02/Mar/2025 22:41:22] "POST /chat HTTP/1.0" 200 -
text.txt 示例:
你好,我是Michael阿明开发的智能助手!
ab -n 10000 -c 100 -T "text/plain" -p text.txt \
http://localhost:8002/completions
服务端日志
--- /completions 请求 @8002 ---
[客户端] 127.0.0.1:47246
[数据] 你好,我是Michael阿明开发的智能助手!
127.0.0.1 - - [02/Mar/2025 22:49:26] "POST /completions HTTP/1.0" 200
# 同时压测两个接口
echo "chat接口压测结果:" && \
ab -n 500 -c 50 -T "application/json" -p json_data http://localhost:80/chat && \
echo "completions接口压测结果:" && \
ab -n 500 -c 50 -T "text/plain" -p text.txt http://localhost:80/completions
completions 接口调用分布:两个机器基本接近
root@MichaelMing:~# cat /var/log/nginx/access.log | tail -n 20000 | grep "completions" | grep 8001 | wc -l
747
root@MichaelMing:~# cat /var/log/nginx/access.log | tail -n 20000 | grep "completions" | grep 8002 | wc -l
755
import requests
import asyncio
import aiohttp
# 同步客户端(基于requests)
class SyncAPIClient:
def __init__(self, base_url):
self.base_url = base_url
def call_chat(self, message):
url = f"{self.base_url}/chat"
data = {"message": message}
response = requests.post(url, json=data)
return response.json()
def call_completions(self, text):
url = f"{self.base_url}/completions"
response = requests.post(url, data=text)
return response.json()
# 异步客户端(基于aiohttp)
class AsyncAPIClient:
def __init__(self, base_url):
self.base_url = base_url
async def call_chat(self, message):
url = f"{self.base_url}/chat"
data = {"message": message}
async with aiohttp.ClientSession() as session:
async with session.post(url, json=data) as response:
return await response.json()
async def call_completions(self, text):
url = f"{self.base_url}/completions"
async with aiohttp.ClientSession() as session:
async with session.post(url, data=text) as response:
return await response.json()
# 同步调用示例
sync_client = SyncAPIClient("http://localhost")
chat_response = sync_client.call_chat("Hello, sync chat!")
print("Chat响应:", chat_response)
completion_response = sync_client.call_completions("test text")
print("Completions响应:", completion_response)
# 异步调用示例
async def main():
async_client = AsyncAPIClient("http://localhost")
# 并发调用两个接口
chat_task = asyncio.create_task(async_client.call_chat("Hello, async chat!"))
completion_task = asyncio.create_task(async_client.call_completions("async test text"))
results = await asyncio.gather(chat_task, completion_task)
print("异步Chat响应:", results[0])
print("异步Completions响应:", results[1])
asyncio.run(main())
输出:
root@MichaelMing:~# python3 /mnt/d/opt/client.py
Chat响应: {'original': 'Hello, sync chat!', 'response': 'Processed by chat API: HELLO, SYNC CHAT!', 'server': 8001, 'timestamp': '2025-03-02T23:11:54.426626'}
Completions响应: {'completions': [{'text': 'Completion 1: test ...', 'index': 0}, {'text': 'Completion 2: text...', 'index': 1}], 'server': 8002, 'timestamp': '2025-03-02T23:11:54.430562'}
异步Chat响应: {'original': 'Hello, async chat!', 'response': 'Processed by chat API: HELLO, ASYNC CHAT!', 'server': 8001, 'timestamp': '2025-03-02T23:11:54.444508'}
异步Completions响应: {'completions': [{'text': 'Completion 1: async...', 'index': 0}, {'text': 'Completion 2: text...', 'index': 1}], 'server': 8002, 'timestamp': '2025-03-02T23:11:54.444973'}
用代码进行压力测试
# 并发压测示例(使用异步客户端)
async def stress_test():
client = AsyncAPIClient("http://localhost")
tasks = []
for _ in range(100):
tasks.append(client.call_chat("test message"))
tasks.append(client.call_completions("test text"))
responses = await asyncio.gather(*tasks)
print(f"成功处理 {len(responses)} 个请求")
asyncio.run(stress_test())
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业
2026-06-30
我把 Codex 装进了 Pi 5 Max:一块 Android 开发板,开始自己参与 AI 相框开发
2026-06-24
讯飞办公本用一键式龙虾部署,终结“只记不查”的资产浪费
2026-06-22
我把吃灰的 Kindle 用起来了:给 AI 桌宠加一块电子墨水屏
2026-05-31
英特尔AI PC专区:专治本地模型跑不动、智能体做不出、新模型不会用
2026-05-18
Android 迎来 Gemini-Intelligence,手机要开始替你干活了
2026-05-18
OpenAI秘密矩阵曝光!你的所有设备,被Codex连成一台超级电脑
2026-05-15
苹果不卷AI了:iOS 27要让第三方模型"竞标"进系统
2026-05-13
安卓彻底变了!Gemini接管所有屏幕,苹果连影子都没追上
2026-04-07
2026-04-02
2026-04-11
2026-04-27
2026-04-21
2026-04-20
2026-04-12
2026-05-09
2026-05-13
2026-05-07
欢迎您使用【53AI 官方网站】(以下简称“本网站”或“我们”)。本《会员服务协议》(以下简称“本协议”)是您(以下简称“会员”或“用户”)与【深圳市博思协创网络科技有限公司】之间关于注册、登录及使用本网站会员服务所订立的法律协议。
在您注册或登录前,请务必审慎阅读、充分理解各条款内容,特别是免除或限制责任的条款、知识产权条款、争议解决条款等。此类条款将以加粗形式提示您注意。 当您通过微信公众号授权、手机验证码验证或其他方式成功登录本网站时,即视为您已完全理解并同意接受本协议的全部内容。
一、 定义
本网站:指由【深圳市博思协创网络科技有限公司】运营的,域名为【53ai.com】的网站及相关移动端页面。
会员服务:指本网站向注册会员提供的知识库文章查阅、内容检索及其他相关增值服务。
知识库内容:指本网站发布的包括但不限于文字、图表、数据、研究报告、行业分析等数字化内容资源。
二、 账号注册与登录
登录方式:本网站支持以下登录方式,您可根据实际情况选择:
微信公众号授权登录:您同意将您的微信OpenID信息授权给本网站,用于创建或关联会员账号。
手机验证码登录:您需提供真实有效的手机号码,并通过短信验证码完成身份验证与登录/注册。
账号安全:您的账号仅限您本人使用,禁止赠与、借用、租用、转让或售卖。因您保管不善导致的账号被盗、密码泄露等损失,由您自行承担。
实名认证:根据相关法律法规要求,我们可能要求您在特定功能下完成实名认证。如您拒绝提供,可能无法使用部分或全部服务。
未成年人保护:若您未满18周岁,请在法定监护人的陪同下阅读本协议,并在征得监护人同意后使用本服务。
三、 服务内容与规范
知识库查阅权限:会员登录后,有权按照其会员等级对应的权限范围,在线浏览、检索本网站知识库中的相关文章及内容。
服务变更:我们有权根据业务发展需要,调整、变更或终止部分服务内容,并将以网站公告、公众号消息等方式提前通知。
禁止行为:您在使用服务时不得实施以下行为:
利用技术手段批量爬取、下载、转存知识库内容;
将知识库内容用于商业目的或未经授权地向第三方传播;
干扰本网站正常运行或侵犯其他用户合法权益;
发布违法违规信息或从事违反公序良俗的活动。
四、 知识产权声明
权利归属:本网站知识库中的排版设计、软件代码等内容的知识产权均归【公司全称】或原权利人所有,受《中华人民共和国著作权法》等法律保护。
有限许可:本网站授予会员一项非独占、不可转让、不可转授权的普通许可,仅限于个人学习、研究之目的在线查阅知识库内容。
侵权追责:未经书面许可,任何单位或个人不得以任何形式复制、转载、摘编、镜像、汇编或以其他方式使用上述内容。一经发现,我们保留追究其法律责任的权利。
五、 个人信息保护
我们重视对您个人信息的保护。关于我们如何收集、使用、存储和保护您的个人信息,请单独阅读 《隐私政策》。
您通过微信公众号授权或手机号验证所提供的信息,我们将严格按照《个人信息保护法》的规定处理,仅用于身份识别、服务提供及安全验证等必要用途。
您可以随时通过网站设置或联系客服行使查阅、更正、删除个人信息及撤回授权同意的权利。
六、 免责声明
内容准确性:知识库内容仅供参考,不构成专业建议。我们不对其完整性、准确性、时效性作任何明示或暗示的保证,您应自行判断并承担使用风险。
不可抗力:因自然灾害、政策法规变化、网络故障、第三方平台接口异常(如微信接口维护、运营商短信通道故障)等不可抗力导致的服务中断或延迟,我们不承担违约责任。
第三方链接:本网站可能包含指向第三方网站的链接,该等网站的内容和服务不受我们控制,请您自行甄别风险。
七、 违约责任
如您违反本协议约定,我们有权视情节采取警告、限制功能、暂停服务、注销账号等措施,并保留要求赔偿损失的权利。
如因您的违约行为导致我们遭受行政处罚、第三方索赔或商誉损失,您应承担全部赔偿责任(包括但不限于罚款、赔偿金、律师费、公证费等)。
八、 法律适用与争议解决
本协议的订立、执行和解释均适用中华人民共和国大陆地区法律。
因本协议产生的或与本协议有关的任何争议,双方应友好协商解决;协商不成的,任何一方均可向【公司所在地】有管辖权的人民法院提起诉讼。
九、 其他
本协议构成双方就本服务达成的完整协议,取代此前任何口头或书面约定。
本协议任一条款被认定为无效或不可执行的,不影响其他条款的效力。
我们对本协议享有最终解释权,并在法律允许的范围内保留随时修改的权利。修改后的协议一经公布即生效,继续使用服务即视为同意修订内容。