1. 项目缘起为什么选择Vercel托管Python后端如果你和我一样经常折腾一些小项目比如做个数据分析的API、一个简单的Webhook接收器或者一个AI模型的调用接口那你肯定遇到过部署的麻烦。传统的服务器无论是云厂商的ECS还是轻量应用服务器都绕不开几个问题你得自己配置环境、管理进程、操心安全更新最头疼的是项目一旦冷启动服务器空转的成本就让人心疼。这时候Serverless无服务器架构就成了一个极具吸引力的选择。它按实际请求量计费自动扩缩容你只需要关心代码本身。在众多Serverless平台中Vercel以其对前端项目的极致优化而闻名但很多人不知道它同样是一个强大且免费的Python后端托管平台。是的免费。Vercel的Hobby套餐提供了每月100GB的带宽和无限的Serverless Function执行时长有单次执行超时限制对于个人项目、原型验证、小型API来说完全够用甚至绰绰有余。我最近就把一个用FastAPI写的、需要调用外部大模型API的智能问答服务部署到了Vercel上。整个过程比想象中顺畅但也踩了几个关于环境依赖和冷启动的“小坑”。这篇文章我就来手把手拆解如何将一个Python后端API从本地开发环境丝滑地部署到Vercel并让它稳定运行。我们会重点解决两个核心难题如何让Vercel正确识别并安装你的Python依赖以及如何配置以适应Serverless环境。你会发现它比租一台服务器要简单和“无感”得多。2. 环境与项目准备从零搭建一个可部署的Python API在把代码扔给Vercel之前我们得先在本地把它跑通。这里我以一个最简单的FastAPI应用为例它包含一个根路由和一个处理POST请求的API。这个模式可以扩展到任何复杂的Web框架比如Flask或Django需要额外配置。2.1 创建本地项目结构首先在你的工作目录下创建一个新的项目文件夹并建立如下结构my-vercel-python-api/ ├── api/ │ └── index.py ├── requirements.txt └── vercel.json这个结构是Vercel部署Python项目的关键约定api/目录Vercel会自动将这个目录下的文件映射为Serverless Function。index.py是这个Function的入口文件。requirements.txtPython项目的依赖清单Vercel的构建系统会读取这个文件并安装所有列出的包。vercel.jsonVercel的配置文件用于覆盖默认行为比如指定运行时、环境变量等。2.2 编写核心API代码接下来我们编辑api/index.py文件。这里我们使用 FastAPI因为它天生适合构建API并且与Serverless环境兼容性很好。# api/index.py from fastapi import FastAPI, HTTPException from pydantic import BaseModel import uvicorn from typing import Optional # 初始化FastAPI应用 app FastAPI(titleMy Vercel Python API, version1.0.0) # 定义一个数据模型用于接收POST请求的JSON body class QueryRequest(BaseModel): question: str user_id: Optional[str] None # 根路径用于健康检查 app.get(/) async def read_root(): return {message: Hello from Vercel Python API!, status: healthy} # 主要的API端点处理POST请求 app.post(/ask) async def ask_question(request: QueryRequest): 处理用户提问的API端点。 在实际应用中这里可以接入LLM、数据库查询等逻辑。 if not request.question or request.question.strip() : raise HTTPException(status_code400, detailQuestion cannot be empty.) # 这里是你的业务逻辑核心 # 例如调用OpenAI API、查询数据库、进行数据处理等 # 此处仅作示例返回一个模拟的响应 simulated_answer fReceived your question: {request.question}. This is a simulated response from the serverless backend. # 构建响应 response_data { answer: simulated_answer, processed: True, user_id: request.user_id } return response_data # 注意在Vercel的Serverless环境中我们不需要也不应该调用 uvicorn.run() # Vercel会使用自己的服务器来运行这个ASGI应用。 # 下面的代码块仅用于本地测试部署时不会被执行。 if __name__ __main__: uvicorn.run(app, host0.0.0.0, port8000)这段代码做了几件事创建了一个FastAPI应用实例。定义了一个QueryRequest模型用来规范客户端发送的JSON数据格式。创建了两个路由GET /一个简单的健康检查端点访问它会返回欢迎信息。POST /ask主要的业务端点接收JSON格式的提问并返回一个模拟的答案。最后有一个if __name__ “__main__”:代码块这是为了方便我们在本地用python api/index.py命令启动服务进行测试。部署到Vercel时这部分代码完全被忽略因为Vercel会把整个app对象当作一个WSGI/ASGI应用来调用。2.3 生成精准的依赖文件 requirements.txt这是最容易出错的一步。Vercel的构建系统依赖于requirements.txt来安装环境。我们需要生成一个精确的列表。在项目根目录 (my-vercel-python-api/) 下打开终端激活你的Python虚拟环境强烈建议使用venv或conda来隔离项目环境然后安装FastAPI和Uvicornpip install fastapi uvicorn安装完成后使用pip freeze命令将当前环境的所有包及其精确版本导出到requirements.txtpip freeze requirements.txt现在查看你的requirements.txt它应该看起来像这样版本号可能不同anyio4.0.0 click8.1.7 fastapi0.104.1 h110.14.0 idna3.6 pydantic2.5.0 pydantic_core2.14.3 sniffio1.3.0 starlette0.27.0 typing_extensions4.8.0 uvicorn0.24.0关键经验永远不要手动编写或随意修改requirements.txt。务必通过pip freeze在干净的项目虚拟环境中生成。这能确保本地开发环境和Vercel的线上环境的一致性避免出现“在我机器上是好的”这类经典问题。如果你需要新增依赖也是在本地虚拟环境中安装后重新生成这个文件。2.4 本地测试验证在部署前先在本地跑通。在项目根目录下执行python api/index.py你应该看到Uvicorn启动的信息显示服务运行在http://0.0.0.0:8000。然后你可以用浏览器访问http://localhost:8000会看到JSON格式的欢迎信息。更专业的测试是使用curl或 Postman 测试/ask接口curl -X POST http://localhost:8000/ask \ -H Content-Type: application/json \ -d {question: What is Serverless?, user_id: test_123}如果返回了包含模拟答案的JSON响应恭喜你本地API已经就绪。3. 部署到Vercel从代码到线上服务的核心步骤本地测试通过后我们就可以着手部署了。Vercel提供了两种主要方式通过网页控制台GUI和通过Vercel CLI命令行。对于Python项目我强烈推荐使用Vercel CLI因为它能让你在本地模拟构建和部署过程提前发现问题并且流程更可控。3.1 安装并配置Vercel CLI首先你需要在本地安装Vercel CLI。使用npm可以全局安装npm install -g vercel安装完成后在终端里登录你的Vercel账户如果你还没有需要先去 vercel.com 注册一个vercel login这个命令会打开浏览器引导你完成授权登录。登录成功后你的终端就与Vercel账户关联了。3.2 创建 vercel.json 配置文件虽然Vercel对Python项目有不错的自动检测能力但为了确保万无一失特别是当我们的项目结构不是最常规的时候显式配置一个vercel.json是很好的实践。在项目根目录创建这个文件{ functions: { api/*.py: { runtime: python3.9 } }, rewrites: [ { source: /(.*), destination: /api/index } ] }让我解释一下这个配置functions: 这里指定了哪些文件应该被当作Serverless Function处理。“api/*.py”表示api目录下的所有.py文件都是一个独立的Function。我们为它指定了运行时“python3.9”。Vercel支持多个Python版本如3.9, 3.10, 3.11根据你的需要选择。指定版本可以避免因Vercel默认版本升级带来的意外问题。rewrites: 这是非常重要的一项配置。它告诉Vercel的路由系统将所有访问根路径及其子路径的请求都重写到/api/index这个Function。为什么是/api/index因为我们的入口文件是api/index.pyVercel会默认将api目录下的文件名映射为路由路径。所以访问你的域名根路径时实际上触发的是api/index.py中定义的app。注意如果你使用Flask并且入口文件是api/index.py中的一个app Flask(__name__)对象这个配置同样有效。对于更复杂的Django项目配置会有所不同通常需要指定一个wsgi.py或asgi.py文件的路径。3.3 执行部署命令一切准备就绪在项目根目录下运行部署命令vercel如果你是第一次在这个目录下执行CLI会交互式地询问你几个问题Set up and deploy “~/path/to/my-vercel-python-api”? [Y/n] 输入y。Which scope do you want to deploy to? 选择你的账户或团队。Link to existing project? [y/N] 通常选N以创建一个新项目。What’s your project’s name? 输入一个项目名或者直接回车使用默认的文件夹名。In which directory is your code located? 确认代码目录直接回车.表示当前目录。接下来CLI会开始上传你的代码并在Vercel的云端执行构建流程。你会看到类似下面的输出 Deploying ~/my-vercel-python-api under your-username Using Python 3.9 Installing requirements.txt... Running build command... Build completed. Deployed to production. ✅最关键的一行是Installing requirements.txt...。这意味着Vercel的构建系统成功识别了你的Python项目并开始根据requirements.txt安装依赖。如果这一步出错比如某个包版本不兼容或找不到构建就会失败并给出错误信息。构建成功后CLI会给你一个预览URL格式类似https://my-vercel-python-api.vercel.app。点击这个链接你应该就能看到和本地一样的{“message”: “Hello from Vercel Python API!”, “status”: “healthy”}响应了。3.4 部署后验证与测试拿到线上地址后我们不仅要测试根路径更要测试核心的业务API。再次使用curlcurl -X POST https://your-project-name.vercel.app/ask \ -H Content-Type: application/json \ -d {question: Is my API live on Vercel?, user_id: deploy_test}如果返回了成功的JSON响应那么你的Python后端API就已经在Vercel上成功运行了整个过程你不需要配置服务器、安装Nginx、设置进程守护如systemd甚至不需要关心SSL证书Vercel自动提供HTTPS。这就是Serverless的魅力。4. 深入解析Vercel如何运行你的Python代码部署成功了但作为一个开发者我们有必要理解背后的机制这能帮助我们在遇到问题时进行排查。Vercel运行Python API本质上是在其Serverless计算平台上启动了一个容器化的环境。4.1 构建与运行时机制当你执行vercel命令或通过Git推送代码时Vercel会启动一个构建过程Build Step环境检测Vercel会扫描你的项目根目录。如果它发现了requirements.txt或Pipfile就会将其识别为Python项目。依赖安装在一个干净的、指定版本如Python 3.9的容器环境中运行pip install -r requirements.txt。所有的依赖都会被安装到该函数容器的本地环境中。函数打包Vercel会将你的api目录下的每个.py文件以及其他必要的项目文件打包成一个独立的Serverless Function部署包。index.py对应的就是/api/index这个函数。路由配置根据vercel.json中的rewrites规则将传入的HTTP请求路由到对应的函数。例如对根路径/的请求被重写为对/api/index函数的调用。当第一个HTTP请求到达你的API端点时会触发该函数的“冷启动”Cold StartVercel需要为这个函数初始化一个全新的运行时容器。在这个容器中加载Python解释器、已安装的依赖包然后执行你的代码即导入api/index.py模块。这个过程通常需要几百毫秒到几秒的时间具体取决于你的依赖包大小和复杂度。之后的请求如果落在同一个容器实例上就是“热启动”Warm Start速度会快很多。4.2 理解“入口点”与ASGI/WSGIVercel的Python运行时期望你的入口文件如api/index.py导出一个名为app的ASGI或WSGI应用实例。这就是为什么我们在代码中直接写app FastAPI()。ASGI异步服务器网关接口是WSGI的异步演进。FastAPI和Starlette基于ASGI。Vercel的现代Python运行时对ASGI支持很好。WSGIWeb服务器网关接口Python Web应用的传统标准。Flask、Django通常使用WSGI。Vercel的内部服务器会调用这个app对象并将HTTP请求传递给它处理。所以你完全不需要也不应该在你的代码里启动一个HTTP服务器如uvicorn.run(app)。那行代码仅仅是为了本地测试方便。4.3 项目结构的最佳实践虽然我们用了最简单的api/index.py结构但对于稍复杂的项目更清晰的结构是这样的my-advanced-api/ ├── api/ │ └── index.py # 主应用入口 ├── src/ │ ├── __init__.py │ ├── core/ # 核心业务逻辑 │ ├── models/ # 数据模型 │ └── utils/ # 工具函数 ├── requirements.txt ├── vercel.json └── README.md在api/index.py中你可以通过相对导入来引入src下的模块# api/index.py import sys import os sys.path.append(os.path.join(os.path.dirname(__file__), ‘..’)) from src.core import some_business_logic from fastapi import FastAPI app FastAPI() # ... 路由定义使用 some_business_logic这种结构保持了API入口的简洁并将业务代码组织在独立的目录中更利于维护。5. 进阶配置与性能优化实战基础部署只是第一步。要让你的Vercel Python API在生产环境中更可靠、更高效还需要进行一些进阶配置。5.1 环境变量的安全管理你的API很可能需要访问数据库、第三方服务的API密钥等敏感信息。绝对不要将这些信息硬编码在代码中或提交到Git仓库。Vercel提供了完善的环境变量管理。你可以在Vercel项目控制台进行设置登录Vercel进入你的项目。点击Settings-Environment Variables。在这里添加你的环境变量例如DATABASE_URL,OPENAI_API_KEY等。在代码中通过os.environ来读取import os api_key os.environ.get(“OPENAI_API_KEY”) if not api_key: raise RuntimeError(“OPENAI_API_KEY environment variable is not set”)对于需要区分开发和生产环境的情况Vercel允许你为不同的分支如main,develop或部署环境Production, Preview设置不同的环境变量。5.2 应对冷启动延迟冷启动是Serverless架构的固有特性。对于Python API尤其是依赖较多、较重的框架如TensorFlow, PyTorch冷启动时间可能达到5-10秒这对于用户体验是致命的。优化策略1精简依赖定期检查requirements.txt移除不必要的包。使用pip-chill等工具可以帮你列出非传递性依赖。考虑用更轻量的替代品比如用httpx替代requests如果适用用orjson替代标准库json来提升序列化速度。优化策略2使用更小的基础镜像高级Vercel默认的Python环境可能包含一些你不需要的系统包。虽然你不能直接选择镜像但可以通过在vercel.json中指定更新的、可能更精简的Python版本来间接优化。例如Python 3.11 通常比 3.9 的启动速度更快。优化策略3保持函数活跃Warm对于关键API可以设置一个简单的定时任务Cron Job定期如每5分钟访问你的API端点以保持其容器实例处于“温热”状态避免完全冷启动。有很多第三方服务如 uptimerobot, cron-job.org或云函数自身如果支持可以做到这一点。在Vercel的Hobby计划中你需要借助外部工具来实现。优化策略4合理设计函数粒度不要把所有功能都塞进一个巨大的api/index.py。可以根据业务模块拆分成多个函数文件例如api/auth.py,api/users.py,api/ask.py。这样每个函数更小依赖更明确冷启动可能更快。但要注意这也会增加管理复杂度。5.3 监控与日志排查当线上API出现问题时查看日志是首要任务。Vercel提供了两种主要的日志查看方式Vercel Dashboard在项目的Deployments页面点击具体的部署再进入Logs标签页。这里可以看到实时和历史的函数调用日志、构建日志和错误信息。这对于调试500 Internal Server Error非常有用。Vercel CLI在终端使用vercel logs deployment-url命令可以流式输出生产环境的日志。这对于实时跟踪问题非常方便。典型的错误日志可能包括ModuleNotFoundError: 这几乎总是因为requirements.txt不完整或安装失败。检查构建日志确认所有依赖都已成功安装。Timeout Error: Vercel Serverless Function 有执行超时限制Hobby计划为10秒Pro计划为15秒。如果你的API处理耗时过长如大型文件处理、复杂计算就会触发超时。你需要优化代码逻辑或者考虑将耗时任务拆分为异步任务通过队列处理。api/index.pymust export a function or an object named ‘app’: 这是入口点错误。请确保你的api/index.py文件顶层有一个名为app的变量并且它是ASGI/WSGI应用实例。6. 常见问题与避坑指南结合我自己的踩坑经历和社区常见问题这里总结几个高频陷阱和解决方案。6.1 依赖安装失败版本冲突与系统依赖问题描述在Vercel构建日志中看到ERROR: Could not find a version that satisfies the requirement some-package或安装过程中编译失败。根因分析纯Python包版本冲突你的requirements.txt里某个包的指定版本与Python环境或其他包不兼容。包含C扩展的包如psycopg2PostgreSQL驱动、cryptography、Pillow等。这些包在安装时需要编译而Vercel的构建环境可能缺少必要的系统库如libpq-dev,gcc,libffi-dev。解决方案对于版本冲突在本地创建一个干净的虚拟环境重新安装并测试所有依赖生成新的requirements.txt。可以使用pip-tools(pip-compile) 来生成更可靠的依赖关系。对于需要C扩展的包首选方案寻找纯Python的替代品。例如用psycopg2-binary替代psycopg2用cryptography的预编译轮子wheel版本。确保requirements.txt中指定的是二进制版本。Vercel的官方方案在项目根目录创建一个vercel-build.sh文件并在其中安装系统依赖。然后在vercel.json中配置构建命令。// vercel.json { “builds”: [ { “src”: “api/*.py”, “use”: “vercel/python” } ], “build”: { “env”: { “PYTHON_VERSION”: “3.9” } } }同时创建一个vercel-build.sh:#!/bin/bash # 安装系统依赖示例根据你的包调整 apt-get update apt-get install -y libpq-dev gcc # 然后执行默认的Python构建 pip install -r requirements.txt并在vercel.json的build部分引用它具体配置需参考Vercel最新文档因为此方式可能变动。不过对于大多数常见包使用其-binary版本是更简单可靠的方法。6.2 路由404错误vercel.json配置是关键问题描述部署后访问根路径/正常但访问/ask返回404。根因分析Vercel的路由规则没有正确配置。默认情况下api/index.py会处理/api/index路径的请求。如果你希望/ask也能被api/index.py中的路由处理就需要rewrites规则将/ask也重写到/api/index。我们的配置{ “source”: “/(.*)”, “destination”: “/api/index” }使用了通配符(.*)已经将所有路径都重写过去了。如果仍然404请检查vercel.json文件是否在根目录且格式正确。你的FastAPI/Flask应用是否正确定义了/ask路由。构建和部署是否成功查看部署日志。6.3 静态文件与中间件处理问题描述你的API可能需要提供静态文件如图片、文档或者需要使用一些中间件如CORS。解决方案静态文件Vercel本身是一个出色的静态文件托管平台。最佳实践是将静态文件放在项目根目录的public文件夹下。例如public/logo.png可以通过https://your-project.vercel.app/logo.png直接访问。不要在Python函数中通过open(‘file.txt’)来读取项目文件因为Serverless函数的文件系统是只读的除了/tmp目录且路径不确定。要么使用public目录要么将文件内容存储在环境变量或外部存储如S3中。CORS中间件如果你的API需要被浏览器前端调用必须处理CORS。在FastAPI中非常简单from fastapi.middleware.cors import CORSMiddleware app.add_middleware( CORSMiddleware, allow_origins[“https://your-frontend.vercel.app”], # 允许的前端域名 allow_credentialsTrue, allow_methods[“*”], # 允许所有方法 allow_headers[“*”], # 允许所有头 )6.4 数据库连接池的挑战问题描述在Serverless函数中直接使用传统的数据库连接池如SQLAlchemy的默认引擎会遇到问题。因为函数实例随时可能被创建和销毁持久化的连接池会失效甚至导致数据库连接数耗尽。解决方案采用更适合Serverless的连接策略。使用连接池代理对于像PostgreSQL这样的数据库可以使用PgBouncer这样的连接池代理。你的函数连接到PgBouncer由它来管理到实际数据库的持久连接。每次请求创建新连接对于低频率调用的API这可能是最简单的方案但要注意连接建立的开销。使用Serverless优化的数据库服务许多云数据库服务如PlanetScale, Supabase, Neon提供了对Serverless友好的连接方式例如通过HTTP协议或内置了智能连接处理。在函数层面管理轻量级池可以利用Python的lru_cache或模块级变量在同一个函数实例的生命周期内复用连接。但要注意当函数实例被回收后下一个冷启动会创建新的连接。from sqlalchemy import create_engine from functools import lru_cache lru_cache(maxsizeNone) def get_db_engine(): database_url os.environ.get(“DATABASE_URL”) # 注意这里不要使用默认的连接池或者设置一个很小的池 engine create_engine(database_url, pool_size1, max_overflow0) return engine # 在路由处理函数中 engine get_db_engine() with engine.connect() as conn: # 执行查询7. 从Demo到生产安全、成本与扩展性考量将一个小型API部署上线只是开始如果要承载真实用户和流量还需要考虑更多。7.1 安全加固要点HTTPSVercel自动提供无需担心。API密钥与敏感信息如前所述全部使用环境变量。并利用Vercel的环境变量管理功能为生产环境和预览环境设置不同的值。输入验证与消毒充分利用Pydantic模型FastAPI或WTFormsFlask进行严格的输入验证防止注入攻击。速率限制对于公开API必须实施速率限制防止滥用。可以在API网关层面Vercel Edge Functions或第三方服务如Cloudflare或应用层面如slowapi库实现。依赖安全定期运行pip-audit或使用GitHub Dependabot、Snyk等工具扫描requirements.txt及时更新有安全漏洞的依赖包。7.2 成本监控与优化Vercel Hobby计划虽然免费但有额度限制每月100GB带宽无限函数执行但有10秒超时限制。你需要关注带宽使用如果你的API返回大量数据如图片、文件容易耗尽带宽。函数执行次数和时长虽然执行时长无限但过多的调用或过长的单次执行可能触发限流或需要升级到Pro计划。 在Vercel项目控制台的Analytics标签页可以清晰地看到这些指标。如果用量接近限制可以考虑优化响应体积、缓存结果或者评估升级到Pro计划每月20美元起。7.3 扩展性设计当你的API用户量增长时需要考虑异步任务对于邮件发送、图片处理、AI模型推理等耗时操作不要阻塞HTTP响应。可以使用消息队列如RabbitMQ, Redis配合后台工作进程或者使用Vercel的无服务器函数触发其他云服务如AWS Lambda, GCP Cloud Functions。在Python中celery是常用的选择但在Serverless环境中部署Celery worker较为复杂可以考虑更云原生的方案如将任务发布到云任务队列由另一个专用的Serverless函数消费。缓存策略对于计算成本高、变化不频繁的数据使用缓存可以极大提升响应速度并降低数据库压力。Vercel自身提供了边缘缓存Edge Cache你也可以集成Redis等内存数据库。在FastAPI中可以很方便地使用fastapi-cache2等库。数据库选型如前所述选择与Serverless架构兼容的数据库。传统的基于长连接的数据库如标准MySQL在函数频繁冷启动的场景下表现不佳。经过以上七个部分的拆解你应该对如何使用Vercel托管Python后端API有了一个从入门到进阶的全面认识。从最简单的Hello World到处理依赖、优化性能、应对生产环境挑战每一步都结合了具体的操作和背后的原理。我个人的体会是Vercel极大地降低了个人开发者和中小团队部署Web服务的门槛让你能更专注于业务逻辑本身。当然它也不是银弹Serverless的冷启动、状态管理、数据库连接等问题需要你根据具体场景仔细设计和权衡。多实践多踩坑你就能越来越熟练地驾驭这个强大的平台。