HTTP API#

当 MP 服务器通过 lmcache server 启动时(推荐的入口点),会暴露一个基于 FastAPI 的 HTTP 前端,以及 vLLM 使用的 ZMQ 套接字。此 HTTP API 旨在供操作员、编排者(例如 Kubernetes)和调试工具使用——它**不**在推理数据路径上。

新的端点会自动从 lmcache/v1/multiprocess/http_apis/ 注册:任何名为 *_api.py 的模块,只要暴露一个模块级的 ``router``(一个 fastapi.APIRouter),在启动时都会被发现。

lmcache/v1/internal_api_server/common/ 下定义的部分路由也在此 HTTP 服务器上暴露。模块 lmcache/v1/multiprocess/http_apis/common_api.py 聚合了这些路由(跳过在 _MP_INCOMPATIBLE_MODULES 中列出的模块,例如 run_script_api),并将它们转发到自动发现管道。因此,在 internal_api_server/common 下添加一个新的兼容模块不需要在 MP 端进行接线更改。

服务器配置#

参数

默认

描述

--http-host

0.0.0.0

绑定 HTTP 服务器的主机。

--http-port

8080

绑定 HTTP 服务器的端口。

示例:

lmcache server \
    --l1-size-gb 100 --eviction-policy LRU \
    --http-host 0.0.0.0 --http-port 8080

以下所有示例都假设服务器可以通过 http://localhost:8080 访问。

端点#

下表按目的对路由进行了分组。操作接口(健康检查、状态、缓存控制)在顶层路径中暴露。来自共享 internal_api_server 包的路由保持在其原始路径上,以便与 vLLM 嵌入的 API 服务器兼容。

方法

路径

目的

获取

/

基本存活探测。

获取

/healthcheck

K8s 存活/就绪探针。

获取

/status

详细的引擎状态以供检查和调试。

POST

/clear-cache

强制清除 L1 (CPU) 内存中的所有 KV 数据。

获取

/quota

列出每个注册的 cache_salt 配额及其实时使用情况。

PUT

/quota/{cache_salt}

设置或更新 cache_salt 的配额(以 GB 为单位)。

获取

/quota/{cache_salt}

读取单个 cache_salt 的配额和实时使用情况。

删除

/quota/{cache_salt}

移除 cache_salt 的配额条目(其数据将在下一个周期被逐出)。

获取

/conf

转储合并的服务器配置(mp、存储管理器、可观察性)。

获取

/version

完整版本描述符(软件包版本 + 提交 ID)。

获取

/lmc_version

LMCache 包版本字符串。

获取

/commit_id

当前构建提交 ID。

获取

/env

转储进程环境变量(JSON,纯文本)。

获取

/loglevel

列出或检查日志记录器级别;也接受 level 以进行修改。

获取

/metrics

Prometheus 展示格式。

POST

/metrics/reset

重置所有可观察性指标为其初始状态。

获取

/threads

列出活动的 Python 线程及其堆栈跟踪。

获取

/periodic-threads

列出注册的周期性线程及其摘要计数。

获取

/periodic-threads/{thread_name}

单个周期线程的详细状态。

获取

/periodic-threads-health

对关键/高层周期线程的快速健康检查。

GET /#

基本的存活检查。返回一个静态负载,指示 HTTP 服务器正在运行。对于还验证缓存引擎是否初始化的探测,请使用 /healthcheck

响应 (200 OK):

{
  "status": "ok",
  "service": "LMCache HTTP API"
}

示例:

curl -s http://localhost:8080/

GET /healthcheck#

健康检查端点适用于 Kubernetes 的存活和就绪探针。200 响应意味着 HTTP 服务器处于活动状态 并且 MP 缓存引擎已初始化。503 响应表示引擎尚未准备好(仍在初始化中,或初始化失败)。

响应 (200 OK):

{
  "status": "healthy"
}

响应 (503 服务不可用):

{
  "status": "unhealthy",
  "reason": "engine not initialized"
}

示例:

curl -s http://localhost:8080/healthcheck

Kubernetes 探针代码片段:

livenessProbe:
  httpGet:
    path: /healthcheck
    port: 8080
  initialDelaySeconds: 10
  periodSeconds: 10
readinessProbe:
  httpGet:
    path: /healthcheck
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 5

GET /status#

返回 MP 引擎内部状态的详细快照:L1 缓存、L2 适配器、注册的 GPU 上下文、活动会话和正在进行的预取任务。旨在供操作员和调试使用,而非监控(请使用 Prometheus 指标获取时间序列数据 — 参见 可观察性)。

响应 (200 OK):

{
  "is_healthy": true,
  "engine_type": "MPCacheEngine",
  "chunk_size": 256,
  "hash_algorithm": "builtin-hash",
  "registered_gpu_ids": [0, 1],
  "gpu_context_meta": {
    "0": {
      "model_name": "meta-llama/Llama-3.1-8B-Instruct",
      "world_size": 1,
      "kv_cache_layout": {
        "num_layers": 32,
        "block_size": 16,
        "hidden_dim_sizes": "...",
        "dtype": "torch.bfloat16",
        "is_mla": false,
        "num_blocks": 12345,
        "gpu_kv_format": "...",
        "gpu_kv_shape": "...",
        "gpu_kv_concrete_shape": "...",
        "attention_backend": "...",
        "cache_size_per_token": 131072
      }
    }
  },
  "active_sessions": 2,
  "active_prefetch_jobs": 0,
  "storage_manager": {
    "is_healthy": true,
    "...": "backend-specific fields"
  }
}

