尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

关于线程池的纠错题

关于线程池的纠错题 一、错误代码import asyncio import threading from concurrent.futures import ThreadPoolExecutor from fastapi import FastAPI from pydantic import BaseModel app FastAPI() executor ThreadPoolExecutor(max_workers4) global_cache {} cache_lock threading.Lock() # 添加锁 class ProcessRequest(BaseModel): id: str def cpu_heavy_task(data: ProcessRequest): result 0 for i in range(100000000): result i # 加锁保护共享缓存 with cache_lock: global_cache[data.id] result return result app.post(/process) async def process_data(data: ProcessRequest): loop asyncio.get_running_loop() result await loop.run_in_executor(executor, cpu_heavy_task, data) return {result: result}二、修改与思考import asyncio from concurrent.futures import ProcessPoolExecutor # 改为进程池 import cachetools # 专业缓存库 from fastapi import FastAPI, HTTPException app FastAPI() # 进程池数量建议等于 CPU 核心数不要超 executor ProcessPoolExecutor(max_workers4) # 带 TTL 和最大条目限制的缓存线程安全 cache cachetools.TTLCache(maxsize100, ttl600) def cpu_bound_sync(data_id: str) - int: # 模拟计算注意进程池中无法共享全局变量必须序列化传入 result sum(range(100000000)) return result app.post(/process) async def process_data(data: ProcessRequest): # 1. 缓存预检读缓存无需加锁TTLCache 内部自带锁 if data.id in cache: return {result: cache[data.id], source: cache} # 2. 提交进程池并设置超时防止永久卡死 loop asyncio.get_running_loop() try: result await asyncio.wait_for( loop.run_in_executor(executor, cpu_bound_sync, data.id), timeout30.0 # 超时后任务仍在后台运行但请求会返回 504 ) except asyncio.TimeoutError: raise HTTPException(status_code504, detailCompute timeout) # 3. 写入缓存加锁保护防止多协程并发写脏数据 # 注ProcessPoolExecutor 返回的结果会 pickle 传回主进程 cache[data.id] result return {result: result}在微服务架构中绝对不建议让 API 网关直接等待这种秒级 CPU 计算。更好的做法是用run_in_executor把任务丢进 Redis 队列如 RQ立即返回202 Accepted和task_id让独立的 Worker 进程去计算计算完再回调或轮询结果。这时候run_in_executor仅用于把任务入队毫秒级 I/O根本不会堵塞线程池。
返回列表