---
url: /courses/cloud-platform-build-management/lab-08/index.md
---
# 实训 08：Nginx 双后端负载均衡与故障恢复

所有操作限定在 `~/cloud-course/lab-08`，Compose 项目名为 `cloud-course-lab-08`，入口只绑定 `127.0.0.1:18008`。

## 一、目标与证据

* 三项服务健康，`nginx -t` 通过；
* 负载均衡器可以直连两个后端；
* 连续请求中出现 `backend-a`、`backend-b`；
* 停止 `backend-b` 后入口继续返回 `backend-a`；
* 日志记录上游失败，恢复后两个标识重新出现；
* 自动验收通过，端口和项目清理完成。

## 二、安全边界

* 只停止 `cloud-course-lab-08` 的 `backend-b`。
* 不停止系统 Nginx、全部容器或其他 Compose 项目。
* 不把 18008 绑定到 `0.0.0.0`，不修改防火墙与安全组。
* 日志只截取本次请求相关行，并遮盖内部地址。

## 三、准备与静态检查

```bash
[ECS] mkdir -p ~/cloud-course/lab-08
[ECS] cd ~/cloud-course/lab-08
[ECS] docker compose config --services
[ECS] docker compose config --quiet
```

截图 1：三个服务名和配置检查。\
说明：静态检查还不能证明什么？

## 四、启动前预检

```bash
[ECS] free -h
[ECS] docker compose ls
[ECS] ss -lnt 'sport = :18008'
```

18008 被占用时停止，不自行改成公网端口。

## 五、启动并验证后端

```bash
[ECS] docker compose up -d
[ECS] docker compose ps
[ECS] docker compose exec -T lb nginx -t
```

分别直连：

```bash
[ECS] docker compose exec -T lb wget -qO- http://backend-a/
[ECS] docker compose exec -T lb wget -qO- http://backend-b/
```

截图 2：三项服务端口、配置检查和后端直连。

## 六、观察轮询

```bash
[ECS] for i in 1 2 3 4 5 6; do
  printf 'request-%s -> ' "$i"
  curl --max-time 8 -sS http://127.0.0.1:18008/ | grep -o 'backend-[ab]'
done
```

截图 3：两个后端标识均出现。\
说明：为什么一次请求不能证明负载均衡？

## 七、单后端故障与恢复

```bash
[ECS] docker compose stop backend-b
[ECS] docker compose ps
```

```bash
[ECS] for i in 1 2 3 4; do
  curl --max-time 8 -sS http://127.0.0.1:18008/ | grep -o 'backend-[ab]'
done
```

`--max-time 8` 限制客户端总等待时间；课程配置还用 `proxy_connect_timeout 2s` 和 `proxy_next_upstream_timeout 6s` 约束后端连接与重试，避免第一条故障请求长时间挂起。

```bash
[ECS] docker compose logs --since 30s --tail 20 lb
```

截图 4：`backend-b` 停止、入口仍返回 `backend-a` 和最近日志。

恢复：

```bash
[ECS] docker compose start backend-b
[ECS] docker compose ps
```

等待健康并超过 `fail_timeout` 后，重新执行六次请求。截图 5：恢复后两个标识再次出现。

## 八、验收与清理

```bash
[ECS] bash verify.sh
[ECS] docker compose down
[ECS] ss -lnt 'sport = :18008'
```

清理后端口查询应无输出。最终只上传：

```txt
班级_学号_姓名_第08次课_Nginx负载均衡报告.docx
```
