4. 医疗微服务网关治理

在医疗微服务架构中,API网关是所有外部请求进入系统的唯一入口。它承担的不只是反向代理职责,更是医疗数据安全与业务连续性的第一道防线。与普通互联网业务不同,医疗系统面临更严格的合规约束(如患者隐私保护、诊疗数据最小化暴露)和更复杂的调用场景(院内HIS、LIS、PACS、互联网医院、第三方医保结算等)。因此,网关治理必须同时解决五个核心问题:请求如何正确路由到目标服务、调用方身份如何可信鉴权、突发流量如何限流保护、下游故障如何熔断隔离、以及响应中的敏感医疗数据如何脱敏。

一、路由:从请求特征到目标服务

网关路由的本质是“匹配条件 + 转发目标”。在医疗场景中,路由条件通常由路径前缀、请求方法、请求头(如院区标识、终端类型)共同决定。例如,将 /api/patient/** 路由到患者服务,将 /api/order/** 路由到医嘱服务,而 /api/report/** 则可能根据请求头中的 X-Hospital-Id 转发到不同院区的报告服务。

实际配置中,路由规则应遵循“精确优先、前缀兜底”的原则。以下是一个基于 Spring Cloud Gateway 风格的路由配置示例(示例参数,非实测):

spring:
  cloud:
    gateway:
      routes:
        - id: patient-service
          uri: lb://patient-service
          predicates:
            - Path=/api/patient/**
            - Method=GET,POST
          filters:
            - StripPrefix=2
        - id: report-service
          uri: lb://report-service
          predicates:
            - Path=/api/report/**
            - Header=X-Hospital-Id, \d+

路由匹配失败时,网关应返回统一的 404 结构体,而不是暴露内部服务列表。同时,路由目标建议使用服务发现(如 Nacos)而非硬编码 IP,以便服务实例扩缩容时无需修改网关配置。

二、鉴权:医疗调用方的身份与权限

医疗网关的鉴权需要区分三类调用方:院内终端(医生站、护士站)、患者端(App、小程序)、第三方系统(医保、区域平台)。鉴权流程通常为:提取令牌 → 校验签名与有效期 → 解析角色与数据权限 → 注入下游请求头。

令牌建议采用 JWT,并在网关层完成签名校验,避免每个微服务重复实现。校验通过后,网关将用户身份、角色、可访问院区等信息写入 X-User-Id、X-Role、X-Data-Scope 等请求头,下游服务直接信任这些头即可。需要特别注意的是,网关必须剥离外部传入的同名头,防止伪造。

医疗数据权限常与“数据范围”绑定,例如某医生只能访问本科室患者。网关鉴权只解决“能不能进”,数据范围过滤仍需下游服务结合 X-Data-Scope 在查询层实现,二者不可混淆。

三、限流:保护核心医疗业务

限流的目标不是拒绝用户,而是防止个别调用方或突发流量拖垮核心服务。医疗场景中,挂号、缴费、报告查询等接口的优先级不同,限流策略也应差异化。常用算法有令牌桶和漏桶,网关层多采用令牌桶,因为它允许一定程度的突发。

限流维度可按“接口 + 调用方”组合。例如,对 /api/report/query 限制每个患者账号每分钟 20 次,对第三方医保接口限制每秒 50 次。以下为示例参数:

接口限流维度阈值(示例)超限行为
/api/register/submit患者ID5次/分钟返回429,提示稍后重试
/api/report/query患者ID20次/分钟返回429
/api/insurance/settle调用方AppId50次/秒排队等待或拒绝

限流阈值应结合压测结果和业务峰值设定,并支持动态调整。网关应记录被限流的调用方和接口,便于后续分析是否为恶意刷取或配置过严。

四、熔断:下游故障时的快速失败与隔离

当某个下游服务响应变慢或错误率升高时,继续转发请求会耗尽网关线程资源,进而影响其他正常服务。熔断器通过统计最近一段时间的失败率来决定是否“跳闸”。以 Resilience4j 为例,可配置滑动窗口 10 次、失败率阈值 50%、熔断打开后等待 30 秒再进入半开状态。

熔断打开期间,网关直接返回降级响应,例如报告查询服务不可用时返回“报告服务暂时繁忙,请稍后重试”,而不是让请求堆积。半开状态下允许少量请求探测下游是否恢复,若成功则关闭熔断,恢复正常转发。

五、医疗数据脱敏:响应出网关前的最后一道关卡

脱敏是医疗网关区别于普通网关的关键能力。患者姓名、身份证号、手机号、病历号、诊断信息等都属于敏感数据。脱敏应在响应返回给调用方之前完成,且要根据调用方角色决定脱敏强度。例如,医生站可看到完整姓名,患者端只能看到“张*”,第三方系统默认只返回脱敏后的标识。

实现上,可在网关响应过滤器中基于 JSON 路径进行字段替换。以下为脱敏规则示例:

{
  "rules": [
    {"path": "$.patient.name", "role": "PATIENT", "action": "mask", "keep": 1},
    {"path": "$.patient.idCard", "role": "THIRD_PARTY", "action": "hash"},
    {"path": "$.patient.phone", "role": "PATIENT", "action": "mask", "keep": 3}
  ]
}

脱敏规则应集中管理,避免散落在各业务服务中。同时,网关日志中也不得记录原始敏感字段,否则脱敏只做了一半。

医疗微服务网关治理链路 院内终端 医生站/护士站 患者端 App/小程序 第三方系统 医保/区域平台 API 网关治理层 ① 鉴权 JWT校验 → 注入 X-User-Id / X-Role / X-Data-Scope ② 路由 Path + Method + Header → 目标微服务 ③ 限流 令牌桶:接口 + 调用方维度,超限返回429 ④ 熔断 失败率超阈值 → 打开 → 半开探测 → 恢复 ⑤ 脱敏 按角色对姓名/身份证/手机号做掩码或哈希 患者服务 patient-service 医嘱服务 order-service 报告服务 report-service 医保结算服务 insurance-service 降级 脱敏响应 请求自左向右依次经过鉴权、路由、限流、熔断;响应返回前执行脱敏,熔断打开时直接降级

六、治理效果的观察与判断

网关治理是否生效,不能只看配置是否下发,而要看可观测指标。建议在网关层统一采集以下数据:路由匹配成功率、鉴权失败率、限流触发次数、熔断状态变化、脱敏字段命中数。当鉴权失败率突然升高时,可能是令牌过期策略或调用方配置问题;当某接口限流触发频繁时,需要评估阈值是否过严或是否存在异常刷取;当熔断频繁打开时,应优先排查下游服务的响应时间和错误日志。

医疗网关的治理顺序建议为:先鉴权、再路由、后限流、熔断兜底、脱敏收尾。顺序颠倒可能导致未鉴权请求进入限流统计,或脱敏前数据已被记录到日志。

综合来看,医疗微服务网关治理不是单一功能的堆叠,而是一条从请求进入到响应返回的完整责任链。路由决定“去哪里”,鉴权决定“能不能进”,限流决定“进多少”,熔断决定“下游坏了怎么办”,脱敏决定“出去的数据长什么样”。只有这五者协同工作,才能在保障医疗业务连续性的同时,守住患者数据安全的底线。