Docker + Nginx 实现反向代理、负载均衡

具体实现步骤:实现 web 应用,可以是 java 或者是其它,为了方便,我这里选择 Python Flask,创建多个后端服务实例(比如 Flask 应用),一个 Nginx 容器作为负载均衡器

项目目录结构
load-balance-demo/
├── app/
│   ├── app.py           # Flask 应用代码
│   └── Dockerfile       # Flask 服务 Dockerfile
├── nginx/
│   ├── nginx.conf       # Nginx 配置文件
│   └── Dockerfile       # Nginx Dockerfile
└── docker-compose.yml   # Docker Compose 配置文件
编写后端服务代码,app/app.py
from flask import Flask
import os
import logging

app = Flask(__name__)
// 添加日志 好进行请求检索
logging.basicConfig(level=logging.INFO)

@app.route('/')
def hello():
    hostname = os.getenv('HOSTNAME', 'unknown')
    logging.info(f"Request handled by {hostname}")
    return f"Hello from {hostname}!\n"

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)
app/Dockerfile
FROM python:3.9-slim
WORKDIR /app
COPY app.py .
RUN pip install flask
ENV HOSTNAME=unknown
EXPOSE 5000
CMD ["python", "app.py"]
配置 Nginx,nginx/nginx.conf
upstream backend {
    least_conn;  # 使用最少连接数算法实现负载均衡
    server app1:5000;
    server app2:5000;
    server app3:5000;
}
server {
    listen 80;
    location / {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
nginx/Dockerfile
FROM nginx:latest
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
配置 Docker Compose,docker-compose.yml
version: "3"
services:
  app1:
    build: ./app
    environment:
      - HOSTNAME=app1
    expose:
      - "5000"

  app2:
    build: ./app
    environment:
      - HOSTNAME=app2
    expose:
      - "5000"

  app3:
    build: ./app
    environment:
      - HOSTNAME=app3
    expose:
      - "5000"

  nginx:
    build: ./nginx
    ports:
      - "80:80"
    depends_on:
      - app1
      - app2
      - app3
启动服务:docker-compose up --build -d
查看 docker 状态 docker ps

截屏2025-02-26 10.04.00.png

模拟发送并发请求

截屏2025-02-26 10.24.47.png

收集日志

截屏2025-02-26 10.28.48.png
可以看到还是很均衡的,符合 least_conn

改为轮训

截屏2025-02-26 10.48.44.png
ip hash 负载均衡需要多个客户端,感兴趣自己尝试

upstream backend {
    ip_hash;  # 使用 ip_hash 策略
    server app1:5000;
    server app2:5000;
    server app3:5000;
}

权重负载均衡

upstream backend {
    server app1:5000 weight=3;  # app1 权重为 3
    server app2:5000 weight=2;  # app2 权重为 2
    server app3:5000 weight=1;  # app3 权重为 1
}