4. Mock服务设计原则与架构:Mock服务的目标、接口定义、状态管理、延迟模拟、错误注入设计
在构建OAuth2.0 Mock服务时,设计原则直接决定了服务的可用性、可观测性以及测试覆盖能力。一个优秀的Mock服务不仅仅是“返回假数据”,而是一个具备可控状态、可编程延迟、可注入错误的仿真系统。本节将围绕Mock服务的核心设计目标,拆解接口定义、状态管理、延迟模拟与错误注入四大关键架构维度。
4.1 Mock服务设计目标
OAuth2.0 Mock服务的核心目标是在不依赖真实授权服务器的情况下,模拟完整的授权码流程、客户端凭证流程、令牌刷新与撤销流程。设计目标可归纳为以下五点:
| 目标 | 说明 | 可观测性关注点 |
|---|---|---|
| 协议兼容 | 严格遵循RFC 6749、RFC 7009、RFC 7662标准 | 请求/响应结构校验日志 |
| 状态可控 | 支持多租户、多会话、多授权码状态独立管理 | 状态变更事件、过期时间追踪 |
| 延迟可编程 | 支持按端点、按场景配置固定/随机/阶梯延迟 | 延迟分布直方图、P99/P50指标 |
| 错误可注入 | 支持HTTP错误码、协议错误、网络级异常注入 | 错误注入触发记录、错误率告警 |
| 可观测性原生 | 内置Metrics、Tracing、Logging三支柱 | 请求链路追踪、指标暴露、结构化日志 |
4.2 接口定义与端点设计
Mock服务需要暴露与真实OAuth2.0授权服务器一致的端点。以下为核心端点定义清单:
- 授权端点
GET /oauth2/authorize— 模拟用户授权页面,支持response_type=code,返回授权码或错误。 - 令牌端点
POST /oauth2/token— 支持authorization_code、client_credentials、refresh_token三种grant_type。 - 令牌撤销端点
POST /oauth2/revoke— 模拟令牌撤销逻辑,返回200或400。 - 令牌 introspection 端点
POST /oauth2/introspect— 返回令牌的活跃状态、scope、client_id等信息。 - JWKS端点
GET /oauth2/jwks— 返回模拟的JSON Web Key Set,用于令牌签名验证。 - 管理端点
POST /mock/admin/state— 用于测试框架动态设置Mock状态、延迟、错误注入规则。
4.3 状态管理设计
状态管理是Mock服务的核心复杂度所在。OAuth2.0流程涉及授权码、访问令牌、刷新令牌、客户端注册等多类状态对象。设计时需考虑以下维度:
| 状态对象 | 生命周期 | 关键属性 | 过期策略 |
|---|---|---|---|
| 授权码 (authorization_code) | 单次使用,默认60秒 | code, client_id, redirect_uri, scope, code_challenge | TTL过期 + 使用后立即删除 |
| 访问令牌 (access_token) | 可配置,默认3600秒 | token, client_id, scope, token_type, expiry | TTL过期 + 撤销标记 |
| 刷新令牌 (refresh_token) | 可配置,默认86400秒 | token, client_id, scope, rotation_count | TTL过期 + 轮换策略 |
| 客户端注册 (client) | 持久化,直到显式删除 | client_id, client_secret, redirect_uris, grant_types | 无自动过期,支持软删除 |
状态存储建议使用内存中的并发安全Map(如Go的sync.Map或Java的ConcurrentHashMap),配合定时清理协程处理过期状态。对于分布式测试场景,可扩展为Redis后端,但需注意序列化与网络延迟对Mock性能的影响。
4.4 延迟模拟设计
延迟模拟用于测试客户端在非理想网络条件下的行为。设计时需支持以下三种延迟模式:
- 固定延迟 — 每个请求等待固定毫秒数,适用于模拟稳定的网络延迟基线。
- 随机延迟 — 在[min, max]区间内均匀或正态分布随机延迟,模拟真实网络抖动。
- 阶梯延迟 — 按请求次数递增延迟(如第1次0ms,第2次100ms,第3次500ms),用于测试重试与退避策略。
延迟模拟的配置可通过管理端点动态注入,支持按端点、按client_id、按scope进行精细化控制。以下为延迟配置的JSON示例:
{
"endpoint": "/oauth2/token",
"delay_mode": "random",
"min_ms": 100,
"max_ms": 500,
"distribution": "uniform",
"apply_to": {
"client_id": "test-client-01",
"scope": "openid profile"
}
}
4.5 错误注入设计
错误注入是Mock服务区别于普通Stub的关键能力。设计时需覆盖以下错误类型:
| 错误类别 | 示例 | 注入方式 | 可观测性记录 |
|---|---|---|---|
| HTTP协议错误 | 500 Internal Server Error, 503 Service Unavailable | 按端点配置返回指定状态码 | 记录错误码、触发规则、请求ID |
| OAuth2协议错误 | invalid_grant, invalid_client, unauthorized_client | 按条件匹配返回标准错误响应 | 记录error、error_description、状态码 |
| 网络级异常 | 连接超时、连接重置、TLS握手失败 | 在Socket层注入异常(需代理模式) | 记录异常类型、注入点、持续时间 |
| 数据异常 | 返回格式错误的JWT、缺失字段、过期时间异常 | 修改响应体结构或字段值 | 记录原始响应与修改后响应的差异 |
错误注入规则应支持条件匹配,例如:仅当请求中包含特定scope时返回invalid_scope;仅当令牌过期时间小于30秒时返回令牌无效。这种条件式注入可以模拟真实场景中的边界情况。
4.6 Mock服务整体架构
综合以上设计原则,Mock服务的整体架构如下图所示。该架构将协议端点、状态管理、延迟模拟、错误注入与可观测性模块有机整合,形成一个可编程、可观测的OAuth2.0仿真系统。
架构图中各层职责清晰:客户端层发起请求,API网关层负责路由分发与协议端点隔离,核心引擎层处理OAuth2.0协议逻辑,状态管理层维护所有状态对象的生命周期,延迟与错误注入层提供可编程的故障模拟能力,可观测性层负责采集与暴露三支柱数据。各层之间通过明确的接口进行交互,便于独立扩展与测试。
4.7 可观测性集成要点
Mock服务的可观测性设计应贯穿所有模块,而非事后追加。以下是各模块的可观测性集成要点:
- 请求追踪 — 每个请求生成唯一Trace ID,贯穿网关、引擎、状态管理、错误注入全链路。在Span中记录端点、延迟模式、错误注入规则等上下文信息。
- 指标暴露 — 暴露请求总数、成功率、延迟分布(P50/P90/P99)、错误注入触发次数、状态对象数量等核心指标。使用Prometheus格式暴露,便于Grafana可视化。
- 结构化日志 — 每条日志包含timestamp、level、trace_id、endpoint、client_id、error_code等结构化字段。日志级别支持动态调整,便于问题排查时临时开启Debug日志。
- 健康检查 — 暴露/healthz和/readyz端点,返回各模块的健康状态。状态管理模块应检查过期清理协程是否正常运行,错误注入模块应检查规则引擎是否可用。