云 运行 发送 SIGTERM,容器实例上没有可见的缩减

Cloud Run sending SIGTERM with no visible scale down on container instances

我已经使用 Gunicorn + Uvicorn worker 在云 运行 上部署了一个 Python 快速 API 应用程序。

云运行配置:

Docker 文件


FROM python:3.8-slim

# Allow statements and log messages to immediately appear in the Knative logs
ENV PYTHONUNBUFFERED True

ENV PORT ${PORT}

ENV APP_HOME /app

ENV APP_MODULE myapp.main:app

ENV TIMEOUT 0

ENV WORKERS 4

WORKDIR $APP_HOME

COPY ./requirements.txt ./

# Install production dependencies.
RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt

# Copy local code to the container image.
COPY . ./

# Run the web service on container startup. Here we use the gunicorn
# webserver, with one worker process and 8 threads.
# For environments with multiple CPU cores, increase the number of workers
# to be equal to the cores available.
# Timeout is set to 0 to disable the timeouts of the workers to allow Cloud Run to handle instance scaling.

CMD exec gunicorn --bind :$PORT --workers $WORKERS --worker-class uvicorn.workers.UvicornWorker --timeout $TIMEOUT $APP_MODULE  --preload

我的应用程序收到请求并执行以下操作:

from fastapi.concurrency import run_in_threadpool

async def bg_task():
    # create json payload
    errors = await run_in_threadpool(lambda: client.insert_rows_json(table_id, rows_to_insert))  # Make an API request.

我注意到间歇性的 Handling signal: term 日志导致 Gunicorn 关闭进程并重新启动它们。我无法理解为什么会发生这种情况。令人惊讶的是,这种情况有时会发生在 off-peak 小时,此时 API 收到 0 个请求。似乎也没有任何明显的云 运行 实例缩减导致此问题。

问题是,这在高峰时段对我的 API 的生产负载期间也经常发生 - 甚至导致 Cloud 运行 从 2 个实例自动缩放到 3/4 个实例。这会为我的 API 添加冷启动时间。我的 API 平均收到 1 reqs/minute.

随机 SIGTERM

期间的云 运行 指标

如此处清楚地显示,我的 API 在此期间没有收到任何请求,Cloud 运行 没有业务终止和重新启动 Gunicorn 进程。

另一个令人吃惊的问题是,这似乎只发生在我的生产环境中。在我的开发环境中,我有完全相同的设置,但我在那里没有看到任何这些问题。

为什么 Cloud 运行 发送 SIGTERM,我该如何避免?

Cloud 运行 是一个无服务器平台,这意味着服务器管理由 Google Cloud 完成,它可以选择不时停止一些实例(出于维护原因,出于技术问题原因,...).

但它对你没有任何改变,当然是冷启动,但它对你的进程来说应该是不可见的,即使在高负载下,因为你有一个 min-instance 参数 2 来保持实例启动并准备就绪在没有冷启动的情况下为流量提供服务。

您能否并行使用 3 或 4 个实例,而不是 2 个(最小值)?是的,但 Billable 实例持平为 2。云 运行 同样是无服务器的,它可以创建实例进行备份,并确保将来关闭某些实例不会影响您的流量。这是一个内部优化。没有附加成本,效果很好!

你能避免吗?不会,因为它是无服务器的,而且对您的工作负载没有影响。


关于“环境”的最后一点。对于Google Cloud,所有项目都是生产项目。没区别,google不知道什么是关键,什么不是,所以都是关键。

如果您注意到 2 个项目之间的差异,那只是因为您的项目部署在不同的 Google 云内部集群上。集群之间的状态、性能、维护操作(...)是不同的。再说一次,你对此无能为力。