ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

Vercel Python Runtime 演进全景:vercel-runtime 从 0.1.0 到 0.17.0 的架构升级与实战要点

Vercel Python Runtime 演进全景:vercel-runtime 从 0.1.0 到 0.17.0 的架构升级与实战要点 CLI后端云原生【免费下载链接】vercelDevelop. Preview. Ship.项目地址https://gitcode.com/gh_mirrors/ve/vercel点击查看免费下载vercel-runtime 是运行于 Vercel Compute 之上的 Python 函数运行时桥接层为 ASGI/WSGI 应用提供服务器实现、可观测性、日志与平台集成能力。本文以 python/vercel-runtime/CHANGELOG.md 为脉络结合 python/vercel-runtime/src/vercel_runtime/ 的源码实现与测试用例系统梳理该包从 0.1.0 到 0.17.0 的每一次能力升级WebSocket、队列订阅、Cron、Worker 服务、运行时缓存、冷启动优化与依赖 vendoring帮助读者既掌握配置与调用方式也理解底层实现原理。一、包定位与总体架构python/vercel-runtime/README.md 明确了该包的使命提供在 Vercel Compute 上运行 Python 应用所需的桥接具体包含 ASGI/WSGI 服务器实现、可观测性、日志与平台集成。从 pyproject.toml 可见其关键约束包名vercel-runtime当前版本 0.17.0要求requires-python 3.12构建后端为uv_builduv_build0.10.11,0.11与 0.11.0 中升级 uv 到 v0.10.11的变更直接对应运行时依赖uvicorn、werkzeug 等被 vendoring 进src/vercel_runtime/_vendor/避免与用户项目的依赖版本冲突重新同步执行./python/vercel-runtime/scripts/vendor.sh[tool.uv]中exclude-newer 2 days与 0.14.0 的 Patch 变更一致uv sync --inexact --frozen则是 0.5.0 冷启动优化的产物。源码目录src/vercel_runtime/下的核心模块构成运行时骨架模块职责vc_init.py平台侧IPC 模式入口模块导入、应用类型探测、请求生命周期、日志挂钩dev.py本地vercel dev入口静态资源、Django 静态文件、uvicorn/werkzeug 启动asgi.pyASGI 类型定义与公共辅助读请求体、发 JSON 响应resolver.py应用导入与 ASGI/WSGI 自动探测routing.py服务路由前缀剥离对应 0.4.3crons.pyCron 服务引导与多路由分发workers.pyWorker 服务与队列集成激活cache.py运行时缓存上下文注入对应 0.14.0headers.pyOIDC 头处理对应 0.13.2与请求头规范化wsgi_websocket.pyWSGI WebSocket 升级对应 0.16.0从 vc_init.py 可以看到运行时与平台通信的基石当存在VERCEL_IPC_PATH环境变量时运行时建立 UNIX 域套接字连接通过 NUL 分隔的 JSON 消息与 functions runtime 通信send_message支持log、metric、handler-started、end、unrecoverable-error等消息类型。平台侧还内置/_vercel/ping健康检查响应ASGI 与 WSGI 两套路径均有实现。二、0.17.0Python 队列与工作流全面迁移到 vercel-queue SDK0.17.0 是最近一次 Minor 变更PR 17ee736将 Python 队列订阅者queue subscribers与工作流workflows的集成从 vercel-workers 迁移到新的 vercel-queue SDK。变更点可以归纳为四条主线1.[[tool.vercel.subscribers]]构建期内省与服务化入口点在构建期通过vercel.queue.get_subscriptions()被内省生成vercel.queue.asgi_app()handler 模块来服务流量触达类型queue/v2beta携带 SDK 注册的消费组consumer groups与每个订阅的调优参数对应源码bootstrap_queue_service_app()在 workers.py 中导入vercel.queue并调用其asgi_app()若缺少vercel-queue包则抛出明确错误。2. Celery / Dramatiq 集成包自动注入构建产物与vercel dev中会自动注入匹配的vercel-celery/vercel-dramatiq集成包bundled 变体除非项目显式依赖vercel-queue底层由install_queue_integrations()实现见 workers.py构建器通过环境变量VERCEL_QUEUE_INTEGRATIONS传入module:installer[:serving_activator]格式的条目逗号分隔运行时依次调用 installerqueue_servingFalse时只激活发布侧能力传输注册、broker 默认值避免非 worker 函数启动嵌入 worker 导致运行时阻塞queue_servingTrue时再执行可选的 serving activator 激活消费侧。3. 工作流的分代处理依赖vercel 0.8.0的项目按新 SDK 生成与订阅者一致走 vercel-queue更旧或无法判明版本的项目保留 legacy vercel-workers 服务方式worker env 标记、注入固定版本的vercel-workers直接依赖vercel-workers的项目整体保留旧集成legacy 订阅 schema、直接入口服务、worker env 标记。4. dev 与构建侧的对齐vercel dev通过vercel.queue.asgi_app()服务队列 sidecar队列 broker 在 sidecar 启动时按 SDK 注册的消费组投递与生产触发行为一致legacy 项目继续走 vercel-workers 引导CLI 不再注入config.hasWorkerServices所有队列服务决策由 Python builder 依据项目元数据完成——这解释了 workers.py 中has_worker_services()读取VERCEL_HAS_WORKER_SERVICES的历史逻辑与is_dev_queue_serving()读取VERCEL_DEV_QUEUE_SERVING这一新路径的并存。三、WebSocket 支持ASGI 与 WSGI 双路径0.15.0 / 0.16.00.15.0PR fe6d98b通过 vendored wsproto 为 Python ASGI 应用加入 WebSocket 支持。vendored 的 wsproto 位于 src/vercel_runtime/_vendor/wsproto/对应 uvicorn 协议层中的websockets_impl.py实现。测试夹具 tests/fixtures/asgi_websocket_app.py 与 tests/fixtures/wsgi_websocket_app.py 分别覆盖两条路径。0.16.0PR ee389a1为 WSGI 应用如 Flask flask-sock补上 WebSocket运行时把原始连接套接字暴露在 WSGIenviron的werkzeug.socket/gunicorn.socket键中一旦写入101握手响应就结束请求生命周期让平台开始双向流式传输——这与 ASGI 的websocket.accept行为对齐。实现层面vc_init.py 的send_wrapper在 ASGI 路径下于websocket.accept、websocket.close或websocket.http.response.body完成时调用finish_request()结束handler-started/end的 IPC 生命周期WSGI 路径则在 vc_init.py 的_vc_fire_end_once中保证每个请求恰好发送一次 end 消息WebSocket 升级时在 101 写入后立即触发。attach_wsgi_websocket()来自 wsgi_websocket.py负责把原始 socket 注入 environ。四、WSGI 请求体与 chunked 解码0.14.20.14.2PR 76aeb97修复了 WSGI 请求体在没有Content-Length时以Transfer-Encoding: chunked到达的解码问题并按 PEP 3333 规范从 WSGI environ 中剥离 hop-by-hop 帧头。从 vc_init.py 的 WSGI handler 可以看到read_wsgi_request_body(self.rfile, self.headers)负责解析请求体非法体返回 400构建 environ 时显式跳过transfer-encoding头保证 PEP 3333 兼容。相关测试见 tests/test_request_body.py。五、运行时缓存为 Python 函数配置缓存0.14.00.14.0PR 4d56632为 Python 函数引入运行时缓存配置并附带exclude-newer 2 days防止解析到过新的依赖的补丁。运行时缓存的核心实现在 cache.py平台通过x-vercel-sc-*系列头传递缓存上下文x-vercel-sc-headers缓存请求头 JSON、x-vercel-sc-host、x-vercel-sc-basepath、x-vercel-sc-protocol、x-vercel-sc-runtime-cacheset_runtime_cache_from_asgi_pairs()/set_runtime_cache_from_http_headers()分别从 ASGI scope 与 WSGI 头中解析这些值调用_apply_cache_context()构造BuildCache与AsyncBuildCache实例并注入vercel.cache.context端点拼装为{protocol}://{host}{basepath}/v1/suspense-cache/见_build_endpoint()并携带x-vercel-internal-sc-client-name RUNTIME_CACHE标记对vercelSDK 旧版本 0.5.9做了set_context(cache...)的降级兼容vercel.cache采用可选导入未安装该 SDK 时静默跳过避免硬依赖请求结束时由clear_runtime_cache_context()清理见 vc_init.py 的finish_request()。此外x-vercel-sc-no-header-leak控制是否向业务代码隐藏内部头SC_HEADERS_ALWAYS_STRIP恒剥离x-vercel-sc-runtime-cache与SC_HEADERS_STRIP_ON_NO_LEAK仅在 no-leak 标记下剥离其余 sc 头两组集合定义在 cache.py。六、OIDC 令牌透传与头处理0.13.2 / 0.5.10.13.2PR 2767cb8在请求没有携带 request-scoped OIDC 头时将VERCEL_OIDC_TOKEN暴露为x-vercel-oidc-token请求头。实现位于 headers.pyget_oidc_token_for_request(has_public_oidc, internal_oidc_token)决定最终注入值append_oidc_header_if_missing()在 ASGI 中间件中补充缺省头见 vc_init.pyWSGI 路径在handle_one_request中同样处理并剥离内部头x-vercel-internal-*invocation-id、request-id、span-id、trace-id、OIDC。0.5.1 的fix typings则是类型标注层面的完善。七、Cron 服务动态声明、模块级入口与多路由分发0.5.6 / 0.6.0 / 0.13.0Cron 能力历经三次迭代0.5.6PR 15175为 Python 增加 cron worker 服务支持0.6.0PR 15393支持基于模块module-based的 cron 入口点0.13.0PR 15930支持从 Python 服务动态指定 crons——cron 路由不再局限于构建期静态配置运行时可通过环境变量__VC_CRON_ROUTESJSON 路由表引导。crons.py 给出了完整实现细节is_cron_service()VERCEL_SERVICE_TYPEcron或VERCEL_SERVICE_TYPEjob VERCEL_SERVICE_TRIGGERschedule判定为 cron 服务bootstrap_cron_service_app()读取__VC_CRON_ROUTES路由表将完整 cron 路径映射到两种 handler 说明符——module:function调用具名可调用对象同步/异步自动识别异步用asyncio.to_thread包裹同步 handler或裸模块名以if __name__ __main__方式执行通过run_entrypoint_as_main运行生成的 ASGI 应用只接受GET/POST其余返回 405支持lifespan协议路由未命中返回 404handler 异常返回 500安全模型若设置了CRON_SECRET环境变量请求必须携带Authorization: Bearer secret并使用hmac.compare_digest做常数时间比较未授权返回 401。在 vc_init.py 中cron 服务会以app bootstrap_cron_service_app(...)覆盖入口变量。测试夹具 tests/fixtures/cron_sync_handler.py、tests/fixtures/cron_async_handler.py、tests/fixtures/cron_dunder_main.py 及cron_multi_handler_a/b覆盖了同步、异步、__main__与多路由场景。八、Worker 服务与 Django 任务0.6.0 / 0.9.0 / 0.10.00.6.0PR 15396为 Django 任务tasks增加 Python worker 服务支持0.9.0PR 15434 / 15433vercel dev开始支持 background workers 与 cron services 的本地调试0.10.0PR 15454Celery worker 服务的 broker 声明支持直接写broker_urlvercel://无需再从vercel.workers.celery导入。workers.py 的is_worker_service()判定VERCEL_SERVICE_TYPEworker或jobqueue/workflowtriggerprepare_worker_environment()在导入用户代码前设置 worker 环境通过可选导入vercel.workers._runtimemaybe_bootstrap_worker_service_app()在 vc_init.py 中被调用将生成的 worker app 挂载为入口的app变量。0.13.1PR 894e7d4将框架相关逻辑重构进独立的python/vercel-workers包让 vercel-runtime 保持与框架无关的职责边界。九、Django 静态文件服务0.8.0 / 0.12.00.8.0PR 15483修复 Django 项目 dev server 报错0.9.0PR 15501修复vercel dev中 Django WSGI 应用的静态文件服务0.12.0PR 15709 / 15772修复 manifest 存储后端的静态文件服务以及未使用 staticfiles 时vc dev的回归。dev.py 展示了完整的 Django 静态处理策略_wrap_django_static()当django.contrib.staticfiles在INSTALLED_APPS中时用StaticFilesHandler包装 WSGI 应用使STATIC_URL请求直接从源码目录经 staticfiles finder 服务无需先跑collectstatic_handle_manifest()当STORAGES[staticfiles].BACKEND或STATICFILES_STORAGE含Manifest/Compressed且项目使用 WhiteNoise 时若STATIC_ROOT已收集产物则直接交给 WhiteNoise 并从STATIC_ROOT服务并给出 collectstatic 提示日志否则覆盖为StaticFilesStorage使{% static %}输出非哈希 URLDjango 5 用settings.STORAGES、旧版用STATICFILES_STORAGE做版本分支。同时 dev.py 还提供通用的public/目录静态服务ASGI 路径优先尝试 FastAPI/StarletteStaticFilesWSGI 路径用_static_wsgi_app()做带路径穿越防护_is_safe_file校验 realpath 前缀的静态读取。十、冷启动优化与依赖安装策略0.4.0 / 0.5.0 / 0.10.1冷启动是 serverless Python 的关键指标CHANGELOG 记录了三次直接优化0.4.0PR 15011Lambda 执行期间若提供了_runtime_requirements.txt则安装之0.5.0PR 15080为大于 250MB 的 Lambda 优化冷启动——移除uv pip install改用uv sync --inexact --frozenLambda zip 先打包依赖至 245MB其余依赖运行时再装0.10.1PR 15639使用 hardlink 链接模式替代 copy减少 /tmp 临时存储的磁盘峰值占用。vc_init.py 给出了运行时依赖安装的完整流程启动时检查_uv/_runtime_config.json若存在则在/tmp/_vc_deps下手工写pyvenv.cfg构造 PEP 405 venv 骨架避免子进程随后调用 vendoreduv sync --inexact --active --frozen --no-dev --no-editable --no-install-project --no-build --no-cache --no-progress --link-mode hardlink并用--no-install-package排除bundledPackages已在_vendor中打包的依赖通过UV_NO_INSTALLER_METADATA1跳过运行期从不读取的安装元数据完成后写入.installed标记文件供 warm start 复用Using cached runtime dependencies并用site.addsitedir将运行时安装的 site-packages 前插到sys.path首位。安装失败会通过_fatal报告unrecoverable-errorIPC 消息并退出。十一、依赖 vendoring 与 quirks 系统0.3.0 / 0.5.3 / 0.5.4 / 0.13.00.3.0PR 14827将 Python 运行时依赖 vendoring避免与用户项目依赖版本冲突0.5.3PR 15289新增prisma-client-py支持并引入 quirks 系统0.5.4PR 15305matplotlib 环境变量移入 quirks。vendoring 的工程化配置完整保留在 pyproject.toml[tool.vendoring]指定目标目录src/vercel_runtime/_vendor/、补丁目录patches/如 patches/werkzeug-001.patch、依赖清单 src/vercel_runtime/_vendor/vendor.txt 与命名空间vercel_runtime._vendor并通过 substitute 变换支持 uvicorn 的动态import_from_string把uvicorn.lifespan/loops/protocols.重写为vercel_runtime._vendor.uvicorn.*同时丢弃bin/、colorama/tests/、*.so。当前 vendor 目录包含 click、colorama、h11、markupsafe、uvicorn、werkzeug、wsproto 等包其中 wsproto 正是 0.15.0 WebSocket 支持的依赖。VERCEL_RUNTIME_ENV_PATH_PREPEND见 vc_init.py则允许 quirks 向PATH前置目录如 bundled shims。十二、入口点解析与应用类型探测0.7.0 / 0.10.0 / 0.11.00.7.0PR 15419将vc_init_dev移入 vercel-runtimedev 侧与应用侧共享引导逻辑0.10.0PR 15614让指定不同入口变量真正生效——此前入口变量配置可能被忽略0.11.0PR 15635简化运行时总是传入app变量。resolver.py 实现了应用解析import_module()通过importlib.util.spec_from_file_location从绝对路径加载模块resolve_app()从模块中取出指定变量缺失时给出指向 Vercel 文档的报错提示。detect_app_type()resolver.py的判定顺序为优先.asgi可调用属性 → 自身是协程函数且位置参数为 3scope, receive, send→ 进一步区分 WSGI 与BaseHTTPRequestHandler子类。平台侧入口通过__VC_HANDLER_ENTRYPOINT、__VC_HANDLER_ENTRYPOINT_ABS、__VC_HANDLER_MODULE_NAME、__VC_HANDLER_VARIABLE_NAME四个环境变量定位入口见 vc_init.pydev 侧则对应VERCEL_DEV_MODULE_NAME、VERCEL_DEV_ENTRY_ABS、VERCEL_DEV_FRAMEWORK、VERCEL_DEV_VARIABLE_NAME见 dev.py。0.14.1PR 1318682的 minor 性能改进与 0.11.0 的 flaky 单测修复PR 15647、0.4.2 的补测试PR 15133则属于持续的质量建设。十三、可观测性日志、指标与致命错误上报0.5.5 / 0.5.20.5.2PR 15268修复非 IPC 代码路径的 ASGI lifecycle 事件0.5.5PR 15319通过 IPCunrecoverable-error消息上报致命初始化错误。vc_init.py 的setup_logging()是日志体系的枢纽自定义VCLogHandler把logging记录映射为fatal/error/warn/info/debug级别并经 IPC 发送StreamWrapper重写sys.stdout/sys.stderr让print与日志关联到当前请求上下文invocationId/requestIdprint_wrapper保证内建print也走包装后的 stdout。握手前的初始化日志被缓冲上限 1MB见_INIT_LOG_BUF_MAX_BYTESserver-started握手完成后由_flush_init_log_buf()统一冲刷。致命错误走_send_unrecoverable_error()vc_init.py——这是握手完成前 functions runtime 唯一接受的两种消息之一。平台侧存在VERCEL_IPC_PATH还会对 urllib3/requests 的urlopen打补丁发送fetch-metric请求指标vc_init.py。十四、服务路由前缀与发布流程0.4.3 / 0.4.1 / 0.2.0 / 0.1.00.4.3PR 15097在 Python 运行时中剥离服务services路由前缀——ASGI 经apply_service_route_prefix_to_asgi_scope、WSGI 经apply_service_route_prefix_to_target/strip_service_route_prefix处理routing.pysplit_request_target拆分 path 与 query0.4.1PR 15033修复发布流程中的 PyPI 发布集成0.2.0PR 14682与 changesets 集成使 CHANGELOG 由 PR 驱动的版本管理自动生成——这正是本文所依据文档的来源机制0.1.0vercel-runtime首次发布提供 Vercel 上 Python 函数的运行时工具。十五、版本演进一览版本核心变更关键源码/配置落点0.17.0队列/工作流迁移 vercel-queue SDKworkers.pyinstall_queue_integrations/bootstrap_queue_service_app0.16.0WSGI WebSocketwerkzeug.socket/gunicorn.socketwsgi_websocket.py、vc_init.py0.15.0ASGI WebSocketvendored wsproto_vendor/wsproto0.14.2WSGI chunked 解码read_wsgi_request_body、test_request_body.py0.14.0运行时缓存cache.py0.13.2OIDC 头透传headers.py0.13.0动态 cronscrons.py__VC_CRON_ROUTES0.12.0Django manifest 静态文件dev.py0.10.0入口变量生效、Celeryvercel://brokerresolver.py0.9.0dev 支持 background/cron 服务dev.py_setup_apps0.5.0冷启动优化uv sync --inexact --frozenvc_init.py0.3.0依赖 vendoringpyproject.toml[tool.vendoring]结语从 0.1.0 到 0.17.0vercel-runtime 的演进清晰勾勒出一条平台能力下沉的路径WebSocket 双协议支持、队列与工作流的 SDK 化vercel-queue、动态 Cron、运行时缓存、OIDC 透传等能力逐一进入运行时内核而冷启动优化与依赖 vendoring 则持续压低 serverless 的边际成本。对开发者而言理解这份 CHANGELOG 与 src/vercel_runtime/ 源码的对应关系可以在排查vercel dev与生产环境行为差异如 Django 静态文件、队列消费组、Cron 鉴权时快速定位问题边界若需深入某一能力的细节tests/ 目录下的 fixturesASGI/WSGI/WebSocket/Cron 各场景是最直接的行为规范文档。赞分享CLI后端云原生【免费下载链接】vercelDevelop. Preview. Ship.项目地址https://gitcode.com/gh_mirrors/ve/vercel点击查看免费下载相关推荐Django Vercel借助 Python Runtime 与 Serverless Functions 部署 Django 6 实战指南Django Vercel借助 Python Runtime 与 Serverless Functions 部署 Django 6 实战指南 Django示例工程前端后端Cua Driver SDK-Owned Runtime从守护进程到进程内 Runtime 的架构演进RFC 2549 全解析Cua Driver SDK Owned Runtime从守护进程到进程内 Runtime 的架构演进RFC 2549 全解析 导读 RFC 2549 是人工智能AI AgentGUI 自动化Agent 评测强化学习Agent 沙箱计算机视觉MCP 服务Vercel Python Serverless Functions 实战基于 Hello World 示例掌握 Python Runtime 部署Vercel Python Serverless Functions 实战基于 Hello World 示例掌握 Python Runtime 部署 导读 本示例工程前端后端上一篇Mojito框架快速入门指南下一篇破解LCOV差异覆盖率报告难题从冲突分析到精准测试实践指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表