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

在Google Cloud Run中使用Python多进程导致容器意外终止

Google Cloud Run中Python多进程触发Signal 11容器退出的排查方案

问题现象

容器意外退出,报错信息:

Uncaught signal: 11, pid=1, tid=13, fault_addr=69102686133216.

Container terminated on signal 11.

本地运行正常,但在Cloud Run环境中触发该问题,核心代码(已修正两处明显语法错误)如下:

from multiprocessing.pool import Pool
import threading

class ExampleClass:
    # ...
    
    @staticmethod
    def some_calc(a,b,c):
        # ... 耗时计算逻辑

    def some_method(self):  # 原代码遗漏self参数,已修正
        # 默认使用系统最大可用进程数创建进程池
        iterable_arguments = [] # 存储(a,b,c)形式的元组参数
        with Pool() as pool:
            result = pool.starmap(self.some_calc, iterable_arguments, chunksize=5)
    

class AnotherClass:
    # ...

    def MyGRPCMethod(self, request, context, **kwargs):
        # 原代码变量名拼写错误:routing -> routine,已修正
        routine = threading.Thread(target=self.example_class.some_method)
        routine.start()

if __name__ == '__main__':
    # 启动gRPC服务
    # ExampleClass.some_method 由AnotherClass.MyGRPCMethod触发,运行在独立线程中

当前环境配置

  • Cloud Run并发数:80
  • CPU限制:2核
  • 内存限制:4GiB
  • Python版本:3.11

排查方向

1. 进程池资源过载

Cloud Run单实例仅分配2核CPU,默认Pool()会根据os.cpu_count()创建进程,当80个并发请求同时触发进程池初始化时,会瞬间生成大量进程,导致CPU/内存资源耗尽,触发系统信号终止进程(Signal 11常对应段错误,资源过载是常见诱因)。

  • 解决建议:显式限制进程池大小,比如设置Pool(processes=2),与CPU核数匹配,避免资源竞争。

2. 线程内启动多进程的兼容性问题

Pythonmultiprocessing默认使用fork启动子进程,而Cloud Run容器主进程是PID 1,fork在PID 1进程下的行为存在兼容性问题(比如信号继承、资源隔离异常),且在线程中启动进程池会加剧这类问题。

  • 解决建议:
    • 切换进程启动方式为spawn,在代码开头添加:
      import multiprocessing
      multiprocessing.set_start_method('spawn')
      
    • 避免在线程内直接创建进程池,改为由主进程维护全局进程池,线程仅提交任务到队列,减少线程与进程的交叉调用。

3. 不可序列化对象的传递问题

虽然some_calc是静态方法,但使用self.some_calc传递给进程池时,会携带self实例引用,若实例包含不可序列化的对象(比如gRPC上下文、线程资源),会导致进程间通信失败,进而触发崩溃。

  • 解决建议:直接使用ExampleClass.some_calc替代self.some_calc,避免传递不必要的实例引用。

4. PID 1进程的信号处理异常

Linux系统中PID 1进程默认不会处理大部分信号,当子进程崩溃时,信号传递逻辑异常,可能导致主进程被误杀。

  • 解决建议:在子进程初始化时重置信号处理,添加进程初始化函数:
    def init_worker():
        import signal
        signal.signal(signal.SIGINT, signal.SIG_IGN)
    
    # 创建进程池时指定初始化函数
    with Pool(processes=2, initializer=init_worker) as pool:
        # ... 任务执行逻辑
    

5. 内存溢出触发段错误

尽管配置了4GiB内存,但80个并发请求叠加多进程计算的内存占用可能超过限制,触发OOM(内存不足),部分情况下OOM会表现为Signal 11段错误。

  • 解决建议:
    • 通过Cloud Console监控实例的内存使用峰值,确认是否存在溢出。
    • 优化some_calc的内存占用,比如及时释放大对象、使用生成器替代列表存储中间结果。
    • 降低Cloud Run并发数或进程池大小,减少资源峰值压力。

内容的提问来源于stack exchange,提问作者Newton Nthiga

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 09:25:51