# 任务队列 (Task Queue)

## 1. 概述

任务队列是应用层的核心组件之一，它在请求接收（由API网关处理）和任务执行（由Agent实例处理）之间扮演着异步通信和缓冲的角色。通过引入任务队列，系统可以实现服务解耦、削峰填谷、提高系统的整体伸缩性和可靠性。所有需要由Agent处理的非即时性任务都会被格式化后放入队列中，等待Agent编排器消费。

## 2. 设计目标

*   **解耦 (Decoupling)**: 将任务的生产者（如API网关）与消费者（Agent编排器）完全分离。生产者无需知道哪个Agent实例将处理任务，也无需关心消费者是否当前可用。
*   **异步处理 (Asynchronous Processing)**: 允许API网关在接收到请求后，快速将任务放入队列并立即响应客户端，而无需等待任务执行完成。这对于耗时较长的任务至关重要。
*   **削峰填谷 (Peak Load Buffering)**: 在流量高峰期，任务队列可以作为缓冲区，暂存超出系统当前处理能力的请求，防止后端服务因瞬时过载而崩溃。系统可以在流量低谷期平稳地处理这些积压的任务。
*   **可靠性与持久化 (Reliability & Durability)**: 任务一旦被放入队列，就应该被持久化存储，确保即使在系统部分组件（如Agent实例）重启或崩溃的情况下，任务也不会丢失。
*   **可扩展性 (Scalability)**: 任务队列本身和消费者（Agent编排器）都应能够水平扩展，以应对不断增长的任务负载。

## 3. 核心组件

### 3.1 消息代理 (Message Broker)

任务队列系统的核心，负责消息的接收、存储和分发。

*   **功能**: 
    *   提供API供生产者发送消息。
    *   将消息持久化到磁盘或内存+磁盘。
    *   管理队列（Queues）或主题（Topics）。
    *   将消息路由给订阅了相应队列或主题的消费者。
    *   处理消息的确认（Acknowledgement）机制。
*   **技术选型**: RabbitMQ, Redis (with Celery/Dramatiq), Apache Kafka, AWS SQS, Google Cloud Pub/Sub。

### 3.2 任务生产者 (Task Producer)

任何向队列中发送任务的组件，最典型的是API网关。

*   **功能**: 
    *   连接到消息代理。
    *   将业务请求封装成一个标准化的`Task`消息体（通常是JSON格式）。
    *   将消息发布到指定的队列或主题。

### 3.3 任务消费者 (Task Consumer)

从队列中获取并处理任务的组件，在我们的架构中，这通常是`Agent Orchestrator`的工作进程（Worker）。

*   **功能**: 
    *   订阅一个或多个队列。
    *   从队列中拉取（pull）或接收（push）消息。
    *   处理任务的业务逻辑（即，调用Agent实例）。
    *   在任务处理成功后，向消息代理发送一个确认（ACK），告知代理可以安全地删除该消息。
    *   如果任务处理失败，可以发送一个否定确认（NACK），让消息可以被重新投递或放入“死信队列”。

### 3.4 死信队列 (Dead-Letter Queue - DLQ)

一个特殊的队列，用于存放处理失败多次后被放弃的消息。

*   **功能**: 
    *   当一个消息因为格式错误、业务逻辑持续失败等原因，被消费者重试了预设次数后仍然失败时，该消息会被自动路由到DLQ。
    *   这可以防止“毒丸消息”（Poison Pill Message）无限次地阻塞主队列的处理。
    *   开发者可以对DLQ中的消息进行监控和手动分析，以诊断系统问题。

## 4. 任务处理流程

1.  **入队 (Enqueuing)**: `API Gateway`接收到一个外部请求，将其转换为一个`Task` JSON对象，并将其作为一条消息发送到`Message Broker`的一个特定主题（如`text_generation_tasks`）。
2.  **持久化**: `Message Broker`接收到消息，将其持久化，并准备将其分发给订阅了该主题的消费者。
3.  **消费 (Consuming)**: `Agent Orchestrator`的一个空闲工作进程（Worker）从`text_generation_tasks`队列中获取了该消息。
4.  **处理 (Processing)**: Worker解析`Task`对象，并调用一个`Agent Instance`来执行任务。
5.  **成功确认 (ACK)**: Agent成功完成了任务。Worker向`Message Broker`发送一个ACK信号。`Message Broker`收到ACK后，将该消息从队列中永久删除。
6.  **失败处理 (Failure Handling)**: 如果Agent处理任务失败，Worker不会发送ACK。根据配置，`Message Broker`会在一段时间后将该消息重新投递给另一个Worker。如果重试多次仍然失败，消息最终会被移入`dead_letter_queue`。

## 5. 关键设计考量

*   **消息格式**: 必须定义一个标准化的、向前兼容的任务消息格式（如使用JSON Schema或Protobuf），确保生产者和消费者之间的契约。
*   **幂等性 (Idempotency)**: 由于网络问题或消费者崩溃，同一个任务可能会被重复投递。消费者在设计时必须考虑幂等性，即多次处理同一个任务（具有相同的`task_id`）应与只处理一次产生相同的结果。
*   **任务路由策略**: 
    *   **简单队列**: 一对一或多对一的模式，适用于简单的任务处理。
    *   **发布/订阅 (Pub/Sub)**: 使用主题（Topic）进行广播，一个任务可以被多个不同的消费者（例如，一个用于执行，一个用于日志记录）接收。Kafka是这种模式的典型代表。
*   **优先级队列**: 在某些场景下，需要支持任务优先级，确保高优先级的任务（如用户交互式请求）能比低优先级的任务（如批量数据处理）更快被处理。
*   **监控**: 必须对任务队列的关键指标进行监控，包括：队列深度（积压的任务数）、消息吞吐率（生产和消费速率）、消费者延迟等。

## 6. 技术选型建议

*   **对于通用、灵活的任务队列**: **RabbitMQ** 或基于 **Redis** 的库（如 **Celery**）是非常好的选择。它们支持复杂的路由拓扑和优先级队列，社区成熟，易于部署。
*   **对于大规模流处理**: 如果任务被看作是连续的事件流，并且需要进行复杂的流处理或日志聚合，**Apache Kafka** 是行业标准。
*   **对于云原生环境**: 如果应用完全部署在云上，使用云厂商提供的托管服务（如 **AWS SQS**, **Google Cloud Pub/Sub**）可以极大地简化运维工作。