SuperAPI AI 工具集

async-processing-best-practices

编程与开发

查看项目

更新于 10-16 08:52

技能介绍

用途

本技能是面向 Web 应用异步处理的实现指南,用于在以下场景中参考:

  • 设计某项处理是否应以异步方式实现时
  • 选型与设计异步处理所需的基础设施时
  • 实现需要异步处理的后端逻辑时
  • 在前端实现异步处理的 UI 时

是否应采用异步处理的判断

当返回 HTTP 响应时处理无需已完成,可考虑采用异步处理。主要从以下角度判断:

  • 用户体验(UX):处理耗时超过 1 秒,且希望避免从 UI 执行时画面无法操作的情况
  • 外部依赖:调用外部 API 或服务等无法自行控制的对象时,担心对方系统故障或延迟导致性能下降、用户体验降低
  • 即时性低:用户无需立即知道处理结果
  • 资源保护:担心长时间处理占用 API 连接数,造成连接资源不必要的消耗

异步处理的实现方式

根据以下要素选择实现方式:托管 Web 应用的基础设施环境、Web 应用实现所用的框架与中间件、使用的云服务(AWS/Google Cloud)、期望的服务规模与所需健壮性、预算等。主要构建模式包括:

  • Ruby on Rails 的 ActiveJob + ActionCable 实现
    • Sidekiq 或 SolidQueue
    • Rails 异步处理实现方式参见 @references/01_infrastructure.md
  • TypeScript BullMQ 实现
    • 基于 Redis 的高性能任务队列
    • 最适合使用 Node.js/TypeScript 构建后端的情况
    • 详见 @references/02_typescript_bullmq.md
  • AWS SQS 任务队列 + AWS AppSync Events 事件发送 + DynamoDB 状态管理
    • 以 AWS 无服务器架构实现
    • Lambda + SQS + AppSync Events + DynamoDB 组合
    • 详见 @references/03_aws_serverless.md
  • Google Cloud Cloud Tasks 任务管理 + Firestore 通知与状态管理
    • 以 Google Cloud 无服务器架构实现
    • Cloud Run + Cloud Tasks + Firestore 组合
    • 详见 @references/04_gcp_serverless.md

实现方式对比

观点 Rails (Solid Queue) Rails (Sidekiq) BullMQ AWS Serverless GCP Serverless
额外基础设施 无 Redis Redis SQS、DynamoDB 等 Cloud Tasks、Firestore
可扩展性 中 高 高 非常高 非常高
运维负担 低 中 中 低 低
成本(低负载时) 低 中 中 非常低 非常低
实时通知 ActionCable ActionCable 自行实现 AppSync Events Firestore
最大处理时间 无限制 无限制 无限制 15 分钟(Lambda) 60 分钟(Cloud Run)
适用用例 小〜中规模 Rails 中〜大规模 Rails Node.js 通用 以 AWS 为中心的无服务器 以 GCP 为中心的无服务器

异步处理的后端实现

后端实现时,请针对以下观点参考各实现方式的最佳实践。

共通实现观点:

  • 参数接收方式
    • 仅传递可序列化的数据
    • 考虑参数大小限制(大数据使用外部存储)
    • 推荐基于 ID 的引用
  • 校验的实现
  • 错误发生时的处理与通知
    • 可重试错误与不可重试错误的分类
    • 重试设置(次数、退避策略)
    • Dead Letter Queue(DLQ)的处理
    • 错误通知(结构化日志、外部服务联动)
  • 进度状态管理
    • 状态管理用数据模型的设计
    • 进度率的计算与更新
    • 实时通知(WebSocket、SSE、轮询)
  • 取消处理
  • 其他
    • 确保幂等性
    • 超时对策
    • 任务拆分与链式
    • 测试策略

实现方式别参考:

实现方式 参考
Ruby on Rails (ActiveJob) @references/05_backend_rails.md
TypeScript BullMQ @references/06_backend_bullmq.md
AWS Serverless (Lambda + SQS) @references/07_backend_aws.md
GCP Serverless (Cloud Run + Cloud Tasks) @references/08_backend_gcp.md

异步处理 UI 的前端实现

前端实现时,请针对以下观点参考各框架的最佳实践。

共通实现观点:

  • 异步处理的调用方式
    • 通过表单提交启动异步任务
    • 通过自定义 Hook 或 Composable 管理调用
    • 防止重复提交
  • 状态管理与显示
    • 实时显示进度状况
    • 通过轮询更新状态
    • 通过 WebSocket/SSE 推送通知
    • Optimistic Updates(乐观更新)
  • 连接恢复处理
    • WebSocket/SSE 连接自动重连
    • 页面隐藏时的连接管理
    • 使用 Visibility API 进行状态同步
    • 离线/在线状态监控
  • 错误处理
    • 通过 Error Boundary 捕获错误
    • 全局错误处理
    • 重试功能(Exponential Backoff)
    • 向用户通知错误

框架别参考:

框架 参考
Rails Hotwire (Turbo + Stimulus + ActionCable) @references/09_frontend_hotwire.md
Next.js (React / App Router) @references/10_frontend_nextjs.md
Vue.js 3 (Composition API) @references/11_frontend_vuejs.md
React (Webpacker/Shakapacker) @references/12_frontend_react.md

生产环境部署

生产环境部署时的设置与最佳实践参见:

  • 生产环境部署指南:@references/13_deployment.md
    • Puma 插件设置
    • ECS/Fargate 环境
    • Kubernetes 环境
    • CI/CD 设置

Solid Cable(ActionCable 的替代)

若希望无需 Redis 使用 ActionCable,可使用 Solid Cable。

  • Solid Cable 参考:@references/14_solid_cable.md
    • 设置方法
    • 与 ActionCable 的区别
    • 配置选项

故障排查

发生问题时参见:

  • 故障排查指南:@references/15_troubleshooting.md
    • 任务未执行时
    • 状态未更新时
    • WebSocket 连接问题
    • 调试方法

环境隔离(共享 DB 时的注意事项)

当预发布环境与生产环境共享同一数据库时,需要以下设置。

Solid Queue 的队列名隔离:

# config/solid_queue.yml
staging:
  workers:
    - queues:
        - <%= ENV.fetch('QUEUE_PREFIX', 'staging') %>_default

production:
  workers:
    - queues:
        - <%= ENV.fetch('QUEUE_PREFIX', 'production') %>_default
# app/jobs/application_job.rb
class ApplicationJob < ActiveJob::Base
  queue_as do
    prefix = ENV.fetch('QUEUE_PREFIX', Rails.env)
    "#{prefix}_default"
  end
end

Solid Cable 的频道隔离:

# config/cable.yml
staging:
  adapter: solid_cable
  channel_prefix: <%= ENV.fetch('CABLE_PREFIX', 'staging') %>

production:
  adapter: solid_cable
  channel_prefix: <%= ENV.fetch('CABLE_PREFIX', 'production') %>

详见 @references/13_deployment.md 的「环境隔离设置」。