feat: 添加 max_concurrent_requests 配置项,优化并发请求控制;更新 InboundProcessor 以支持信号量控制并发

This commit is contained in:
ooodc 2026-05-13 21:56:01 +08:00
parent 35b9c42d07
commit d4c15e0478
3 changed files with 102 additions and 54 deletions

View File

@ -312,6 +312,8 @@ pub struct GatewayConfig {
rename = "agent_prompt_reinject_every" rename = "agent_prompt_reinject_every"
)] )]
pub agent_prompt_reinject_every: u64, pub agent_prompt_reinject_every: u64,
#[serde(default = "default_max_concurrent_requests")]
pub max_concurrent_requests: usize,
} }
#[derive(Debug, Clone, Deserialize, Serialize)] #[derive(Debug, Clone, Deserialize, Serialize)]
@ -589,6 +591,10 @@ fn default_agent_prompt_reinject_every() -> u64 {
100 100
} }
fn default_max_concurrent_requests() -> usize {
10
}
impl Default for GatewayConfig { impl Default for GatewayConfig {
fn default() -> Self { fn default() -> Self {
Self { Self {
@ -597,6 +603,7 @@ impl Default for GatewayConfig {
show_tool_results: false, show_tool_results: false,
chat_history_ttl_hours: Some(4), chat_history_ttl_hours: Some(4),
agent_prompt_reinject_every: default_agent_prompt_reinject_every(), agent_prompt_reinject_every: default_agent_prompt_reinject_every(),
max_concurrent_requests: default_max_concurrent_requests(),
} }
} }
} }

View File

@ -29,6 +29,7 @@ use axum::{Router, routing};
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
use tokio::net::TcpListener; use tokio::net::TcpListener;
use tokio::sync::Semaphore;
use crate::bus::MessageBus; use crate::bus::MessageBus;
use crate::channels::ChannelManager; use crate::channels::ChannelManager;
@ -92,8 +93,14 @@ impl GatewayState {
/// Start the message processing loops /// Start the message processing loops
pub async fn start_message_processing(&self) { pub async fn start_message_processing(&self) {
let bus_for_outbound = self.bus.clone(); let bus_for_outbound = self.bus.clone();
// Create semaphore for controlling concurrent requests
let max_concurrent = self.config.gateway.max_concurrent_requests;
let semaphore = Arc::new(Semaphore::new(max_concurrent));
// Spawn inbound processor with semaphore-controlled concurrency
let inbound_processor = let inbound_processor =
InboundProcessor::new(self.bus.clone(), self.session_manager.clone()); InboundProcessor::new(self.bus.clone(), self.session_manager.clone(), semaphore);
tokio::spawn(inbound_processor.run()); tokio::spawn(inbound_processor.run());
// Spawn outbound dispatcher // Spawn outbound dispatcher

View File

@ -1,6 +1,9 @@
use std::sync::Arc; use std::sync::Arc;
use crate::bus::{MessageBus, OutboundMessage}; use tokio::sync::Semaphore;
use crate::agent::AgentError;
use crate::bus::{InboundMessage, MessageBus, OutboundMessage};
use super::session::{BusToolCallEmitter, SessionManager}; use super::session::{BusToolCallEmitter, SessionManager};
@ -8,38 +11,68 @@ use super::session::{BusToolCallEmitter, SessionManager};
pub struct InboundProcessor { pub struct InboundProcessor {
bus: Arc<MessageBus>, bus: Arc<MessageBus>,
session_manager: SessionManager, session_manager: SessionManager,
semaphore: Arc<Semaphore>,
} }
impl InboundProcessor { impl InboundProcessor {
pub fn new(bus: Arc<MessageBus>, session_manager: SessionManager) -> Self { pub fn new(
bus: Arc<MessageBus>,
session_manager: SessionManager,
semaphore: Arc<Semaphore>,
) -> Self {
Self { Self {
bus, bus,
session_manager, session_manager,
semaphore,
} }
} }
pub async fn run(self) { pub async fn run(self) {
tracing::info!("Inbound processor started"); let max_concurrent = self.semaphore.available_permits();
tracing::info!(
max_concurrent_requests = max_concurrent,
"Inbound processor started"
);
loop { loop {
// 1. 消费消息
let inbound = self.bus.consume_inbound().await; let inbound = self.bus.consume_inbound().await;
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
{ {
tracing::debug!( tracing::debug!(
channel = %inbound.channel, channel = %inbound.channel,
chat_id = %inbound.chat_id, chat_id = %inbound.chat_id,
sender = %inbound.sender_id, sender = %inbound.sender_id,
content = %inbound.content, content_len = %inbound.content.len(),
media_count = %inbound.media.len(), media_count = %inbound.media.len(),
"Processing inbound message" "Processing inbound message"
); );
if !inbound.media.is_empty() {
for (i, media) in inbound.media.iter().enumerate() {
tracing::debug!(media_index = i, media_type = %media.media_type, path = %media.path, "Media item");
} }
// 2. 获取 semaphore permit控制并发
let permit = match self.semaphore.clone().acquire_owned().await {
Ok(permit) => permit,
Err(_) => {
tracing::error!("Semaphore closed, stopping inbound processor");
break;
}
};
// 3. 克隆 processor 用于新任务
let processor = self.clone();
// 4. 独立任务处理(包含 permit任务完成自动释放
tokio::spawn(async move {
let _permit = permit; // 持有 permit 直到任务完成
if let Err(e) = processor.process_one(inbound).await {
tracing::error!(error = %e, "Message processing failed");
}
});
} }
} }
async fn process_one(&self, inbound: InboundMessage) -> Result<(), AgentError> {
let live_emitter = Arc::new(BusToolCallEmitter::new( let live_emitter = Arc::new(BusToolCallEmitter::new(
self.bus.clone(), self.bus.clone(),
inbound.channel.clone(), inbound.channel.clone(),
@ -87,6 +120,7 @@ impl InboundProcessor {
} }
} }
} }
}
Ok(())
} }
} }