面试题手册

梳理高频技术问题,帮助你按主题复习和查漏补缺。

服务端阅读 05月27日 14:23

Serverless 架构下怎么测试才算靠谱?

为什么 Serverless 的测试这么难搞写 Serverless 的人大概都有过这种体验:本地跑得好好的函数,一部署上去就出问题。原因很简单——Serverless 应用天生是分布式的。你的代码不是跑在一台机器上,而是分散在 Lambda 函数、API Gateway、SQS 队列、DynamoDB 表这些服务之间,靠事件和触发器串联起来。这带来几个核心难点:本地环境无法还原云端行为。 你没法在笔记本上完整模拟 IAM 权限、冷启动延迟、VPC 配置这些运行时条件。事件驱动的异步流程难以追踪。 一个请求可能触发 SNS → Lambda → SQS → 另一个 Lambda,中间任何一环出问题,排查成本都很高。第三方服务依赖难以隔离。 你的函数可能调用 Step Functions、EventBridge、Secrets Manager,这些服务没有本地替代品,mock 又容易和真实行为脱节。所以 Serverless 测试的核心矛盾在于:你要在"快速反馈"和"真实性"之间做取舍。完全依赖云端测试太慢,完全依赖本地 mock 又不够可信。单元测试:把业务逻辑从云服务里剥离出来单元测试在 Serverless 里没有消失,但它的角色变了。大多数 Lambda 函数本质上是"胶水代码"——接收事件、做简单转换、调用其他服务。真正值得用单元测试覆盖的,是那些包含业务规则的逻辑。关键做法是将业务逻辑与云服务解耦。把核心计算和判断抽成纯函数,不依赖 AWS SDK 调用,这样就可以用传统的单元测试方式来验证。例如:# 业务逻辑:纯函数,易于测试def calculate_discount(order_total, customer_tier): rates = {"gold": 0.15, "silver": 0.10, "bronze": 0.05} return order_total * rates.get(customer_tier, 0)# Lambda handler:只做胶水,不做计算def handler(event, context): tier = event["customerTier"] total = event["orderTotal"] discount = calculate_discount(total, tier) dynamodb.put_item(Item={"pk": event["orderId"], "discount": discount})对于必须调用云服务的代码,需要用 mock 来隔离。Python 生态的 moto 可以 mock 几乎所有 AWS 服务,JavaScript 的 sinon.js 可以拦截 AWS SDK 调用,Java 用 Mockito。但要注意:mock 能验证"你的代码是否按预期调用了某个服务",却无法验证"那个服务是否真的会按你的预期响应"。这是单元测试在 Serverless 里的天然上限。集成测试:在本地和云端之间找到平衡点集成测试是 Serverless 测试中最关键的一层,因为它验证的是服务之间能否正确协作。这一层有两个主要策略:本地模拟和云端实测。本地集成测试AWS SAM CLI 的 sam local invoke 可以在 Docker 容器中运行 Lambda 函数,使用和云端相同的运行时环境。sam local start-api 还能模拟 API Gateway。这对于验证函数本身的逻辑和 API 路由是否匹配很有用。LocalStack 更进一步,它在一个 Docker 容器里模拟了数十种 AWS 服务——S3、DynamoDB、SQS、SNS、Kinesis 等。配合 samlocal 命令,你可以把整个 SAM 应用部署到 LocalStack 里,跑完整的集成测试。但本地模拟有其局限:它无法覆盖 IAM 策略验证、VPC 网络配置、Lambda 层的加载行为等细节。LocalStack 对部分高级功能的支持也不完整。云端集成测试更推荐的做法是在真实的 AWS 环境中做集成测试。现在的共识是"Remocal"(Remote + Local)策略:本地快速验证基本逻辑,云端验证真实行为。具体做法是为每个 PR 或分支创建一个临时环境(ephemeral environment),用 SAM Accelerate 或 CDK watch 快速部署变更,跑完测试后自动销毁。这样既保证了测试的真实性,又避免了污染共享环境。Google Cloud Functions 用户可以用 Functions Framework 在本地运行函数,但同样建议在真实 GCP 环境中做集成验证。端到端测试:验证完整的事件流端到端测试覆盖的是从用户请求到最终结果的完整链路。在 Serverless 里,这意味着验证事件是否按设计穿过所有服务。典型场景:用户上传图片到 S3 → 触发 Lambda 生成缩略图 → 写入 DynamoDB → 发送 SNS 通知。端到端测试需要验证每一个环节都正确执行,并且最终结果符合预期。这类测试的挑战在于异步等待和幂等性。你需要用轮询或回调机制等待异步流程完成,同时确保测试可以重复执行不会产生副作用。端到端测试数量要控制,因为它们运行慢、成本高、维护难。通常只覆盖最核心的几条业务链路。CI/CD 里的测试怎么排在 Serverless 应用的 CI/CD 流水线中,测试的编排方式直接影响交付速度和质量信心。推荐的流程是:PR 阶段:跑单元测试 + 本地集成测试,快速反馈代码逻辑是否正确。合并到主分支后:部署到临时云端环境,跑云端集成测试,验证服务间交互。预发布环境:跑端到端测试,覆盖核心业务链路。生产环境:跑烟雾测试(smoke test),确认关键功能可用。这个流程的关键是每一层测试只验证上一层无法覆盖的东西。单元测试验证业务规则,集成测试验证服务交互,端到端验证业务流程,烟雾测试验证部署成功。不要在每一层重复验证同样的事情。测试工具速查不同平台和语言都有对应的测试工具:| 工具 | 用途 | 适用场景 ||------|------|----------|| AWS SAM CLI | 本地调用和调试 Lambda | 快速验证单个函数逻辑 || LocalStack | 本地模拟多种 AWS 服务 | 离线集成测试 || moto (Python) | Mock AWS SDK 调用 | 单元测试中隔离云服务 || sinon.js (JS) | 拦截 AWS SDK 调用 | Node.js Lambda 单元测试 || ServerlessSpy | 监听和验证事件流 | 事件驱动架构的集成测试 || Functions Framework | 本地运行 Cloud Functions | GCP 函数本地调试 || SAM Accelerate | 快速增量部署 | CI/CD 中减少部署等待时间 || CDK watch | 监听代码变更并自动部署 | 开发阶段快速迭代 |测试金字塔为什么变成了蜂巢传统的测试金字塔建议 70% 单元测试、20% 集成测试、10% 端到端测试。这个比例在单体应用里很合理,但在 Serverless 里,大多数 Lambda 函数就是"收到事件、调用服务、返回结果",内部逻辑极其简单,单元测试的投入产出比很低。Spotify 提出的测试蜂巢(Testing Honeycomb)模型更适合 Serverless:单元测试比例降低,集成测试成为主力,端到端测试依然保持在少量。原因是 Serverless 应用中超过 60% 的生产故障来自服务间集成错误,而不是单个函数内部逻辑错误。集成测试恰好覆盖了这个风险最高的区域。但这不意味着不需要单元测试。当你的函数包含复杂的业务规则、数据转换逻辑或条件分支时,单元测试仍然是最有效的验证手段。关键是根据代码的实际复杂度来决定测试策略,而不是机械地套用某个模型。说到底,Serverless 测试没有银弹。你需要根据自己应用的架构特点、团队节奏和故障历史,找到本地 mock 和云端实测之间的最佳组合。测试的终极目标不是覆盖率达到某个数字,而是你有信心地把代码推到生产环境。
服务端阅读 05月27日 10:46

