6 个月预付 −28% · 1 年预付 −50%比较方案
PrivacyNodes
应用运维

为后台 worker 设定有界预算

仅当整个作业能够承受时才增加并发。队列起初可能排空更快,但同时会使数据库过载或重复副作用。从有界工作开始,并确保作业再次运行时结果仍然正确。

PrivacyNodes 工程笔记 · 已审核 · 3 分钟阅读

定义一单位有用工作

对于内部 CSV 导出,请求会创建导出记录;工作进程读取有界数据集、写入输出对象并将记录标记为完成。定义最大有用范围、时间限制和取消行为。使用隔离的队列、测试数据库和无法通知真实客户的目标。

将计算时间与数据库和存储等待区分开。单个作业时长数字会掩盖这些区别。在内存中构建整个文件与流式处理有界批次的可扩展性不同。保持队列消息足够小,以描述工作,而不嵌入客户数据或凭据。

通过设计使重复投递安全

使用持久导出标识符将尝试关联到一个逻辑结果。在持久状态中强制唯一性以及原子的所有权/完成转换。先检查导出是否存在,然后在单独的无保护步骤中插入,会让并发尝试发生竞态。发布对象并确认队列消息也构成一个失败边界。

# Illustrative contract, not queue implementation
job_type: export-account-report
logical_result: EXPORT_RECORD_ID
input_scope: AUTHORIZED_ACCOUNT_AND_DATE_RANGE
attempt_limit: REVIEWED_FINITE_LIMIT
completion: ONE_PUBLISHED_RESULT_FOR_THIS_EXPORT
retry: CLASSIFIED_TRANSIENT_FAILURES_ONLY
failed_result: INSPECTABLE_WITHOUT_CUSTOMER_SECRETS

Celery 将延迟确认与幂等任务关联,并记录了在子进程终止后仍会发生确认的情况。队列选项并不会创造恰好一次执行。请审查系统的重新投递语义,并设计应用结果以容忍重试。

技术参考: Celery 任务行为.

在增加进程之前设定预算

对于一个假设的工作进程,每个活动导出使用 300 MiB,四个同时导出在运行时开销之前就已意味着约 1,200 MiB。这些是规划输入,不是基准。再加上数据库连接、查询内存、临时磁盘和输出带宽;进程数只是其中一个限制。

用一个活动导出和真实积压进行演练。在重复相同 API 流量的情况下增加到两个。比较完成的有用导出、最旧作业年龄、延迟、失败和主机压力。如果吞吐量几乎不提高而数据库等待增加,请停止增加并发。额外的 CPU 可能无法消除该瓶颈。

阻止失败造成更多负载

在重试之前对错误分类。临时存储中断可能是暂时性的;未授权账户或不支持的导出格式需要终止性错误或人工干预。使用有限尝试预算以及支持的退避和抖动延迟重试。保持失败作业可检查,并移除敏感字段。

为外部调用设置超时并设定整体任务预算。放弃一次尝试并不能证明其远程副作用没有发生。一次超时的发布可能已经写入了输出。应通过导出 ID 进行对账,而不是盲目再发布一个结果。

将工作进程纳入部署和恢复

按照旧工作节点文档化的关闭行为停止其上的新工作。让进行中的工作完成,或在已知截止时间下安全中断。测试在输出已写入但完成尚未记录之后发生崩溃的情况;替换尝试应找到一致的结果,而不是将其重复。

在重叠的发布版本之间保持消息格式兼容。新的 API 可能入队一个旧工作节点无法读取的负载。对契约进行版本管理,或对发布进行排序,以便在新消息出现之前已有受支持的消费者。将这些数据库写入方纳入 模式兼容性审查.

选择下一个要更改的约束

留下并发设置、重试策略、任务契约和经过测量的停止规则。如果昂贵的导出拖慢了小任务,考虑在提高全局限制之前使用具有独立预算的独立队列。如果在任何现实的导出负载下 API 延迟都受到影响,分离工作节点可能比扩大一个共享主机更有用。

在变更后重复相同的工作负载并保留对比。 API 与工作者场景 说明了 App 2 和额外内存如何进入选择。这些流程并不意味着托管队列、无限任务或自动扩展。

官方参考

本文档已针对本文进行审核。示例是规划练习,不是已在 PrivacyNodes 服务器上测试过的命令。请查阅你所安装版本的文档。