文章目录
任务背景
需要处理用户发来的视频理解任务,每个任务执行耗时约5到10分钟。算法处理层需要占用CPU和内存资源。同时,为了削峰减流,要引入消息队列组件。
- 理想的选型可能是Pulsar,它是存算分离的架构,且易于扩容。但是为了满足统一规范,消息队列选型为Kafka。
- 虽然每个视频理解任务可以拆分为多个阶段,但这会增加微服务数量,并引入编程复杂度。因此,本文在优化时单条视频理解任务需要5~10分钟,且无法分拆。
- 要满足多租户的要求,不同用户的处理之间不应当互相阻塞。
解决方案1:单topic
引入了Kafka后,最简易的形态是只维持单个topic,单个容器。我们假设一个容器内可以运行多个消费者线程,订阅这个topic。示意图如下:
其中:
- DB指Database数据库,t1指topic1,D1, D2指Docker容器1和2。
- D1和D2都会订阅同一个topic t1,分担订阅压力。
留意到,实际上一个容器内可能运行多个线程,每个线程都是一个消费者,会订阅某个topic。
它的缺点是,在同一队列里,某个用户的请求会被其它用户的请求阻塞。如上图所示,在队列中,用户1的请求1(以下简称u1r1)排在用户2的请求1前面,如果u1r1的耗时过久,会连带使得u2r1的耗时也增加,这不满足多租户的要求。
解决方案2:多topic全订阅
为了解决多租户问题,我们为每个用户创建一个topic,这样不同用户的请求就不会排在同一队列中了。如下图所示:
- 假设我们有n个用户,就为它们创建n个topic。
- 我们维持m个容器。
- 每个容器在运行时,都周期性地从数据库中读取全部topic(t1, t2, …, tn)。
- 然后,每个容器都会订阅每一个topic,能分摊消费的压力。容器会为每一个订阅的topic分配一个常驻的消费者线程。
这样的好处是:
- 支持多租户,不同用户的请求不会互相阻