响应 (503 服务不可用) 当引擎尚未初始化时:

{
  "error": "engine not initialized"
}

示例:

curl -s http://localhost:8080/status | jq

POST /clear-cache#

强制清除当前保存在 L1 (CPU) 内存中的 所有 KV Cache 数据。

警告

此端点是破坏性的,并绕过读/写锁。正在进行的存储或预取操作可能会被损坏。仅在服务器空闲时或从已知的坏缓存状态恢复时使用。

请求体将被忽略。

响应 (200 OK):

{
  "status": "ok"
}

响应 (503 服务不可用):

{
  "status": "error",
  "reason": "engine not initialized"
}

示例:

curl -s -X POST http://localhost:8080/clear-cache

/quota — 每个``cache_salt``的配额管理#

这些端点管理由 IsolatedLRU 逐出策略(通过 --eviction-policy IsolatedLRU 选择)消耗的每个 cache_salt 存储预算。配额是 软性 的:设置限制并不会拒绝写入 — 任何超出预算的 cache_salt 会在下一个逐出周期(约 1 秒)被逐出。没有注册配额的 cache_salt 有一个有效限制为 0 字节,因此其数据将在下一个周期被清除(白名单语义)。

这些端点在未使用 --eviction-policy IsolatedLRU 启动的引擎上是无操作的:QuotaManager 仍然存在,但 LRU 策略会忽略注册的配额。

空盐的 URL 转义。 cache_salt=\"\"``(无盐 / 匿名流量)不能出现在 URL 路径参数中,因此 API 接受哨兵 ``_default 作为替代。PUT /quota/_default 设置 cache_salt=\"\" 的配额。合法存储数据的用户使用 cache_salt=\"_default\",无法通过此 HTTP API 与匿名流量区分管理——两者映射到相同的路径参数;选择任何其他值(例如 \"default\")以消除歧义。

PUT /quota/{cache_salt}#

创建或更新配额。

