mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-03 09:50:21 +08:00
perf(gateway): 流式处理代码层性能优化
- 将 spawn 内 buffered_body 从 Vec<u8> 改为 VecDeque<u8>, drain 前端从 O(n) 变 O(1) - 消除 prefetched body/chunks 的不必要 clone, 改为直接 move - Pending/Streaming 非终态候选状态写入改为 tokio::spawn fire-and-forget - 连接池默认 max_connections 从 30 提升到 50
This commit is contained in:
@@ -112,21 +112,28 @@ pub(crate) async fn execute_execution_runtime_stream(
|
|||||||
.usage_runtime
|
.usage_runtime
|
||||||
.record_pending(state.data.as_ref(), &lifecycle_seed);
|
.record_pending(state.data.as_ref(), &lifecycle_seed);
|
||||||
let candidate_started_unix_secs = current_request_candidate_unix_ms();
|
let candidate_started_unix_secs = current_request_candidate_unix_ms();
|
||||||
record_local_request_candidate_status(
|
{
|
||||||
state,
|
let state_bg = state.clone();
|
||||||
&plan,
|
let plan_bg = plan.clone();
|
||||||
report_context.as_ref(),
|
let report_context_bg = report_context.clone();
|
||||||
SchedulerRequestCandidateStatusUpdate {
|
tokio::spawn(async move {
|
||||||
status: RequestCandidateStatus::Pending,
|
record_local_request_candidate_status(
|
||||||
status_code: None,
|
&state_bg,
|
||||||
error_type: None,
|
&plan_bg,
|
||||||
error_message: None,
|
report_context_bg.as_ref(),
|
||||||
latency_ms: None,
|
SchedulerRequestCandidateStatusUpdate {
|
||||||
started_at_unix_ms: Some(candidate_started_unix_secs),
|
status: RequestCandidateStatus::Pending,
|
||||||
finished_at_unix_ms: None,
|
status_code: None,
|
||||||
},
|
error_type: None,
|
||||||
)
|
error_message: None,
|
||||||
.await;
|
latency_ms: None,
|
||||||
|
started_at_unix_ms: Some(candidate_started_unix_secs),
|
||||||
|
finished_at_unix_ms: None,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
});
|
||||||
|
}
|
||||||
let plan_request_id_for_log = short_request_id(plan.request_id.as_str());
|
let plan_request_id_for_log = short_request_id(plan.request_id.as_str());
|
||||||
let provider_name = plan.provider_name.as_deref().unwrap_or("-");
|
let provider_name = plan.provider_name.as_deref().unwrap_or("-");
|
||||||
let endpoint_id = plan.endpoint_id.as_str();
|
let endpoint_id = plan.endpoint_id.as_str();
|
||||||
@@ -973,23 +980,31 @@ async fn execute_stream_from_frame_stream(
|
|||||||
status_code,
|
status_code,
|
||||||
prefetched_telemetry.as_ref(),
|
prefetched_telemetry.as_ref(),
|
||||||
);
|
);
|
||||||
record_local_request_candidate_status(
|
{
|
||||||
state,
|
let state_bg = state.clone();
|
||||||
&plan,
|
let plan_bg = plan.clone();
|
||||||
report_context.as_ref(),
|
let report_context_bg = report_context.clone();
|
||||||
SchedulerRequestCandidateStatusUpdate {
|
let latency_ms = prefetched_telemetry
|
||||||
status: RequestCandidateStatus::Streaming,
|
.as_ref()
|
||||||
status_code: Some(status_code),
|
.and_then(|telemetry| telemetry.elapsed_ms);
|
||||||
error_type: None,
|
tokio::spawn(async move {
|
||||||
error_message: None,
|
record_local_request_candidate_status(
|
||||||
latency_ms: prefetched_telemetry
|
&state_bg,
|
||||||
.as_ref()
|
&plan_bg,
|
||||||
.and_then(|telemetry| telemetry.elapsed_ms),
|
report_context_bg.as_ref(),
|
||||||
started_at_unix_ms: Some(candidate_started_unix_secs),
|
SchedulerRequestCandidateStatusUpdate {
|
||||||
finished_at_unix_ms: None,
|
status: RequestCandidateStatus::Streaming,
|
||||||
},
|
status_code: Some(status_code),
|
||||||
)
|
error_type: None,
|
||||||
.await;
|
error_message: None,
|
||||||
|
latency_ms,
|
||||||
|
started_at_unix_ms: Some(candidate_started_unix_secs),
|
||||||
|
finished_at_unix_ms: None,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let (tx, mut rx) = mpsc::channel::<Result<Bytes, IoError>>(16);
|
let (tx, mut rx) = mpsc::channel::<Result<Bytes, IoError>>(16);
|
||||||
let state_for_report = state.clone();
|
let state_for_report = state.clone();
|
||||||
@@ -999,9 +1014,9 @@ async fn execute_stream_from_frame_stream(
|
|||||||
let report_kind_owned = report_kind.clone();
|
let report_kind_owned = report_kind.clone();
|
||||||
let report_context_owned = report_context.clone();
|
let report_context_owned = report_context.clone();
|
||||||
let lifecycle_seed_for_report = lifecycle_seed.clone();
|
let lifecycle_seed_for_report = lifecycle_seed.clone();
|
||||||
let provider_prefetched_body_for_report = provider_prefetched_body.clone();
|
let provider_prefetched_body_for_report = provider_prefetched_body;
|
||||||
let prefetched_body_for_report = prefetched_body.clone();
|
let prefetched_body_for_report = prefetched_body;
|
||||||
let prefetched_chunks_for_body = prefetched_chunks.clone();
|
let prefetched_chunks_for_body = prefetched_chunks;
|
||||||
let initial_telemetry = prefetched_telemetry.clone();
|
let initial_telemetry = prefetched_telemetry.clone();
|
||||||
let initial_reached_eof = reached_eof;
|
let initial_reached_eof = reached_eof;
|
||||||
let direct_stream_finalize_kind_owned = direct_stream_finalize_kind.clone();
|
let direct_stream_finalize_kind_owned = direct_stream_finalize_kind.clone();
|
||||||
@@ -1012,8 +1027,8 @@ async fn execute_stream_from_frame_stream(
|
|||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
const MAX_STREAM_BODY_BUFFER_BYTES: usize = 256 * 1024; // 256KB
|
const MAX_STREAM_BODY_BUFFER_BYTES: usize = 256 * 1024; // 256KB
|
||||||
|
|
||||||
let mut provider_buffered_body = provider_prefetched_body_for_report;
|
let mut provider_buffered_body: VecDeque<u8> = provider_prefetched_body_for_report.into();
|
||||||
let mut buffered_body = prefetched_body_for_report;
|
let mut buffered_body: VecDeque<u8> = prefetched_body_for_report.into();
|
||||||
let mut provider_body_truncated = false;
|
let mut provider_body_truncated = false;
|
||||||
let mut client_body_truncated = false;
|
let mut client_body_truncated = false;
|
||||||
let mut telemetry: Option<ExecutionTelemetry> = initial_telemetry.clone();
|
let mut telemetry: Option<ExecutionTelemetry> = initial_telemetry.clone();
|
||||||
@@ -1077,7 +1092,7 @@ async fn execute_stream_from_frame_stream(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
provider_buffered_body.extend_from_slice(&chunk);
|
provider_buffered_body.extend(chunk.iter().copied());
|
||||||
if provider_buffered_body.len() > MAX_STREAM_BODY_BUFFER_BYTES {
|
if provider_buffered_body.len() > MAX_STREAM_BODY_BUFFER_BYTES {
|
||||||
let tail_start =
|
let tail_start =
|
||||||
provider_buffered_body.len() - MAX_STREAM_BODY_BUFFER_BYTES;
|
provider_buffered_body.len() - MAX_STREAM_BODY_BUFFER_BYTES;
|
||||||
@@ -1140,7 +1155,7 @@ async fn execute_stream_from_frame_stream(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffered_body.extend_from_slice(&rewritten_chunk);
|
buffered_body.extend(&rewritten_chunk);
|
||||||
if buffered_body.len() > MAX_STREAM_BODY_BUFFER_BYTES {
|
if buffered_body.len() > MAX_STREAM_BODY_BUFFER_BYTES {
|
||||||
let tail_start = buffered_body.len() - MAX_STREAM_BODY_BUFFER_BYTES;
|
let tail_start = buffered_body.len() - MAX_STREAM_BODY_BUFFER_BYTES;
|
||||||
buffered_body.drain(..tail_start);
|
buffered_body.drain(..tail_start);
|
||||||
@@ -1239,7 +1254,7 @@ async fn execute_stream_from_frame_stream(
|
|||||||
normalized_chunk
|
normalized_chunk
|
||||||
};
|
};
|
||||||
if !rewritten_chunk.is_empty() {
|
if !rewritten_chunk.is_empty() {
|
||||||
buffered_body.extend_from_slice(&rewritten_chunk);
|
buffered_body.extend(&rewritten_chunk);
|
||||||
if tx.send(Ok(Bytes::from(rewritten_chunk))).await.is_err() {
|
if tx.send(Ok(Bytes::from(rewritten_chunk))).await.is_err() {
|
||||||
warn!(
|
warn!(
|
||||||
event_name = "stream_execution_downstream_flush_disconnected",
|
event_name = "stream_execution_downstream_flush_disconnected",
|
||||||
@@ -1278,7 +1293,7 @@ async fn execute_stream_from_frame_stream(
|
|||||||
if let Some(rewriter) = local_stream_rewriter.as_mut() {
|
if let Some(rewriter) = local_stream_rewriter.as_mut() {
|
||||||
match rewriter.finish() {
|
match rewriter.finish() {
|
||||||
Ok(flushed_chunk) if !flushed_chunk.is_empty() => {
|
Ok(flushed_chunk) if !flushed_chunk.is_empty() => {
|
||||||
buffered_body.extend_from_slice(&flushed_chunk);
|
buffered_body.extend(&flushed_chunk);
|
||||||
if tx.send(Ok(Bytes::from(flushed_chunk))).await.is_err() {
|
if tx.send(Ok(Bytes::from(flushed_chunk))).await.is_err() {
|
||||||
warn!(
|
warn!(
|
||||||
event_name = "stream_execution_downstream_rewrite_flush_disconnected",
|
event_name = "stream_execution_downstream_rewrite_flush_disconnected",
|
||||||
@@ -1340,10 +1355,15 @@ async fn execute_stream_from_frame_stream(
|
|||||||
provider_body_base64: (!provider_body_truncated
|
provider_body_base64: (!provider_body_truncated
|
||||||
&& !provider_buffered_body.is_empty())
|
&& !provider_buffered_body.is_empty())
|
||||||
.then(|| {
|
.then(|| {
|
||||||
base64::engine::general_purpose::STANDARD.encode(&provider_buffered_body)
|
base64::engine::general_purpose::STANDARD
|
||||||
|
.encode(provider_buffered_body.make_contiguous())
|
||||||
}),
|
}),
|
||||||
client_body_base64: (!client_body_truncated && !buffered_body.is_empty())
|
client_body_base64: (!client_body_truncated && !buffered_body.is_empty()).then(
|
||||||
.then(|| base64::engine::general_purpose::STANDARD.encode(&buffered_body)),
|
|| {
|
||||||
|
base64::engine::general_purpose::STANDARD
|
||||||
|
.encode(buffered_body.make_contiguous())
|
||||||
|
},
|
||||||
|
),
|
||||||
telemetry: telemetry.clone(),
|
telemetry: telemetry.clone(),
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
@@ -1378,7 +1398,7 @@ async fn execute_stream_from_frame_stream(
|
|||||||
if provider_body_truncated {
|
if provider_body_truncated {
|
||||||
&[]
|
&[]
|
||||||
} else {
|
} else {
|
||||||
&provider_buffered_body
|
provider_buffered_body.make_contiguous()
|
||||||
},
|
},
|
||||||
candidate_started_unix_secs_for_report,
|
candidate_started_unix_secs_for_report,
|
||||||
failure,
|
failure,
|
||||||
@@ -1394,9 +1414,13 @@ async fn execute_stream_from_frame_stream(
|
|||||||
status_code,
|
status_code,
|
||||||
headers: headers_for_report.clone(),
|
headers: headers_for_report.clone(),
|
||||||
provider_body_base64: (!provider_body_truncated && !provider_buffered_body.is_empty())
|
provider_body_base64: (!provider_body_truncated && !provider_buffered_body.is_empty())
|
||||||
.then(|| base64::engine::general_purpose::STANDARD.encode(&provider_buffered_body)),
|
.then(|| {
|
||||||
client_body_base64: (!client_body_truncated && !buffered_body.is_empty())
|
base64::engine::general_purpose::STANDARD
|
||||||
.then(|| base64::engine::general_purpose::STANDARD.encode(&buffered_body)),
|
.encode(provider_buffered_body.make_contiguous())
|
||||||
|
}),
|
||||||
|
client_body_base64: (!client_body_truncated && !buffered_body.is_empty()).then(|| {
|
||||||
|
base64::engine::general_purpose::STANDARD.encode(buffered_body.make_contiguous())
|
||||||
|
}),
|
||||||
telemetry: telemetry.clone(),
|
telemetry: telemetry.clone(),
|
||||||
};
|
};
|
||||||
record_stream_terminal_usage(
|
record_stream_terminal_usage(
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ impl Default for PostgresPoolConfig {
|
|||||||
Self {
|
Self {
|
||||||
database_url: String::new(),
|
database_url: String::new(),
|
||||||
min_connections: 1,
|
min_connections: 1,
|
||||||
max_connections: 30,
|
max_connections: 50,
|
||||||
acquire_timeout_ms: 3_000,
|
acquire_timeout_ms: 3_000,
|
||||||
idle_timeout_ms: 60_000,
|
idle_timeout_ms: 60_000,
|
||||||
max_lifetime_ms: 30 * 60_000,
|
max_lifetime_ms: 30 * 60_000,
|
||||||
|
|||||||
Reference in New Issue
Block a user