
LMCache 扩展 HTTP API 实战指南基于 HTTPAPIRegistry 的零代码改动端点注册机制【免费下载链接】LMCacheLMCache: Supercharge Your LLM with the Fastest KV Cache Layer项目地址: https://gitcode.com/GitHub_Trending/lm/LMCache本篇技术指南面向需要为 LMCache 多进程 HTTP 服务lmcache server增加自定义 REST 端点的开发者核心讲解其零代码改动的端点扩展框架只需在http_apis/目录新增一个以_api.py结尾、暴露 FastAPIAPIRouter的模块服务启动时HTTPAPIRegistry便会自动发现并挂载该路由无需改动任何既有源码。读完本文你将掌握自动发现机制的底层实现pkgutil扫描与importlib导入、模块契约must / should / must not、通过app.state访问共享状态的方法以及仓库内置的依赖注入与集中式错误处理设施。扩展框架概述一个文件零改动LMCache 的多进程 HTTP 前端由 http_server.py 承载它基于 FastAPI 构建应用。该服务把所有路由注册工作全部委托给HTTPAPIRegistry完成# lmcache/v1/multiprocess/http_server.py app FastAPI(titleLMCache HTTP API, version1.0.0, lifespanlifespan) # Automatically discover and register all HTTP API endpoints registry HTTPAPIRegistry(app) registry.register_all_apis()这意味着添加新端点不需要触碰http_server.py、http_api_registry.py或任何既有模块。一个端点就是一个放置在lmcache/v1/multiprocess/http_apis/目录下、文件名以_api.py结尾的普通 Python 模块模块内暴露一个名为router的 FastAPIAPIRouter即可。这套零修改扩展模式与 L2 适配器L2 适配器文档使用的插件体系一脉相承其完整设计文档位于 docs/design/v1/multiprocess/http_api_extension.md。内置端点一览在深入了解机制之前先看仓库中遵循同一约定实现的内置模块源码位于 lmcache/v1/multiprocess/http_apis/模块端点方法说明info_api.py/GET基础存活检查livenessinfo_api.py/healthcheckGETKubernetes 探针端点info_api.py/statusGET内部状态报告cache_api.py/cache/clearPOST强制清空 L1 缓存config_api.py/configGET服务端配置信息导出以 info_api.py 为例可以看到它忠实地实践了本文将要介绍的全部约定模块级router APIRouter()、通过request.app.state访问引擎、引擎未初始化时返回 503# lmcache/v1/multiprocess/http_apis/info_api.py router APIRouter() router.get(/) async def root() - dict[str, str]: Basic liveness check endpoint. return {status: ok, service: LMCache HTTP API} router.get(/healthcheck) async def healthcheck(request: Request) - Any: Health check endpoint for k8s liveness/readiness probes. engine getattr(request.app.state, engine, None) if engine is None: return JSONResponse( status_code503, content{status: unhealthy, reason: engine not initialized}, ) return {status: healthy}此外info_api.py还通过router.include_router(_version_router)把内部 API 服务器中的版本路由/version、/lmc_version、/commit_id重暴露到本服务上展示了复用既有 router的另一种扩展手法。当前仓库的http_apis/目录还包含common_api.py、quota_api.py、reconfigure_api.py等更多内置模块而dependencies.py、error_handlers.py、schemas.py因不以_api结尾不会被自动发现它们是被_api模块显式导入的辅助设施。自动发现机制HTTPAPIRegistry 工作原理HTTPAPIRegistry位于 http_api_registry.py其核心逻辑极简class HTTPAPIRegistry: def __init__(self, app: FastAPI): self.app app self.router APIRouter() def register_all_apis(self) - None: apis_path Path(__file__).parent / http_apis if not apis_path.exists(): logger.warning(http_apis directory not found) return apis_package f{__package__}.http_apis for r in discover_api_routers(apis_path, apis_package): self.router.include_router(r) self.app.include_router(self.router)真正的扫描与导入工作由通用的 router_discovery.py 中的discover_api_routers()完成其步骤如下用pkgutil.iter_modules([str(search_path)])遍历http_apis/目录下的所有模块只保留文件名以_api结尾的模块suffix参数可配置默认_api对每个候选模块调用importlib.import_module(full_name)完成导入检查模块是否具有router属性且该属性是fastapi.APIRouter实例符合条件则收集。# lmcache/v1/utils/router_discovery.py for _, module_name, _ in pkgutil.iter_modules([str(search_path)]): if not module_name.endswith(suffix): continue if module_name in excluded: logger.info(Skipping excluded API module: %s, module_name) continue full_name f{package_name}.{module_name} module importlib.import_module(full_name) if hasattr(module, router) and isinstance(module.router, APIRouter): routers.append(module.router) logger.info(Discovered API module: %s, module_name)discover_api_routers还支持exclude参数一个可迭代的模块名集合便于宿主包只注册部分 router例如{run_script_api}。设计文档 docs/design/v1/multiprocess/http_api_extension.md 中给出了完整的发现流程图http_server.py → HTTPAPIRegistry(app) → register_all_apis() → pkgutil 扫描 → include_router新增模块my_new_api与内置模块走完全相同的路径无需任何手工注册。添加新端点从创建模块到生效步骤 1创建模块文件。在lmcache/v1/multiprocess/http_apis/下新建一个以_api.py结尾的文件并在模块顶层定义router# lmcache/v1/multiprocess/http_apis/metrics_api.py # SPDX-License-Identifier: Apache-2.0 from fastapi import APIRouter, Request from fastapi.responses import JSONResponse router APIRouter() router.get(/metrics) async def metrics(request: Request): Return cache hit/miss metrics. engine getattr(request.app.state, engine, None) if engine is None: return JSONResponse( status_code503, content{error: engine not initialized}, ) return {hits: 42, misses: 7}步骤 2重启服务。以上即全部工作。下一次lmcache server启动时HTTPAPIRegistry会自动发现metrics_api模块并挂载/metrics端点其他任何文件都无需改动。上述示例同时示范了两条重要实践通过request.app.state.engine判断引擎是否就绪、未就绪时以 503 响应——这与内置/healthcheck的处理方式完全一致。注意模块必须带SPDX-License-Identifier: Apache-2.0头仓库所有源码文件均遵循此约定并遵守仓库的导入顺序规范Standard → Third Party → First Party。模块契约必须、应当与禁止为保持扩展的一致性和可靠性仓库对 API 模块约定了明确的行为边界必须must位于lmcache/v1/multiprocess/http_apis/目录内文件名以_api.py结尾暴露模块级router其类型为fastapi.APIRouter。应当should通过检查request.app.state.engine防护未初始化状态引擎为None时返回 503使用lmcache.logging.init_logger(__name__)获取日志器仓库日志设施见 lmcache/logging.py使用async处理器避免阻塞 I/O。对于 CPU 密集型或慢操作可以参考内置cache_api.py中/cache/checksums的做法——用asyncio.get_running_loop().run_in_executor(None, ...)把计算任务交给线程池保持事件循环不被阻塞。禁止must not直接导入或修改http_server.py中的app对象。路由挂载完全由注册表负责模块内部不应与全局app产生耦合在端点处理器中执行阻塞式 I/O。访问共享状态app.state 与依赖注入app.state是 FastAPI 应用在启动生命周期lifespan阶段填充的共享上下文端点处理器通过Request对象访问它。从 http_server.py 的lifespan可以看到服务启动时依次注入的属性属性类型说明app.state.zmq_serverZMQ server 实例底层多进程 ZMQ 服务器app.state.engine缓存引擎实例主 KV 缓存引擎负责 KV 操作app.state.contextMPHTTPContext类型化的服务上下文见下文app.state.plugin_launcher运行时插件启动器运行时插件管理app.state.coordinator_client/app.state.coordinator_registration_taskhttpx 客户端 / 任务MP 协调器注册相关在自定义端点中这样使用router.get(/my-endpoint) async def my_endpoint(request: Request): engine request.app.state.engine # main cache engine zmq_server request.app.state.zmq_server # underlying ZMQ server ...推荐路径使用依赖注入。仓库内置的 dependencies.py 提供了更规范的访问方式lifespan启动完成后调用build_context(engine)构造类型化的MPHTTPContext封装了engine、ObjectService、PrefetchService三个协作对象端点通过get_context(request)获取。get_context会在上下文尚不存在时例如请求与启动竞态抛出 503 的HTTPExceptiondef get_context(request: Request) - MPHTTPContext: context getattr(request.app.state, context, None) if context is None: raise HTTPException( status_codeHTTPStatus.SERVICE_UNAVAILABLE, detailserver not initialized, ) return context内置的 cache_api.py 就是这一模式的典型使用者/cache/objects列出/删除 L1/L2 缓存对象、/cache/prefetches提交/轮询预热任务均为对ObjectService/PrefetchService的透传调用而/cache/clear强制清空 L1 缓存请求体可缺省缺省等价于{tier: l1, force: true}与/cache/checksums按 KV block 计算 MD5 校验和则直接操作引擎内部。这些内置端点还揭示了另一个设计要点路由内无需 try/except——领域错误由集中的异常处理器统一映射为 HTTP 状态码。集中式错误处理领域错误到 HTTP 状态码由于自动发现机制只负责收集 router异常处理器需要在应用级注册。error_handlers.py 是领域错误词汇与 HTTP 状态码词汇唯一的映射点_STATUS_BY_ERROR: dict[type[CacheControlError], HTTPStatus] { InvalidRequest: HTTPStatus.BAD_REQUEST, # 400 NotFound: HTTPStatus.NOT_FOUND, # 404 Unavailable: HTTPStatus.SERVICE_UNAVAILABLE, # 503 }register_error_handlers(app)在http_server.py模块级调用app.add_exception_handler(CacheControlError, _handle)基于 Starlette 按异常 MRO 匹配的特性对CacheControlError基类注册单个处理器即可覆盖其全部子类。因此你的自定义端点如果复用cache_control服务并抛出领域异常会自动获得统一的{detail: ...}响应体与状态码无需自行处理——这与端点模块不感知 HTTP 层的分层思想一致。小结LMCache 的 HTTP API 扩展框架把扩展成本压缩到了最低一个_api.py文件 一个router属性即可获得完整的自动发现、注册、错误映射与共享状态访问能力。这套机制与 L2 适配器、内部 API 服务器共享同一零修改扩展设计原则其设计文档 docs/design/v1/multiprocess/http_api_extension.md 是深入了解的入口。实践要点回顾新增端点 在lmcache/v1/multiprocess/http_apis/新建*_api.py模块并暴露router无需改动任何既有代码发现链路由http_server.py → HTTPAPIRegistry → discover_api_routerspkgutilimportlib完成访问共享状态优先使用get_context(request)并对未初始化状态返回 503遵循模块契约must / should / must not保持端点async、非阻塞并交由集中式错误处理器完成领域错误到 HTTP 状态码的映射。【免费下载链接】LMCacheLMCache: Supercharge Your LLM with the Fastest KV Cache Layer项目地址: https://gitcode.com/GitHub_Trending/lm/LMCache创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考