主体: {\"limit_gb\": <float>} (必需,有限,非负)。

响应 (200 OK):

{"cache_salt": "alice", "limit_gb": 10.0, "status": "ok"}

错误: 400 表示 JSON 格式错误、缺少 limit_gblimit_gb 不是数字、nan / inf 或负值;503 表示引擎未初始化。

示例:

curl -s -X PUT http://localhost:8080/quota/alice \
    -H 'Content-Type: application/json' \
    -d '{"limit_gb": 10.0}'

GET /quota/{cache_salt}#

读取当前配额和一个 cache_salt 的实时使用情况。

响应 (200 OK):

{
  "cache_salt": "alice",
  "limit_gb": 10.0,
  "current_usage_gb": 2.137,
  "exists": true
}

existsfalse 当该 cache_salt 从未注册过配额时(limit_gb 此时为 0.0,而 current_usage_gb 反映当前为该盐缓存的字节数——这些字节将在下一个周期根据 IsolatedLRU 被逐出)。

DELETE /quota/{cache_salt}#

删除 cache_salt 的配额条目。任何仍然缓存于此 cache_salt 下的字节将在下一个逐出周期中超出预算(有效限制降至 0),并将被逐出。

响应 (200 OK):

{"cache_salt": "alice", "status": "removed"}

当给定的 cache_salt 没有注册配额时,响应为 {\"cache_salt\": \"...\", \"status\": \"not_found\"}``(仍然是 ``200 OK)。

GET /quota#

列出每个注册的配额及其实时使用情况。

响应 (200 OK):

{
  "users": {
    "alice": {"limit_gb": 10.0, "current_usage_gb": 2.137},
    "bob":   {"limit_gb":  4.0, "current_usage_gb": 0.812}
  }
}

GET /conf#

返回在 app.state.configs 上注册的每个服务器端配置对象(通常是 mpstorage_managerobservability),作为一个单一的缩进 JSON 文档。数据类通过 safe_asdict 序列化;其他值通过 make_json_safe 处理。对于确认进程实际加载的内容(包括环境覆盖)非常有用,而无需重启。

响应 (200 OK):

{
  "mp": {
    "http_host": "0.0.0.0",
    "http_port": 8080,
    "...": "..."
  },
  "storage_manager": {
    "...": "..."
  },
  "observability": {
    "...": "..."
  }
}

**响应**(503 服务不可用),当配置尚未连接到 app.state 时:

{
  "error": "configs not initialized"
}

示例:

curl -s http://localhost:8080/conf | jq

GET /version#

返回完整的版本描述符(软件包版本与当前提交 ID 的组合),格式由 lmcache.utils.get_version() 生成。

响应 (200 OK):

"0.3.x+<commit-id>"

示例:

curl -s http://localhost:8080/version

GET /lmc_version#

返回原始的 LMCache 包版本字符串 (lmcache.utils.VERSION)。

示例:

curl -s http://localhost:8080/lmc_version

GET /commit_id#

返回构建中嵌入的 git 提交 id (lmcache.utils.COMMIT_ID)。

示例:

curl -s http://localhost:8080/commit_id

GET /env#

将进程环境变量转储为排序的、格式良好的 JSON 文档。响应的 Content-Typetext/plain,因此可以直接通过管道传输到终端。

警告

有效负载可能包含通过环境变量注入的机密。在生产环境中限制对该端点的网络访问。

示例:

curl -s http://localhost:8080/env

GET /loglevel#

在运行时检查或修改 Python 日志记录器级别。所有响应都是 text/plain。该端点有三种模式,由查询参数驱动:

查询

行为

(无参数)

列出所有在 logging 中注册的记录器及其级别。

?logger_name=<name>

返回指定记录器的有效级别。

?logger_name=<name>&level=<LEVEL>

将命名的日志记录器(及其处理程序)设置为 LEVEL``(``DEBUG/INFO/WARNING/ERROR/CRITICAL)。在未知级别时返回 400

示例:

# list everything
curl -s http://localhost:8080/loglevel

# read one
curl -s 'http://localhost:8080/loglevel?logger_name=lmcache'

# elevate to DEBUG
curl -s 'http://localhost:8080/loglevel?logger_name=lmcache&level=DEBUG'

GET /metrics#

默认 prometheus_client 注册表中注册的每个指标的 Prometheus 展示格式。直接从 Prometheus 抓取此内容。有关导出指标的列表,请参见 可观察性

示例:

curl -s http://localhost:8080/metrics

POST /metrics/reset#

重置所有 LMCache 可观察性指标到其初始状态(reset_observability_metrics)。旨在用于测试工具和基准测试——不适用于生产环境。

响应 (200 OK):

ok

示例:

curl -s -X POST http://localhost:8080/metrics/reset

GET /threads#

列出服务器进程中活动的 Python 线程及其堆栈跟踪,并提供总计摘要。这对于实时调试挂起或失控的工作线程非常有用。

查询

行为

?name=<substr>

仅保留名称包含 <substr> 的线程(不区分大小写)。

?thread_id=<int>

只保留与匹配的 ident 相关的线程。

示例:

curl -s 'http://localhost:8080/threads?name=periodic'

GET /periodic-threads#

返回 PeriodicThreadRegistry 的 JSON 快照:按级别统计以及每个线程的状态(上次运行时间戳、最新摘要等)。

查询

行为

?level=critical|high|medium|low

仅包含给定级别的线程。对未知情况返回 400

?running_only=true

仅包含当前正在运行的线程。

?active_only=true

仅包括被视为活动的线程(最近的滴答)。

响应 (200 OK):

{
  "summary": {
    "total_count": 4,
    "running_count": 4,
    "active_count": 4,
    "by_level": {"critical": 1, "high": 2, "medium": 1, "low": 0}
  },
  "threads": [
    {"name": "...", "level": "high", "is_running": true, "...": "..."}
  ]
}

示例:

curl -s 'http://localhost:8080/periodic-threads?level=critical' | jq

GET /periodic-threads/{thread_name}#

单个周期性线程的详细状态(如果未找到则返回 404)。

示例:

curl -s http://localhost:8080/periodic-threads/storage-flush | jq

GET /periodic-threads-health#

快速健康检查仅覆盖 criticalhigh 级别的周期性线程。当线程被标记为正在运行但在预期间隔内未进行滴答时,它会被标记为不健康。

响应 (200 OK):

{
  "healthy": true,
  "unhealthy_count": 0,
  "unhealthy_threads": []
}

当某些东西滞后时:

{
  "healthy": false,
  "unhealthy_count": 1,
  "unhealthy_threads": [
    {
      "name": "storage-flush",
      "level": "critical",
      "last_run_ago": 42.5,
      "interval": 5.0
    }
  ]
}

示例:

curl -s http://localhost:8080/periodic-threads-health

添加新端点#

端点会从 lmcache/v1/multiprocess/http_apis/ 自动发现。要添加一个新端点:

  1. 在该目录中创建一个名为 <name>_api.py 的新模块。

  2. 定义一个模块级的 router = APIRouter()

  3. 使用 FastAPI 装饰器在 router 上注册处理程序。

  4. 通过 request.app.state.engine 访问引擎,并检查 None 情况(引擎尚未初始化)。

HTTPAPIRegistry 将在启动时自动加载模块 — 无需编辑中央注册列表。

如果路由足够通用,可以与嵌入 vLLM 的 API 服务器共享,请将其添加到 lmcache/v1/internal_api_server/common/ 下。它将在 MP 端通过 common_api.py 被识别,除非其模块名称在 _MP_INCOMPATIBLE_MODULES 中列出(用于需要 vLLM 特定 app.state 属性的模块,例如 run_script_api)。

添加新端点时,请在此页面上添加一个匹配的部分,记录端点的目的、请求/响应架构以及一个示例 curl 调用。