-
Notifications
You must be signed in to change notification settings - Fork 614
[PERFORMANCE]: Configure HTTP Client Connection Pool Limits #1676
Copy link
Copy link
Labels
enhancementNew feature or requestNew feature or requestperformancePerformance related itemsPerformance related itemspythonPython / backend development (FastAPI)Python / backend development (FastAPI)
Milestone
Description
Configure HTTP client connection pool limits to prevent connection exhaustion and improve reliability. Many places create new httpx.AsyncClient instances per request, preventing connection reuse.
Current State Analysis
Already Optimized (Persistent Clients)
These services correctly create a persistent HTTP client:
| Location | Code | Status |
|---|---|---|
mcpgateway/utils/retry_manager.py:273 |
self.client = httpx.AsyncClient(**self.client_args) |
Good |
mcpgateway/federation/forward.py:101 |
self._http_client = httpx.AsyncClient(...) |
Good |
mcpgateway/services/server_service.py:135 |
self._http_client = httpx.AsyncClient(...) |
Good |
mcpgateway/federation/discovery.py:284 |
self._http_client = httpx.AsyncClient(...) |
Good |
mcpgateway/services/llm_proxy_service.py:73 |
self._client = httpx.AsyncClient(...) |
Good |
Problem Areas (New Client Per Request)
These files create new clients per request, preventing connection reuse:
| Location | Line | Context |
|---|---|---|
mcpgateway/translate.py |
1174, 1331, 1582, 1698 | HTTP-to-MCP translation |
mcpgateway/routers/llm_admin_router.py |
691 | LLM admin operations |
mcpgateway/services/llm_provider_service.py |
647 | LLM provider checks |
mcpgateway/services/sso_service.py |
460, 479 | SSO token exchange |
mcpgateway/services/tool_service.py |
2649 | Tool HTTP invocation |
mcpgateway/utils/keycloak_discovery.py |
47 | OIDC discovery |
mcpgateway/services/catalog_service.py |
424 | Catalog fetching |
mcpgateway/services/a2a_service.py |
856 | Agent-to-agent calls |
mcpgateway/services/gateway_service.py |
2664 | Gateway peer communication |
Example Problem Pattern
# Found in translate.py:1174, sso_service.py:460, etc.
async with httpx.AsyncClient(headers=headers, timeout=...) as client:
response = await client.get(url)
# Client is closed immediately after - no connection reuse!Proposed Solution
Create a shared HTTP client factory:
# mcpgateway/utils/http_client.py
from functools import lru_cache
import httpx
@lru_cache
def get_http_client() -> httpx.AsyncClient:
return httpx.AsyncClient(
limits=httpx.Limits(
max_keepalive_connections=100,
max_connections=200,
keepalive_expiry=30.0,
),
timeout=httpx.Timeout(30.0, connect=10.0),
)Configuration
HTTP_CLIENT_MAX_KEEPALIVE=100
HTTP_CLIENT_MAX_CONNECTIONS=200
HTTP_CLIENT_KEEPALIVE_EXPIRY=30.0
HTTP_CLIENT_TIMEOUT=30.0
HTTP_CLIENT_CONNECT_TIMEOUT=10.0Acceptance Criteria
- Shared HTTP client factory created
- Problem files updated to use shared client
- Connection pool limits configurable via environment
- Lifespan cleanup in main.py
- Connection pool metrics exposed
- All HTTP-related tests pass
- Passes
make verify
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or requestperformancePerformance related itemsPerformance related itemspythonPython / backend development (FastAPI)Python / backend development (FastAPI)