V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Vcide
V2EX  ›  程序员

请教一下这种系统到底应该怎么设计

  •  
  •   Vcide · 307 天前 · 1988 次点击
    这是一个创建于 307 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现在 PO 主正在设计这样一个系统,现有的设计包含 4 个模块.

    四个模块具体如下:

    1. 1 个 SpringBoot 的后端模块 A,这个模块主要是实现 endpoint,提供对外使用的 API. 用户可以通过它上传文件并创建对应任务,选择后续的处理模块,并查询处理结果.
    2. 3 个独立的 Python 的 FastAPI 分析模块 B,C,D. 每一个处理起来都非常耗时,根据输入的不同,耗时在 30s 到 5 分钟左右不等. 其中 C 模块需要 B 模块处理后的结果,D 模块独立运行.

    现在整个系统的工作流程类似于,用户通过 A 上传要处理的文件至服务器,并创建一个包含多个子任务的主任务,子任务是文件要不要被 B,C,D 处理. A,B,C,D 之间有一个消息队列作为中介进行消息的传递.

    现在我的问题是:

    1. 对于 C 模块需要 B 模块的处理结果这件事,应该如何实现? 是 B 完成处理后通知 C, 还是通知 A,由 A 通知 C 呢?
    2. PO 主目前使用的是 RabbitMQ, 因为 B,C,D 都会消耗大量系统资源, 所以目前的设计是将它们对应的 perfetch_qos 设定为了 1, 并且在处理完之后手动 ack.感觉这样做很奇怪.有没有更好的处理方法呢?
    3. 假设 B,C,D 处理完之后是应该由它们更新数据库中子任务的状态,还是向 A 传递消息,由 A 来更新子任务的状态呢?

    希望大家不吝赐教, 谢谢!

    11 条回复    2024-03-13 15:51:37 +08:00
    vczyh
        1
    vczyh  
       307 天前
    1. 模块的依赖和功能需要划分清楚,C 需要 B 的执行结果,为什么要通知 A ,如果你规定所有消息必须经过 A 或者因为 A 管理整个任务的生命周期,那就通知 A ,ABCD 只是 worker ,这样模块就清晰了,而且都用消息队列了,同时通知 A 和 C 也没问题。
    2. 我认为手动 ACK 不奇怪吧,这个不太清楚
    3. 同 1
    rrfeng
        2
    rrfeng  
       307 天前
    你这是个任务编排问题,跟信息交互关系不大。
    要我说的话,丢到 jenkins ( or 类似工具)上去做个 flow 完事儿……
    masterclock
        3
    masterclock  
       307 天前
    看起来是流程,所以 Temporal
    jungledg
        4
    jungledg  
       307 天前
    想法和 1L 基本一致; 如果 A 需要感知所有任务处理状态、统筹分配的话,所有持久化状态改变都统一收口到 A 来做,反之就由各子系统来更新状态。
    dayeye2006199
        5
    dayeye2006199  
       307 天前
    最上面叠个 orchester 。所有的任务都走这个服务。
    这个服务负责下发并且管理子任务之间的依赖。
    lsk569937453
        6
    lsk569937453  
       307 天前
    由 A 统一来管理状态就行了。
    1.上传视频文件到 A 。A 负责更新此任务的状态为"上传完毕"。A 会开启定时任务(1 分钟执行一次)检查任务状态。定时任务逻辑如下:

    - a.从数据库里找到最新的"上传完毕"的任务,调用 B/D 的 API 检查是否有运行中的任务,没有的话,则调用 B/D 的 API ,提交任务。
    - b.从数据库里找到最新的"B 已经处理完毕"的任务,调用 C 的 API 检查是否有运行中的任务,没有的话,则调用 C 的 API ,提交任务。

    所有的提交任务都为异步提交。任务处理完毕直接到数据库中更新任务状态。
    9c04C5dO01Sw5DNL
        7
    9c04C5dO01Sw5DNL  
       307 天前
    B 处理完之后往特定通道发送通知消息,谁感兴趣谁订阅处理。
    flmn
        8
    flmn  
       307 天前
    你这个处理流程会变化么?会有多个不同的流程么?
    如果是,那么,最好找个任务编排框架来处理

    如果流程相对固定,可以使用 mq 和多个服务来手工编排,状态记到数据库


    两种情况,A 都只做命令控制和状态查询,不参与流程处理,和 BCD 通过数据库交换信息
    auh
        9
    auh  
       307 天前
    1. A 系统看上去像是个任务管理者。包含查询结果的功能。那么,当然是需要被通知的。通知的方式,如果是数据库的话,A 系统可以有定时任务处理。如果,A 系统被通知,采用网络回调通知。那么,存在网络问题,显然,还是 task+回调,的形式,进行的结果。所以,A 系统,至少被数据库通知到。才能保证不丢失消息。叠回调,才能更快吧。
    2. 没感觉。
    3. 和 1 一样。
    nolog
        10
    nolog  
       303 天前
    1.感觉可以 B 通知 MQ ,然后 MQ 通知 C 做处理
    2.手动 ACK 没毛病
    3.看情况吧,如果 B 、C 、D 需要更新状态很频繁并且 QPS 很大的话,并不建议由 A 来统一管理,各子模块自己更新自己的数据状态更好点,这样模块边界比较明确。
    Vcide
        11
    Vcide  
    OP
       253 天前
    谢谢大家的建议和意见,非常有帮助! 由于我们处理的流程较为固定, 所以目前的处理方法是使用 mq 和多个服务来进行手工编排,各个模块分开管理自己的状态了. 对于 B 的处理方法采用了 @giiiiiithub 的方法, 由于项目时间的限制, 没有使用项目编排框架的机会, 如果后续有新的变化, 会继续在这里向大家更新.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   962 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 21:47 · PVG 05:47 · LAX 13:47 · JFK 16:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.