From a87e1c13159c6b1594de2ba04929b0dd3639caa2 Mon Sep 17 00:00:00 2001 From: Hang Yin Date: Tue, 14 Apr 2026 23:08:40 +0000 Subject: [PATCH] fix(ingress): eliminate 5s latency from HAProxy evidence routing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The evidence-server routing used payload(0,0) to inspect request bytes. Per HAProxy docs, length=0 means "extract to end of buffer", which in TCP mode defers rule evaluation until the full inspect-delay (5s) expires — HAProxy cannot know when a raw TCP stream ends. This added a 5-second latency to every TLS connection, making the service appear broken for users. Fix: use payload(0,16) with a concrete byte count (16 = len of "HEAD /evidences", the longest prefix matched) and accept once req.len >= 16. After SSL termination a full TLS record is decrypted atomically, so these 16 bytes arrive instantly. Before: ~5.2s per request (TLS 0.2s + inspect-delay 5.0s) After: ~0.28s per request (TLS 0.2s + routing ~0.04s) Tested on a live Phala CVM with Route53 DNS — both normal requests and /evidences endpoint verified working. Co-Authored-By: Claude Opus 4.6 --- .../dstack-ingress/scripts/entrypoint.sh | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/custom-domain/dstack-ingress/scripts/entrypoint.sh b/custom-domain/dstack-ingress/scripts/entrypoint.sh index 560418b..2f1eed9 100644 --- a/custom-domain/dstack-ingress/scripts/entrypoint.sh +++ b/custom-domain/dstack-ingress/scripts/entrypoint.sh @@ -156,14 +156,16 @@ EOF cat <<'EVIDENCE_BLOCK' >>/etc/haproxy/haproxy.cfg # Route /evidences requests to the local evidence HTTP server. - # inspect-delay sets the upper bound for buffering; the accept rule - # fires as soon as any application data is present in the buffer - # (after SSL termination a full TLS record is decrypted atomically, - # so the complete HTTP request is available on first evaluation). + # accept fires once 16 bytes have arrived — enough for the + # longest prefix we match ("HEAD /evidences" = 16 chars). + # Using req.len with a concrete threshold is critical: the + # previous payload(0,0) (length 0 = "whole buffer") deferred + # evaluation until the full inspect-delay because HAProxy + # cannot know when a TCP stream ends. tcp-request inspect-delay 5s - tcp-request content accept if { req.len gt 0 } - acl is_evidence payload(0,0) -m beg "GET /evidences" - acl is_evidence payload(0,0) -m beg "HEAD /evidences" + tcp-request content accept if { req.len ge 16 } + acl is_evidence payload(0,16) -m beg "GET /evidences" + acl is_evidence payload(0,16) -m beg "HEAD /evidences" use_backend be_evidence if is_evidence EVIDENCE_BLOCK fi