Serverless 监控和调试怎么做?实战方案详解

Serverless 的监控比传统应用难得多——函数生命周期短,日志转瞬即逝,一次请求可能跨越十几个函数,调用链路像黑盒。传统 APM 工具虽然支持 Serverless,但配置复杂,且按函数收费的定价模式在大量函数场景下很贵。先搞清楚要监控什么:冷启动频率和耗时、函数执行时间、错误率和错误类型、并发数和限流情况、调用链路和依赖关系。这五项覆盖了 Serverless 最核心的可观测性需求。日志:结构化是前提Serverless 函数的日志不是写在本地文件上的,而是打到 CloudWatch / 日志服务。如果还是 print("something happened") 这种格式,在几千条日志里找到你要的那条无异于大海捞针。必须做两件事:JSON 格式输出:每条日志包含 traceid、functionname、timestamp、level、message,方便用 CloudWatch Insights 或 Loki 过滤查询请求级 trace ID:在 API Gateway 层生成,一路透传到下游所有函数,这样可以用一条查询把整个请求链路的日志串起来分布式追踪:看清调用链路一个 API 请求从 API Gateway → Lambda A → SQS → Lambda B → DynamoDB,光看日志拼不出完整链路。分布式追踪就是解决这个问题的。AWS X-Ray 是最直接的选择——和 Lambda 原生集成,开启即可用,但功能有限。OpenTelemetry 更灵活,支持多后端(Jaeger、Zipkin、Datadog),适合多云或混合架构。关键配置点:确保所有函数都开启 tracing在函数间传递 trace context(W3C Trace Context 标准的 traceparent header)设置合理的采样率——全量追踪成本高,1% 采样又可能漏掉关键错误本地调试:模拟环境还是直接上云?本地跑 Serverless 函数有两种思路:模拟派:用 SAM CLI 的 sam local invoke 或 Serverless Framework 的 offline 插件,在本地模拟 API Gateway、DynamoDB 等服务。好处是快,坏处是模拟环境总跟线上有差异——IAM 策略、VPC 配置、环境变量都可能不一样。直接上云派:写完代码直接部署到 dev 环境,用真实云服务测试。好处是环境一致,坏处是部署慢、费钱。实际项目中两者结合:单元测试本地跑,集成测试部署到 dev 环境。别花太多时间折腾本地模拟——线上环境的差异问题,本地模拟永远解决不了。错误处理和告警Serverless 函数报错后实例就被回收了,现场信息不会保留。所以错误处理必须做到两点:捕获所有异常:在函数入口包一层 try-catch,把错误信息连同上下文(请求参数、环境变量、调用栈)写入日志和错误追踪服务(Sentry、Rollbar)。裸奔的 Lambda 一旦崩溃,你连它为什么崩溃都不知道。设置合理的告警:CloudWatch Alarm 按 Lambda 的 ErrorRate 和 Duration 设阈值,错误率超过 5% 或 P99 延迟超过 2 秒就触发告警。别等到用户投诉才发现问题。
服务端阅读 05月27日 10:45

