ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基本功练习-9月

基本功练习-9月 20260901练习题目1 如何测试一个大模型推理服务假设服务提供如下接口POST /v1/chat/completions请求示例{model:xxx,messages:[{role:user,content:你好}],stream:true}请整理一份 35 分钟的面试回答至少覆盖以下内容功能测试需要覆盖哪些场景如何测试流式输出客户端中途断开连接时如何验证如何设计并发测试和压力测试什么是 TTFT、TPOT、E2E Latency、吞吐量和 P99 延迟输入长度、输出长度和并发数分别会怎样影响性能如果 P99 延迟突然升高如何定位问题如何测试服务重启、GPU 不可用、请求超时和下游异常回答q1. 功能测试需要覆盖的基本场景如下按照优先级排序p0 基本功能如不同的模型id构造不同的message类型stream的true or false是否返回预期内容比如传入11 模型是否正确的返回了答案等p0 逻辑部分是否依赖于其他前置接口如auth等p1 异常边界测试如异常场景参数异常等p1 安全测试cookie token等认证q2. 流式接口测试的核心理念是响应是否持续到大以及每个event是否都正确因此要测试流式接口主要从以下步骤入手s1. 确定流式接口的传输形式SSE: 标志为header中的Content-Type为text/event-streamHTTP-Chunked:标志为 header中字段为transfer-encoding为chunkedWebScoket连接建立后双向收发形式。如果是前两种则可以直接使用curl进行验证如果是websocket则需要编写代码或者专用客户端s2. 应该验证断言内容如下- 状态码- 首包及其响应时间- 事件格式是否符合要求- 事件顺序- 事件是否正确结束- 持续性与完整性- 连接是否正常关闭- 事件延迟间隔总耗时- 事件结束后服务端是否正确停止和生成资源s3. 异常与压力测试q3. 相较于传统的应答式接口流式接口的测试应该从两个角度或者说测试模型入手。a. 固定并发模型能稳定维持多少个流式连接b. 到达率模型每秒能承受多少个新建请求比如不去管先前的模型而是固定的按时间启动固定数量的流活跃并发数 每秒新请求 * 平均流请求时间基于上述模型需要进行以下阶段的测试s1.基线测试少量并发请求确认接口和客户端逻辑基本正确s2. 阶段性的加压测试持续增加并发数量每档保持一定量级的时间s3. 临界点: 找到开始出现异常的时间点s4. 突发异常流量测试: 短时间内从0至大并发观察连接与服务器负载s5. 稳定性测试正常负载下持续并发请求与测试s6. 取消与重试测试随机中断连接验证服务器资源是否正常q4. TTFT time to fisrt token从请求发出到收到的第一个token首token时间TPOTtime per output token首token后生成每个token所需要的平均时间持续生成速度Decode效率流式输出是否顺畅的主要衡量项E2E Latency: end-to-end latency 从请求开始到完整请求的总耗时吞吐量单位时间内处理的请求数Token数和字节数p99延迟延迟分布的第99百分位同样的p95和p50分别是95和50百分位他们保证的分别是大多数用户一般用户的体验q5.a. 输入长度对性能的影响主要体现在 TTFT 显存与最大并发等指标上这是因为输入的内容在经过模型计算后需要去建立KV Cache都是些需要去消耗资源去做的事输入长度越长通常意义上来讲也就是说模型需要去理解的事情越复杂也就是模型需要去思考的事情变得更多了那么思考阶段的成本也就变高了。因此就会导致TTFT增大E2E的延迟也会增大模型思考阶段的KV Cache增加显存需求量更大输入阶段的注意力计算量也需要更大此外更长的输入也意味着后续每个输入的token需要关注的上下文也越来越长因此Decode阶段的计算和显存访问也会显存增加。b. 输出长度主要会导致E2E的延迟变长以及连接占用的时间变久同时输出变长每一个输出的token都需要调用一次decoder所以decode阶段对显存的需求也会增长c. 并发长度并发数量则直观的影响系统资源无需多言三者情况组合的话大概是如下组合长输入 高并发容易显存不足长输出 高并发容易连接堆积和排队长输入 长输出 高并发P99超时 OOM等最不健康的状态q6. 定位途径 当前请求数量/负载 - 系统资源cpu/内存/显存 - 服务状态 - 网络状态q7:a. 预期流程重启检查原请求是否正确路由或者说负载到了备用服务上检查是否有新请求进来b. 强制重启预料外的断开检查入口是否正确启动了负载客户端是否正确发送了重试请求是否正确路由到了新的服务器原有长链接是否被正确关闭, 服务器重启后是否存在僵尸进程残留进程协议栈中连接是否正确释放c. GPU异常应测试GPU调度异常CUDA设备无法识别GPU OOM模型失败GPU实例负载失败具体方法有- 修改GPU配置以模拟调度异常- 暂时屏蔽或者短线GPU模拟CUDA无法识别- 减小GPU可用内存模拟显存OOM- 模拟模型的返回给下游返回异常d. 请求超时需要模拟的异常情况主要有首token超时流中超时E2E超时f. 下游异常返回mock异常返回即可20260902练习假设你需要用 Go 编写一个简单的大模型推理服务压测工具要求如下总共发送 1000 个请求最大并发数为 20每个请求超时时间为 5 秒支持通过CtrlC取消测试统计成功数、失败数、超时数、平均延迟和 P99 延迟程序退出时不能遗留 goroutine 或 HTTP 连接请整理一份 35 分钟的面试回答至少覆盖以下内容如何使用 goroutine 和 channel 组织并发请求如何限制最大并发数有哪些实现方式全局取消、单请求超时和程序退出之间是什么关系多个 goroutine 如何安全地统计测试结果如果收到CtrlC应该如何停止新请求并处理正在执行的请求如何验证程序没有 goroutine 泄漏“固定并发”与“固定每秒请求数”两种压测模型有什么区别如果 P99 延迟升高你会优先查看哪些指标回答q1. 如何使用 goroutine 和 channel 组织并发请求任务队列 固定数量 worker模型主 goroutine 将请求任务写入jobschannel启动不超过最大并发数的 worker每个 worker 循环读取任务、执行请求并将结果写入resultschannel。这样做的好处是可以复用固定数量的 goroutine不需要为 1000 个请求一次性创建 1000 个 goroutine。jobschannel 负责分发任务resultschannel 负责传递结果q2. 如何限制最大并发数有哪些实现方式常见实现方式有三种固定数量 worker直接启动concurrency个 worker每个 worker 同时只处理一个任务。带缓冲 channel 作为信号启动任务前向容量为concurrency的 channel 写入一个令牌任务结束后取出令牌。semaphore使用golang.org/x/sync/semaphore管理并发许可。同时并发实现时需要配合sync waitgroup锁等机制来配合使用并保证并发安全防止出现脏数据q3. 全局取消、单请求超时和程序退出之间是什么关系全局取消任务整体被停止比如收到操作系统层面的SIGINT信号后调用context 的cancel()。实现全局取消的前提是所有任务、worker 和请求都应该监听这个 context。单请求超时在context 下为某个请求创建context.WithTimeout子 context只影响该请求超时后应记录为超时结果并释放资源。程序退出程序预期中的退出任务完成优雅的退出并清理释放资源q4. 多个 goroutine 如何安全地统计测试结果有三种可行方案worker 只负责发送Result由一个 collector goroutine 串行更新计数器和延迟数组对共享计数器或切片使用sync.Mutex保护这也是最简单和常用的方法对简单的成功数、失败数使用sync/atomic延迟明细仍由单独 collector 收集。q5. 如果收到 CtrlC应该如何停止新请求并处理正在执行的请求收到CtrlC后调用根 context 的cancel()。任务生产者在投递任务前监听ctx.Done()取消后不再投递新任务worker 在取任务和执行任务时也监听ctx.Done()。q6. 如何验证程序没有 goroutine 泄漏可以采用以下方法在测试前后记录runtime.NumGoroutine()重复执行多轮取消测试观察数量是否持续增长使用pprof.Lookup(goroutine)或runtime/trace查看 goroutine 的调用栈和生命周期使用go.uber.org/goleak等测试工具辅助检测为 jobs、results 和 worker 的退出路径设置明确的关闭和等待逻辑使用go test -race检查数据竞争但要明确-race不能替代 goroutine 泄漏检测。q7. “固定并发”与“固定每秒请求数”两种压测模型有什么区别固定并发始终维持固定数量的活跃请求。一个请求完成后才补充下一个请求。它形式上比较类似于并发测试固定请求按照固定速率产生新请求例如每秒启动 20 个请求不等待之前的请求完成。形式上比较类似于新建测试q8. 如果 P99 延迟升高你会优先查看哪些指标“确认现象 → 拆分链路 → 关联资源 → 验证根因”的顺序定位确认时间窗口、样本量和统计口径对比 P50、P95、P99、错误率和吞吐量判断是整体变慢还是少量长尾变慢。查看最近是否发生版本发布、模型切换、配置修改、扩缩容或流量结构变化特别关注输入和输出 Token 长度分布。将端到端延迟拆成网关、排队、Prefill、Decode、网络传输和下游依赖耗时。查看推理服务的排队长度、batch 大小、TTFT、TPOT、GPU 利用率、显存和 KV Cache 占用以及 OOM 和重试情况。查看 CPU、内存、GC、连接数、负载均衡是否倾斜、网络丢包/重传和下游服务状态。根据 request ID 抽取 P99 慢请求关联日志和 Trace最后通过回滚、降低流量、隔离实例或复现实验验证根因。不能因为只有 P99 升高就直接排除网络问题网络抖动、连接复用异常和负载均衡倾斜都可能主要表现为长尾延迟。题目2 Go 小型工程练习实现一个可取消、限并发的任务执行器请实现下面的函数暂时不要求真正调用 HTTP 接口typeResultstruct{SuccessboolLatencyMsint64Errerror}funcRunLoadTest(ctx context.Context,totalint,concurrencyint,)[]Result要求如下使用context.Context支持任务取消。最大并发数不能超过concurrency。每个任务随机模拟 10100 毫秒的执行耗时。收集每个任务的执行结果。ctx取消后不再启动新任务。已经开始执行的任务应能够感知取消并尽快退出。结果收集不能产生数据竞争。使用go test -race检查并发安全性。思考如何验证程序没有 goroutine 泄漏。
返回列表