开发MCU业务程序如何选择合适的编程范式(异步/多线程/多进程)
编程范式选型方案
你当前的场景适合采用 异步IO + 多进程池 的混合范式,不需要单独选用某一种单一架构,组合使用可同时满足IO低延迟和计算不阻塞的需求。
单一范式的适配性问题
- 纯asyncio:仅适合IO密集型场景,你提到的CV任务属于CPU密集型计算,Python GIL会导致计算过程完全阻塞异步事件循环,30-40秒的计算窗口内所有机器人请求、Redis监听都会停止响应,完全不符合新请求需正常处理的要求。
- 纯多线程:同样受GIL限制,CPU密集的CV任务运行时会挤占IO任务的调度资源,导致TCP请求响应、Redis发布订阅的延迟升高,高并发场景下容易出现消息丢失。
- 纯多进程:所有任务都采用进程实现的话,进程上下文切换开销过大,TCP服务、Redis监听这类IO密集型任务用进程承载属于资源浪费,同时进程间通信成本也会大幅提升开发复杂度。
混合架构的实现逻辑
将任务按类型拆分,分别用对应技术栈处理:
- 所有IO密集型任务走asyncio异步事件循环
涵盖TCP服务器接收机器人请求、Redis发布订阅监听、请求转发到Redis、结果回传给机器人等IO等待类场景,可搭配aioredis这类异步Redis客户端,完全适配事件循环特性,响应速度快、资源占用低,可支撑后续更多外部控制单元接入的并发需求。 - 所有CPU密集型任务(CV计算、数据处理程序)丢给多进程池执行
- 当异步事件循环满足CV任务启动条件(收到机器人请求 + Redis存在所需数据),不要在协程内直接执行计算,而是将任务提交给
concurrent.futures.ProcessPoolExecutor - 可直接调用asyncio内置的
loop.run_in_executor方法对接多进程池,计算过程完全不会阻塞主事件循环,CV任务运行的30-40秒内新的机器人请求仍然可以被正常处理 - 任务执行完成后通过异步回调将结果写回Redis,再回传给对应的机器人即可。
- 当异步事件循环满足CV任务启动条件(收到机器人请求 + Redis存在所需数据),不要在协程内直接执行计算,而是将任务提交给
可选优化点
- 多进程池设置固定进程上限,避免同时运行过多CV任务占满MCU算力,影响基础IO服务的稳定性
- 给不同优先级的任务分配不同的队列调度权重,机器人实时请求的优先级高于后台批量数据处理任务
- 针对重复参数的CV任务可增加结果缓存,避免重复计算浪费资源
内容的提问来源于stack exchange,提问作者Daniil
相关产品推荐
相关产品推荐