Serverless 架构有什么缺点?冷启动、调试和成本问题怎么解?

用了两年 Serverless,踩了不少坑。冷启动延迟、调试困难、成本失控……这些问题在 PPT 里不会被提及,但上线后每一个都会咬你。下面按实际影响程度,逐一拆解 Serverless 架构的主要限制和应对策略。冷启动:最让人头疼的延迟函数一段时间没被调用后,运行环境会被回收。下次请求进来,平台得重新分配资源、加载运行时、初始化代码——这个过程就是冷启动。AWS Lambda 冷启动通常 200ms-5s,Java 等重运行时更慢,可能 10 秒以上。应对方法:预留实例:花钱保活,适合对延迟敏感的核心接口轻量运行时:Go、Rust 比 Java/Node 冷启动快一个数量级定时心跳:每 5 分钟调一次函数防止回收(治标不治本,还浪费钱)SnapStart:AWS 提供的快照恢复功能,Java 冷启动从 10 秒降到 200ms执行时间和资源的天花板AWS Lambda 最长执行 15 分钟,内存上限 10GB,/tmp 最多 10GB。视频转码、大数据批处理这类长任务直接超出限制。解法不是硬塞进 Lambda,而是换架构:长任务用 AWS Fargate / Azure Container Apps,本质是 Serverless 容器,没有执行时间限制批处理用 AWS Step Functions 编排多个 Lambda,每个处理一部分大内存任务用 AWS Lambda 的 10GB 配置,但成本很高状态管理的天然缺陷Serverless 函数是无状态的——每次调用可能落在不同的实例上,实例间不能共享内存。这意味着:不能用全局变量缓存数据(下次请求可能不是同一个实例)WebSocket 长连接需要借助 API Gateway + DynamoDB 维护用户会话必须存外部存储(Redis、DynamoDB)这不是"限制"而是"设计约束"——接受无状态,把状态外置到专用服务,反而让架构更清晰。调试和可观测性是硬伤本地跑得好好的,部署到云端就出问题——环境差异、IAM 权限、网络配置都可能不一样。传统应用的断点调试在 Serverless 里基本不可行。实际可用的调试手段:本地模拟:用 Serverless Framework 的 local invoke 或 AWS SAM 的 sam local,模拟云环境结构化日志:每个请求带 trace ID,用 CloudWatch/Loki 按请求链路追踪X-Ray/Jaeger:分布式追踪,看清函数间的调用链和耗时预发布环境:和线上配置一致,上线前跑一遍集成测试厂商锁定:被平台绑定的隐性成本AWS Lambda 用了 API Gateway + DynamoDB + Step Functions,整套架构深度绑定 AWS。要迁到阿里云函数计算,代码、配置、基础设施全得重写。降低锁定风险的策略:业务逻辑和基础设施解耦:核心代码不依赖云 SDK,通过适配层调用云服务用 Terraform/CDK 管理基础设施:换平台只改配置,不改业务代码优先选开放标准:容器镜像部署比原生函数更容易迁移现实一点:锁定是不可避免的,关键是评估迁移成本是否在可接受范围内成本:看起来便宜,算起来不一定Serverless 按调用量计费,低流量场景确实便宜。但高并发或被攻击时,费用可能远超预期——DDoS 攻击不只是安全风险,还是财务风险。成本控制手段:设置并发上限和账单告警:AWS Lambda 支持账户级并发限制,防止失控对比预留实例和按需付费:稳定流量下预留实例更划算关注冷启动的间接成本:预留实例花钱,冷启动浪费请求时间,找到平衡点监控每次调用的成本:CloudWatch 可以按函数统计费用,及时发现异常
服务端阅读 02月21日 15:25

