Skip to content

Tamar-Edge-AI/cloud-run-readiness-probe-test

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Cloud Run Readiness Probe Test Demo

这个项目是一个简单的用来验证 Google Cloud Run 的 Load Balancer 在就绪探针(Readiness Probe)失败时的流量切断行为的微服务 Demo。

项目结构

  • main.py: FastAPI 应用源代码。
  • Dockerfile: 用于构建容器镜像。
  • requirements.txt: Python 依赖。

✨ 功能特性

1. 真实 Cloud Run 实例 ID 获取

应用启动时会自动尝试从 Google Cloud Metadata Server 获取真实的 Instance ID

  • Cloud Run 环境:返回真实的 32 位实例 ID。
  • 本地环境:自动降级为 local-dev-[suffix],带有随机后缀,方便本地多进程调试。

快速开始

1. 本地运行 (使用 Python 虚拟环境)

我们推荐使用 Python 虚拟环境来运行项目。

# 创建并激活虚拟环境 (如果尚未创建)
python3 -m venv venv
source venv/bin/activate

# 安装依赖
pip install -r requirements.txt

# 启动应用
# 方式 A: 直接运行 Python 文件
python main.py

# 方式 B: 使用 Uvicorn 命令 (支持热重载)
uvicorn main:app --reload --port 8080

2. 本地运行 (使用 Docker)

# 构建镜像
docker build -t readiness-demo .

# 运行容器
docker run -p 8080:8080 readiness-demo

🧪 Cloud Run 流量切断实验 SOP

这是一个**“破坏实验”。 我们将模拟一个服务实例突然“生病”(就绪探针失败),然后观察 Cloud Run 的负载均衡器(Load Balancer)是否足够聪明,能够迅速切断**发往该实例的流量,保护业务不受影响。

实验原理图解

sequenceDiagram
    participant User as 👤 用户
    participant LB as ⚖️ Cloud Run LB
    participant Instance as 📦 服务实例

    Note over Instance: 🟢 状态: Healthy
    User->>LB: 请求 (GET /)
    LB->>Instance: 转发请求
    Instance-->>LB: 200 OK
    LB-->>User: 200 OK

    Note over Instance: 🤢 突然生病! (装病返回 503)
    
    User->>LB: 请求 (GET /)
    Note right of LB: 🚫 保安: "这人病了"<br/>停止派单 (切断流量)
    LB--xInstance: (流量被切断)
    LB-->>User: 503 Service Unavailable<br/>(或转发给其他健康实例)

    Note over Instance: � 药效过了 (满血复活 200)
    User->>LB: 请求 (GET /)
    LB->>Instance: 恢复转发
    Instance-->>LB: 200 OK
Loading

🛠️ 实验步骤

第一步:确认病人...啊不,服务是健康的 🩺

首先,我们要确保服务正在正常运行。

# 1. 检查业务接口 (应该返回 200)
curl http://localhost:8080/
# ✅ 预期输出: {"status":"ok", "served_by":"..."}

# 2. 检查就绪探针 (应该返回 200)
curl http://localhost:8080/health/ready
# ✅ 预期输出: {"status":"ready", ...}

第二步:注入故障药剂 💉

我们要人为制造一个“事故”。调用这个接口,让当前实例在接下来的 30秒 内假装自己“坏掉了”(Readiness Probe 返回 503)。

curl -X POST "http://localhost:8080/admin/fail?duration=30"

现象预告:这就好比告诉门口的保安(Load Balancer):“我肚疼,别给我派活了!”

第三步:见证流量切断 🚫

这时候,如果我们直接问这个实例“你还好吗?”,它会说“不好”。

curl -v http://localhost:8080/health/ready
# ⚠️ 预期输出: HTTP/1.1 503 Service Unavailable

关键点来了: 在 Cloud Run 的真实环境中,一旦 Load Balancer 收到这个 503 信号,它就会立刻停止把外部的用户请求转发给这个实例。 如果这是唯一的实例,用户会看到 503;如果有多个实例,用户流量会被自动导向其他健康的实例,实现无感故障转移

第四步:自动康复 🩹

耐心等待 30 秒(就像等待药效过去)。再次检查,服务应该已经生龙活虎了。

curl -v http://localhost:8080/health/ready
# ✅ 预期输出: HTTP/1.1 200 OK

🐢 Cloud Run 探针超时实验 SOP

除了直接“装病”(503),另一种常见的故障是**“反应迟钝”**。 我们将模拟服务响应变慢,导致 Readiness Probe 超时。

实验原理图解

sequenceDiagram
    participant User as 👤 用户
    participant LB as ⚖️ Cloud Run LB
    participant Instance as 📦 服务实例

    Note over Instance: 🟢 状态: Healthy
    User->>LB: 请求 (GET /)
    LB->>Instance: 转发请求
    Instance-->>LB: 200 OK

    Note over Instance: 💤 喝了安眠药! (响应延迟 > Timeout)
    
    LB->>Instance: 发送探针 (GET /health/ready)
    Note right of LB: ⏱️ LB 等得花都谢了 (Timeout)<br/>标记实例为 Unhealthy
    LB--xInstance: (流量被切断)

    User->>LB: 请求 (GET /)
    LB-->>User: 503 Service Unavailable<br/>(或转发给其他健康实例)

    Note over Instance: 🟢 药劲过了 (恢复秒回)
    LB->>Instance: 发送探针
    Instance-->>LB: 200 OK
    LB->>Instance: 恢复业务流量转发
Loading

🛠️ 实验步骤

第一步:给实例喝“安眠药” 🧪

我们要让这位实例变得反应迟钝。调用接口,强制它在接下来的 30秒 内,每次回答 Readiness Probe 都要思考 5秒 人生。

# 模拟延迟 5秒,持续 30秒
curl -X POST "http://localhost:8080/admin/delay?delay=5&duration=30"

现象预告:这就像门口的保安(LB)问:“在吗?”,实例半天不回话(超时),保安只能当它不在了。

第二步:见证“被忽视”的代价 ⏱️

如果 Cloud Run 上配置的 Readiness Probe Timeout 设置为 1秒(默认值通常较小),那么 5秒 的延迟对保安来说就是**“失联”**。

保安会毫不留情地切断发往该实例的流量。

第三步:自然苏醒 ☀️

等待 30秒后,“安眠药”失效,实例恢复秒回状态,保安确认它又活过来了,流量恢复。


📝 日志观测 (Observability)

为了方便排查问题,应用已经在关键节点添加了结构化日志。您可以在 Cloud Run 的 Logs 标签页或使用 Cloud Logging 查询。

关键日志特征

场景 日志级别 关键词 说明
应用启动 INFO 🚀 应用启动 包含真实的 Instance ID
故障注入 WARNING 💣 管理操作 记录 503 注入操作
延迟注入 WARNING 🐢 管理操作 记录延迟注入操作
探针失败 WARNING 🚫 就绪探针 记录当前正在返回 503
探针延迟 INFO 🐢 就绪探针 记录当前正在 Sleep

🔍 Cloud Logging 查询示例 (过滤某个实例的异常)

resource.type="cloud_run_revision"
textPayload:"Readiness Probe"
jsonPayload.instanceId="YOUR_INSTANCE_ID"

通过日志,您可以精确对应的知道是哪个实例在什么时间点开始由于什么原因被标记为了不健康。

About

测试Cloud Run的就绪探针行为

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Languages

  • Python 71.7%
  • Shell 19.5%
  • Dockerfile 8.8%