4. 医疗SaaS平台总体架构设计
医疗SaaS平台的总体架构不是把“微服务”“DDD”“网关”这些词堆在一起,而是要让它们各自解决一个具体问题:分层架构解决职责边界与依赖方向,微服务划分解决业务能力独立演进与弹性伸缩,领域驱动设计解决医疗业务语义复杂、规则密集的建模问题,前后端分离与API网关解决多端接入、安全管控与流量治理问题。下面从“怎么分、怎么划、怎么落、怎么接”四个角度展开。
一、分层架构:先定依赖方向,再谈技术选型
医疗SaaS平台建议采用五层结构,自上而下为:接入层、应用层、领域层、基础设施层、数据层。依赖方向必须单向向下,领域层不依赖任何框架和外部服务,只依赖抽象接口。这样做的直接收益是:医保政策、临床规则、计费逻辑变化时,改动集中在领域层,不会波及接入层和基础设施层。
接入层负责协议适配与安全入口,包括HTTPS终止、JWT校验、租户识别、限流。应用层负责用例编排,例如“预约挂号”用例依次调用患者校验、号源锁定、订单生成、通知发送,它只做流程协调,不写业务规则。领域层承载聚合、实体、值对象和领域服务,是医疗规则的核心落点。基础设施层提供数据库、缓存、消息队列、对象存储、第三方接口(医保、LIS、PACS、短信)的具体实现。数据层按租户隔离策略组织,通常采用共享库+租户字段,对合规要求高的租户可升级为独立库。
二、微服务划分:按业务能力切,不按技术切
医疗SaaS的微服务划分应围绕业务能力,而不是围绕“用户服务、订单服务、日志服务”这类技术分层。推荐划分为:患者服务、预约挂号服务、门诊服务、住院服务、医嘱服务、计费与结算服务、药品与库存服务、检验检查服务、医保对接服务、消息通知服务、租户与权限服务、报表与运营服务。每个服务拥有独立数据库schema,禁止跨服务直连数据库。
服务粒度控制原则:一个服务对应一个限界上下文,一个事务只在一个服务内完成。跨服务一致性用领域事件+最终一致性,例如“医嘱已开立”事件触发计费服务生成待收费项,而不是在医嘱服务里直接写计费表。对于强一致要求高的场景,如号源扣减,采用Redis原子操作+数据库唯一约束双重保障,避免超卖。
三、领域驱动设计在医疗业务中的落地
以“预约挂号”限界上下文为例,聚合根是Appointment,实体包括Patient、ScheduleSlot,值对象包括TimeRange、VisitType、RegistrationFee。领域服务SlotAllocationService负责号源分配规则,仓储接口AppointmentRepository定义在领域层,实现放在基础设施层。
医疗业务中大量规则适合用值对象和领域服务表达。例如挂号费计算:RegistrationFee = baseFee + doctorTitleSurcharge + visitTypeSurcharge - insuranceDiscount。其中baseFee由医院等级决定,doctorTitleSurcharge由医生职称决定,visitTypeSurcharge由普通/专家/急诊决定,insuranceDiscount由医保类型和报销比例决定。这些规则应封装在FeeCalculationService中,而不是散落在Controller或SQL里。
领域事件是解耦的关键。预约成功后发布AppointmentCreated事件,通知服务发送短信,计费服务生成待缴费记录,报表服务更新统计。事件携带appointmentId、patientId、tenantId、occurredAt,消费方幂等处理,避免重复扣费或重复通知。
四、前后端分离与API网关设计
前后端分离的核心不是“前端用Vue、后端用Spring Boot”,而是接口契约先行。推荐使用OpenAPI 3.0定义接口,前端通过openapi-generator生成TypeScript客户端,后端通过同一份YAML生成Controller接口骨架。这样字段名、类型、必填项在前后端之间不会漂移。医疗场景中,患者姓名、身份证号、手机号属于敏感字段,接口返回时默认脱敏,前端展示层再做二次掩码。
API网关承担六项职责:路由转发、认证鉴权、租户识别、限流熔断、日志审计、协议转换。以Spring Cloud Gateway为例,核心配置如下:
spring:
cloud:
gateway:
routes:
- id: appointment-service
uri: lb://appointment-service
predicates:
- Path=/api/v1/appointments/**
filters:
- StripPrefix=2
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 50
redis-rate-limiter.burstCapacity: 100
key-resolver: "#{@tenantKeyResolver}"
其中tenantKeyResolver从JWT的tenant_id声明中提取租户标识,实现按租户限流。这样单个租户突发流量不会拖垮整个平台。网关还应在GlobalFilter中注入X-Tenant-Id和X-Request-Id,下游服务据此做数据隔离和链路追踪。
前后端分离后,跨域问题由网关统一处理,前端只访问网关域名。对于文件上传(如检验报告PDF),采用前端直传对象存储+后端签发临时凭证的方式,避免大文件穿透网关。对于实时消息(如叫号提醒),使用WebSocket网关或SSE,网关层做连接数限制和心跳检测。
总体而言,医疗SaaS平台的架构设计要围绕“合规、隔离、可演进”三个目标。分层架构保证依赖可控,微服务划分保证业务能力独立,DDD保证医疗规则内聚,前后端分离与API网关保证多端接入的安全与稳定。四者配合,才能支撑多租户、多院区、多医保类型的复杂医疗业务持续迭代。