Serverless 架构下的性能测试如何进行?

Serverless 架构下的性能测试需要考虑其独特的特性,如冷启动、自动扩展和按需付费等特点:性能测试重点:1. 冷启动测试首次调用延迟:测量函数首次调用的响应时间预热策略验证:验证预热机制的有效性不同运行时对比:对比不同语言的冷启动时间2. 并发性能测试并发扩展能力:测试函数在高并发下的扩展能力资源限制:验证账户级别和函数级别的并发限制性能瓶颈:识别性能瓶颈和资源瓶颈3. 持续负载测试长时间运行:测试函数在持续负载下的稳定性内存泄漏:检测是否存在内存泄漏问题资源回收:验证函数实例的回收机制测试工具:Artillery:支持 HTTP 负载测试k6:现代化的性能测试工具JMeter:传统的性能测试工具Locust:Python 编写的分布式负载测试工具测试策略:基准测试:建立性能基准,用于对比优化效果压力测试:测试系统在极端负载下的表现容量规划:根据测试结果进行容量规划持续监控:在生产环境中持续监控性能指标关键指标:响应时间(P50、P95、P99)吞吐量(请求/秒)错误率冷启动时间资源使用率面试者应能分享实际项目中的性能测试经验和优化成果。
前端阅读 02024年7月23日 22:16

Serverless函数和Lambda函数有什么区别?

无服务器函数(Serverless Functions)和Lambda函数通常在讨论中被混用,但它们在严格意义上有区别:无服务器函数(Serverless Functions):这是一个广泛的概念,指的是运行在无服务器计算环境中的任何类型的函数。无服务器计算允许开发者编写和部署代码而不用管理服务器。无服务器架构中,开发者只关注业务逻辑层面的代码,而底层的运行环境、服务器的维护、扩展等由云服务提供商管理。常见的无服务器平台有 AWS Lambda、Azure Functions、Google Cloud Functions 等。Lambda函数:Lambda函数是Amazon Web Services(AWS)的一个特定服务产品,是无服务器计算服务的一种,但专指AWS平台上的实现。AWS Lambda 允许你运行代码响应事件,例如文件上传到AWS S3、更新DynamoDB表等,而无需考虑服务器的配置和管理。Lambda服务自动处理单个请求的扩展,并按功能运行时间的确切数量计费,无需预先购买服务器容量。总结来说,无服务器函数是一个涵盖所有无服务器平台上函数的通用术语,而Lambda函数特指AWS上的无服务器计算服务的实现。