You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GitHub Actions工作流中本地服务器连接被拒绝问题求助

解决GitHub Actions中后台启动服务器后「连接被拒绝」的问题

核心问题分析

  • 后台启动服务器后立刻执行curl,此时服务器尚未完成端口绑定和服务初始化,导致连接被拒绝。
  • 前台启动服务器会占用当前shell会话,后续步骤无法执行,因为GitHub Actions会一直等待该步骤的命令结束。

解决方案步骤

1. 添加启动等待逻辑

在后台启动服务器后,通过循环检测连接状态,直到服务就绪或超时。这样能避免因服务未完全启动导致的连接失败。

修改你的工作流中「Run server in background」步骤为:

- name: Run server in background and test
  run: |
    python -V
    # 后台启动服务器
    python -m http.server 3000 &> /dev/null &
    # 等待服务器就绪,最多尝试10次,每次间隔1秒
    MAX_ATTEMPTS=10
    ATTEMPT=1
    while [ $ATTEMPT -le $MAX_ATTEMPTS ]; do
      if curl -s http://localhost:3000 > /dev/null; then
        echo "✅ 服务器已成功启动"
        break
      fi
      echo "⏳ 等待服务器启动... 第 $ATTEMPT/$MAX_ATTEMPTS 次尝试"
      sleep 1
      ATTEMPT=$((ATTEMPT+1))
    done
    # 最终测试连接
    curl http://localhost:3000
    # 如果超时仍未启动,终止工作流
    if [ $ATTEMPT -gt $MAX_ATTEMPTS ]; then
      echo "❌ 服务器启动超时"
      exit 1
    fi

2. 针对FastAPI + Gunicorn的适配

如果是FastAPI项目,建议添加一个健康检查端点,方便准确判断服务状态:

from fastapi import FastAPI

app = FastAPI()

@app.get("/health")
async def health_check():
    return {"status": "ok"}

然后在工作流中启动服务并等待健康检查通过:

- name: Start FastAPI service and run tests
  run: |
    pip install -r requirements.txt
    # 后台启动Gunicorn服务
    gunicorn main:app -w 2 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000 &> /dev/null &
    # 等待健康检查就绪
    MAX_ATTEMPTS=15
    ATTEMPT=1
    while [ $ATTEMPT -le $MAX_ATTEMPTS ]; do
      if curl -s http://localhost:8000/health | grep -q "ok"; then
        echo "✅ FastAPI服务已就绪"
        break
      fi
      echo "⏳ 等待服务启动... 第 $ATTEMPT/$MAX_ATTEMPTS 次尝试"
      sleep 1
      ATTEMPT=$((ATTEMPT+1))
    done
    # 执行集成测试
    pytest tests/integration/
    # 超时处理
    if [ $ATTEMPT -gt $MAX_ATTEMPTS ]; then
      echo "❌ 服务启动超时"
      exit 1
    fi

3. 关于Docker启动的注意事项

如果使用Docker容器启动服务,除了等待容器启动,还需要等待容器内的服务就绪:

- name: Start Docker container and test
  run: |
    docker build -t my-fastapi-app .
    docker run -d -p 8000:8000 --name fastapi-container my-fastapi-app
    # 等待容器内服务就绪
    MAX_ATTEMPTS=20
    ATTEMPT=1
    while [ $ATTEMPT -le $MAX_ATTEMPTS ]; do
      if curl -s http://localhost:8000/health | grep -q "ok"; then
        echo "✅ Docker容器内服务已就绪"
        break
      fi
      echo "⏳ 等待容器服务启动... 第 $ATTEMPT/$MAX_ATTEMPTS 次尝试"
      sleep 1
      ATTEMPT=$((ATTEMPT+1))
    done
    # 执行测试
    pytest tests/
    # 清理容器
    docker stop fastapi-container && docker rm fastapi-container

关键注意事项

  • GitHub Actions的每个run步骤是独立的shell会话,后台进程在步骤结束后会被系统终止。因此,启动服务、等待就绪、执行测试必须在同一个run步骤中完成,否则后续步骤无法访问已启动的服务。
  • 不要依赖lsof或netstat判断服务是否就绪,因为端口被监听不代表服务已经完成初始化并能处理请求,直接用业务请求或健康检查端点验证更可靠。
  • 根据服务启动速度调整等待次数和间隔时间,避免因等待时间不足导致的误判。

内容的提问来源于stack exchange,提问作者André Ginklings

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 14:55:17