凌晨十点,某互联网大厂会议室。
玻璃门一关,气压立刻低了三度。

面试官周工,表情严肃,像是连 NullPointerException 都不敢在他面前随便抛。
求职者王小二,简历写着“精通 Java 全家桶,熟悉 AI Agent、RAG、微服务、云原生、大数据生态”。
他坐下时很自信,坐稳后又有点像刚被 GC 标记过。

这次面试的业务背景,是一套互联网医疗健康管理+AIGC智能客服平台
平台包含在线问诊、健康档案、药品商城、医生排班、智能客服、企业知识库问答、订单支付、风控审计等模块,技术栈以 Java 为主,运行在 Kubernetes 上。


第一轮:从单体到微服务,先看你能不能把系统搭起来

问题1:

面试官:
假设我们要做一个互联网医疗平台,包含用户、医生、挂号、订单、支付、病历、智能客服几个核心模块。你会怎么用 Java 技术栈做第一版架构?选型也说一下。

王小二:
这个……我会用 Java 17,因为新一点,看起来比较高级。然后框架嘛,肯定 Spring Boot,启动快,面试也爱听。
服务拆分的话,就拆成用户服务、医生服务、订单服务、支付服务、病历服务、客服服务。
数据库用 MySQL,ORM 我一般 MyBatis 和 JPA 都能写,看团队风格。
服务之间可以用 OpenFeign 调,注册发现可以用 Eureka 或 Consul。
缓存上 Redis,消息队列上 Kafka 或 RabbitMQ。
部署的话 Docker 加 Kubernetes,监控就 Prometheus 和 Grafana。

面试官:
回答得还算完整,至少不是“一个 Controller 走天下”。
那你继续说,为什么第一版不是直接上 WebFlux 和 R2DBC 全异步?

王小二:
因为……因为先活下来比较重要。大部分医疗后台还是 CRUD 比较多,Spring MVC 配合 JPA、MyBatis 更稳。WebFlux 更适合高并发 I/O 场景,比如流式推送、AI 对话。

面试官:
不错,这句说到点子上了。


问题2:

面试官:
挂号服务里,医生排班和患者预约很容易出现并发冲突。比如同一个号源最后一个名额,被两个人同时抢到。你怎么处理?

王小二:
这个我会先想到数据库层。
比如库存字段 remaining_count,更新时带条件:where remaining_count > 0,更新成功才算抢到。
也可以用乐观锁版本号,比如 JPA 的 @Version
如果并发更大,就加 Redis 做预扣减,再异步落库。
实在不放心,还可以把预约请求丢 Kafka,排队串行消费。

面试官:
行,知道“别让两个病人拿同一个号”这件事要靠数据一致性,不靠祈祷。
那 Redis 预扣减失败和数据库写入失败的补偿,你考虑了吗?

王小二:
这个……一般会有补偿任务。
或者用消息事务……或者本地消息表……
大概就是,不能让 Redis 和数据库各过各的。

面试官:
嗯,后半句开始有点飘了,不过方向没错。


问题3:

面试官:
你说说 MyBatis、JPA、Hibernate 在这个场景里怎么选。别背定义,说实际业务。

王小二:
如果是用户、医生、病历这种对象关系比较明确、关联也比较多的模块,我会偏 JPA/Hibernate,开发快,适合后台管理系统。
如果是订单、报表、复杂查询、分页筛选、多表统计,我更倾向 MyBatis,SQL 可控。
有些简单服务也可以用 Spring Data JDBC,模型更轻。
连接池用 HikariCP,性能和稳定性都更主流。
数据库版本管理可以上 Flyway 或 Liquibase。

面试官:
不错,这个回答挺像干过活。
那病历查询为什么不全上 Elasticsearch?

王小二:
因为 Elasticsearch 适合检索,不适合做强事务主存储。
病历原始数据还是落 MySQL,检索索引异步同步到 Elasticsearch 比较稳。

面试官:
很好。


问题4:

面试官:
如果挂号成功后,需要发送短信、站内信、医生工作台提醒、患者 App 消息,你会怎么设计消息链路?

王小二:
我会把“挂号成功”作为领域事件发出去。
订单服务提交成功后,发 Kafka 消息,多个消费者分别处理短信、App Push、医生提醒。
如果业务需要更强路由能力,也可以用 RabbitMQ。
消息体可以用 Jackson 序列化 JSON;如果追求高性能和跨语言,可以用 Protobuf 或 Avro。
为了避免重复消费,要做幂等,比如消息表、业务唯一键、去重 Redis Key。

面试官:
可以,至少你知道 MQ 不是“发了就一定成”。
第一轮到这里。


第二轮:系统能跑起来还不够,你得让它撑住、守住、看得见

问题5:

面试官:
现在平台用户量起来了,问诊高峰期每秒几千请求。你怎么做缓存设计?说说 Redis、Caffeine、Spring Cache 分别怎么用。

王小二:
Redis 适合分布式缓存,比如医生详情、科室列表、号源快照。
Caffeine 适合单机热点缓存,比如本机短期高频字典数据。
Spring Cache 可以统一缓存注解,底层接 Redis 或 Caffeine。
缓存要注意穿透、击穿、雪崩。
穿透可以布隆过滤器或缓存空值;击穿可以互斥锁或热点永不过期加异步刷新;雪崩要加过期时间随机化和多级缓存。

面试官:
不错,这段答得挺顺。
那患者健康档案能不能直接全部丢 Redis?

王小二:
不能。这个数据敏感、体量大、更新也复杂。Redis 更适合热点读,不适合作为长期主存。
核心还是数据库,缓存只是加速层。

面试官:
嗯,没把 Redis 当万能冰箱,这点很好。


问题6:

面试官:
支付和医疗数据都很敏感。你说说 Spring Security、JWT、OAuth2、Keycloak 在这个系统里怎么落地。

王小二:
用户登录可以用 Spring Security 做认证鉴权。
移动端和小程序登录后签发 JWT,网关校验令牌。
如果平台有医生端、患者端、运营后台、第三方药企后台,多租户和统一身份管理可以引入 OAuth2 或 Keycloak。
权限模型上可以做 RBAC,接口按角色、资源、数据范围控制。
敏感字段比如身份证号、手机号可以加密存储,必要时用 Bouncy Castle 做加解密能力支持。
此外,操作病历、处方这些高风险接口,要做审计日志。

面试官:
回答合格。
那 JWT 一旦签发,用户被封禁了怎么办?

王小二:
这个……可以缩短 JWT 有效期,再配合 Redis 黑名单。
或者做双 Token 机制,Access Token 短效,Refresh Token 控制续签。

面试官:
行,比“让用户重新登录试试”强。


问题7:

面试官:
微服务之间经常有超时、雪崩。你说说 OpenFeign、Resilience4j、网关限流、熔断降级怎么配合。

王小二:
服务调用可以用 OpenFeign。
如果医生服务慢了,订单服务直接同步等,就容易把线程池拖死。
所以要做超时控制、重试、舱壁隔离、熔断和限流,Resilience4j 很适合。
比如查询医生画像失败,就降级返回基础信息;推荐标签失败,不影响挂号主链路。
API 网关层可以做统一限流和鉴权,防止恶意刷接口。
下游不可用时,可以快速失败,不要层层等待。

面试官:
不错。
那重试是不是越多越好?

王小二:
不是。重试太多可能把本来就快挂的服务彻底按死。
重试只适合幂等读操作或少量可控场景,支付扣款这类要非常谨慎。

面试官:
很好,这句靠谱。


问题8:

面试官:
线上出了问题,你怎么排查?把日志、指标、链路追踪说完整。

王小二:
日志方面我会统一 SLF4J 门面,底层用 Logback 或 Log4j2。
把 traceId、userId、orderId 放到 MDC 里,便于串联日志。
指标方面用 Micrometer 暴露 JVM、线程池、HTTP、数据库连接池指标给 Prometheus,再用 Grafana 做看板。
链路追踪可以接 Jaeger 或 Zipkin,看一次请求经过了哪些服务。
日志聚合可以上 ELK Stack。
如果发现接口 RT 飙升,要看是 CPU 高、GC 频繁、数据库慢查询、MQ 堆积还是外部依赖超时。

面试官:
不错,排障思路比很多只会说“重启试试”的强。
第二轮结束。


第三轮:现在加 AI,别把系统做成“智能胡说平台”

问题9:

面试官:
公司现在要做 AI 智能客服,支持医保政策问答、医院流程问答、药品说明检索。你会怎么用 Spring AI 和 RAG 落地?

王小二:
这个我熟,我简历上写了三遍。
大概流程是:先把医院制度、药品说明书、医保文档、常见问答导入知识库;然后切片;然后向量化;再存到向量数据库,比如 Milvus、Chroma 或 Redis Vector。
用户提问后,先做语义检索,拿到相关片段,再拼进 Prompt,最后交给大模型回答。
Spring AI 可以帮我们统一模型调用、Embedding、向量检索这些流程。
这样比模型“裸答”更靠谱,能减少幻觉。

面试官:
嗯,这个回答不错。
那你继续说,文档切片怎么做?是按 1000 字一刀切?

王小二:
这个……也不一定。
有时候按标题层级切,有时候按段落切。
反正就是,切得太大检索不准,切得太小上下文不够。
要根据业务调。

面试官:
你这句虽然有点像废话,但确实是对的。


问题10:

面试官:
如果用户问:“我高血压还能不能吃这个药?”你觉得企业文档问答和医疗建议之间的边界怎么控制?怎么避免 AI 幻觉带来风险?

王小二:
这个不能让 AI 直接当医生。
可以把它定位成“信息辅助”,比如引用药品说明书、医院规范、挂号流程,而不是直接给诊断结论。
回答里要带来源片段、免责声明。
高风险问题可以触发转人工或转医生。
还可以做提示词约束,不在知识库里的问题不要乱答。
另外把审核规则加上,比如命中禁答词、处方建议、高风险病症,就不让模型自由发挥。

面试官:
可以,风险意识合格。
那如果用户追问十轮,系统怎么保留会话上下文?

王小二:
可以做聊天会话内存。
短期上下文存在 Redis,长期摘要落库。
也可以把历史对话摘要后再拼接到 Prompt 里,避免 Token 爆炸。

面试官:
嗯,还行。


问题11:

面试官:
如果我们要做 Agent,让 AI 帮用户完成“查报告、预约复诊、推送用药提醒”这种复杂工作流,你怎么设计工具执行框架?

王小二:
我会把 AI 当成决策层,不让它直接乱调内部系统。
先定义标准化工具接口,比如查询报告、查询排班、创建预约、发送提醒。
工具调用要有权限校验、参数校验、审计日志。
模型只负责决定“该调哪个工具”,真正执行还是后端服务做。
如果是多步骤流程,可以做状态机或者编排流。
如果再高级一点,还可以做 MCP 或类似协议,把工具能力标准化接入。

面试官:
前面说得不错。
那 Agentic RAG 和普通 RAG 的区别呢?

王小二:
这个……普通 RAG 就是检索再回答。
Agentic RAG 可能就是……更聪明一点?
会自己规划、多跳检索、可能还会调用工具。
大概是从“查一遍”升级成“边查边想边干”。

面试官:
你最后这句,土是土了点,但意思差不多。


问题12:

面试官:
最后一个问题。你怎么保证这套系统能持续交付?从测试、CI/CD 到上线发布说一下。

王小二:
单元测试用 JUnit 5、Mockito、AssertJ。
历史遗留不好 mock 的代码,可能会碰到 PowerMock,但新项目尽量少用。
接口测试可以用 Spring Boot Test,端到端页面流程可以用 Selenium,业务验收可以用 Cucumber。
构建用 Maven 或 Gradle。
CI/CD 用 Jenkins、GitLab CI 或 GitHub Actions。
打包 Docker 镜像,发到 Kubernetes。
数据库变更用 Flyway 或 Liquibase 管理。
发布可以做灰度、蓝绿或滚动更新。
上线后通过 Prometheus、Grafana、ELK 看指标和日志,不行就回滚。

面试官:
整体还行。
你会的东西不少,懂的深浅嘛……有些地方像温水泡枸杞,颜色有了,药劲差点。
今天先到这里,回去等通知吧。

王小二:
好的老师。我这边如果有结果,是您通知我,还是 Kafka 异步通知我?

面试官:
……门在你右手边。


面试题答案精讲

下面把上面 12 个问题的标准答案,用小白也能看懂的方式详细展开。


1. 互联网医疗平台第一版架构怎么设计?

业务场景

一个互联网医疗平台,至少会有这些核心能力:
用户注册登录、医生信息展示、排班挂号、订单支付、病历查看、消息通知、智能客服。

推荐技术方案

  • Java 版本:优先 Java 17,兼顾性能、语法增强、LTS 支持

  • 基础框架:Spring Boot

  • Web 层:大多数后台接口用 Spring MVC

  • AI 对话或流式返回:可局部使用 Spring WebFlux

  • 服务治理:Spring Cloud、OpenFeign、Consul/Eureka

  • 数据库:MySQL/PostgreSQL

  • ORM:JPA/Hibernate 处理标准对象模型,MyBatis 处理复杂 SQL

  • 缓存:Redis

  • 消息队列:Kafka 或 RabbitMQ

  • 部署:Docker + Kubernetes

  • 监控:Micrometer + Prometheus + Grafana

  • 日志:SLF4J + Logback/Log4j2

  • 文档:Swagger/OpenAPI

初期为什么不建议一上来全异步?

因为大部分业务是标准事务型接口,例如注册、挂号、支付订单查询,这类场景:

  • 逻辑清晰

  • 阻塞式开发更直接

  • 团队更容易维护

  • 排错更简单

WebFlux/R2DBC 更适合

  • 流式 AI 对话

  • 长连接消息推送

  • 高并发 I/O 聚合场景

所以第一版系统通常是:
核心交易链路走 Spring MVC,局部高并发/流式模块再引入 WebFlux。


2. 医生号源并发抢占怎么处理?

业务场景

医生某时间段只剩 1 个号源,两个用户同时点击预约。

风险

如果处理不好,就会出现:

  • 超卖

  • 重复挂号

  • 数据不一致

常见方案

方案一:数据库条件更新
update doctor_schedule
set remaining_count = remaining_count - 1
where schedule_id = ? and remaining_count > 0;

如果更新行数为 1,说明抢号成功;为 0,说明没抢到。

优点:简单可靠
缺点:高并发下数据库压力大

方案二:乐观锁

JPA/Hibernate 可用 @Version 字段控制版本号。

适合:

  • 冲突不是特别极端

  • 需要在应用层处理重试逻辑

方案三:Redis 预扣减 + 异步落库

流程:

  1. Redis 先扣号源

  2. 扣减成功后发 MQ

  3. 消费者写数据库

  4. 失败时做补偿

适合高并发秒杀式场景。

补偿机制

如果 Redis 扣了,但数据库失败,需要:

  • 本地消息表

  • 死信队列

  • 重试任务

  • 对账任务

核心原则

强一致核心数据不能只信缓存,一定要以数据库或可靠事务机制兜底。


3. MyBatis、JPA、Hibernate、Spring Data JDBC 怎么选?

JPA/Hibernate 适合什么?

适合:

  • 用户、医生、科室、权限等标准领域模型

  • 对象关系清晰

  • 开发效率优先

优点:

  • 开发快

  • 统一实体管理

  • 支持懒加载、级联、乐观锁

缺点:

  • 复杂 SQL 可控性不如 MyBatis

  • 不熟悉容易踩 N+1 查询坑

MyBatis 适合什么?

适合:

  • 复杂列表查询

  • 多表 join

  • 统计报表

  • 动态 SQL

  • 性能调优要求高的模块

优点:

  • SQL 完全可控

  • 易做复杂查询优化

缺点:

  • 模板代码较多

  • 纯 CRUD 时开发效率不如 JPA

Spring Data JDBC 适合什么?

适合:

  • 模型简单

  • 不需要复杂对象关联

  • 希望比 JPA 更轻量

实战建议

一个大型项目里,JPA 和 MyBatis 混用非常常见:

  • 核心后台管理模型:JPA/Hibernate

  • 复杂查询与报表:MyBatis

  • 连接池:HikariCP

  • 数据库变更:Flyway/Liquibase


4. 挂号成功后的通知链路怎么设计?

业务场景

挂号成功后,要同时触发:

  • 短信通知

  • App 推送

  • 医生工作台待办

  • 站内信

  • 后续统计埋点

为什么不用同步串行调用?

如果订单服务在一个请求里同步调完所有通知服务,会导致:

  • 耦合严重

  • 响应变慢

  • 某个通知服务挂了影响主流程

正确做法:事件驱动

订单服务完成后发一个事件,比如:
AppointmentCreatedEvent

由多个消费者分别处理:

  • 短信服务

  • Push 服务

  • 医生待办服务

  • BI 埋点服务

Kafka vs RabbitMQ

Kafka

适合:

  • 吞吐高

  • 日志型事件流

  • 多消费者订阅

  • 数据回放

RabbitMQ

适合:

  • 路由灵活

  • 延迟队列

  • 业务消息编排

幂等设计

MQ 至少一次投递时,要避免重复处理:

  • 消息唯一 ID

  • 数据库唯一约束

  • Redis 去重键

  • 消费记录表


5. Redis、Caffeine、Spring Cache 怎么组合用?

业务场景

热门医生详情页、科室列表、医院公告、药品基础信息访问量极高。

三级思路

1)Caffeine:本地缓存

适合单机热点数据:

  • 科室字典

  • 配置项

  • 高频静态数据

优点:

  • 速度极快

  • 不走网络

缺点:

  • 多实例之间不共享

2)Redis:分布式缓存

适合多个服务节点共享的数据:

  • 医生详情

  • 号源快照

  • 会话信息

  • 黑名单 Token

3)Spring Cache:统一抽象

通过注解:

  • @Cacheable

  • @CachePut

  • @CacheEvict

底层可接 Redis 或 Caffeine。

三大缓存问题

缓存穿透

查询不存在的数据,导致请求每次打数据库。
方案:

  • 缓存空值

  • 布隆过滤器

缓存击穿

热点 Key 过期瞬间,大量请求打数据库。
方案:

  • 互斥锁

  • 热点永不过期

  • 后台刷新

缓存雪崩

大量 Key 同时过期。
方案:

  • 过期时间加随机值

  • 多级缓存

  • 限流降级


6. Spring Security、JWT、OAuth2、Keycloak 怎么落地?

业务场景

平台有:

  • 患者端 App

  • 医生端工作台

  • 运营后台

  • 第三方合作机构接口

认证与鉴权分层

Spring Security

负责基础认证鉴权框架:

  • 登录

  • 权限拦截

  • 过滤器链

  • 方法级权限控制

JWT

适合无状态认证:

  • 用户登录后签发 Token

  • 网关或服务端校验

优点:

  • 不用每次查 Session

  • 适合分布式系统

缺点:

  • 签发后难立刻失效

OAuth2

适合:

  • 第三方授权

  • 统一身份平台

  • 多客户端接入

Keycloak

适合:

  • 企业统一身份认证

  • 单点登录

  • 多租户

  • 统一权限中心

安全增强

  • Access Token 短期有效

  • Refresh Token 控制续签

  • Redis 黑名单处理封禁/登出

  • 敏感字段脱敏/加密

  • 审计日志记录谁看了谁的病历


7. OpenFeign、Resilience4j、限流熔断怎么配合?

业务场景

订单服务要调用:

  • 用户服务

  • 医生服务

  • 优惠券服务

  • 支付服务

任何一个慢了,整条链路都可能被拖垮。

OpenFeign

用于服务间声明式调用,代码简洁。

Resilience4j 能做什么?

  • 超时控制

  • 重试

  • 熔断

  • 限流

  • 舱壁隔离

典型策略

超时

给每个下游调用设最大等待时间,避免线程长时间阻塞。

熔断

如果某服务持续失败,暂时不要继续打它,先快速失败。

降级

比如推荐服务挂了,只返回基础信息,不影响挂号主链路。

限流

避免某接口被刷爆,保护系统。

舱壁隔离

不同依赖使用不同线程池/信号量,防止一个服务故障拖死全系统。

注意

重试不是越多越好。
高峰期盲目重试,只会把故障扩大。


8. 线上故障怎么排查?

三大可观测性

1)日志
  • 门面:SLF4J

  • 实现:Logback / Log4j2

  • 关键字段:traceId、spanId、userId、orderId

为什么要 MDC?

MDC 能把同一请求的关键字段自动打到所有日志里,方便串联。

2)指标

Micrometer 暴露:

  • JVM 内存

  • GC 次数与耗时

  • 线程池状态

  • HTTP RT/QPS

  • 数据库连接池

  • MQ 消费积压

Prometheus 负责采集,Grafana 负责展示。

3)链路追踪

Jaeger / Zipkin 追踪一次请求流经了哪些服务。

常见排查路径

接口慢时按顺序看:

  1. 网关 RT 是否异常

  2. 某个服务 CPU 是否高

  3. JVM 是否频繁 Full GC

  4. 数据库是否有慢 SQL

  5. MQ 是否堆积

  6. 外部依赖是否超时

  7. 是否有缓存失效


9. Spring AI + RAG 怎么做企业文档问答?

业务场景

智能客服回答:

  • 医保报销流程

  • 住院须知

  • 医院制度

  • 药品说明书

  • 术前术后注意事项

RAG 流程

第一步:文档加载

来源可能包括:

  • PDF

  • Word

  • Excel

  • 网页

  • 知识库文章

第二步:文档切片

把长文档拆成适合检索的小段。

切片原则:

  • 太大:检索不准

  • 太小:上下文不完整

常见方式:

  • 按标题层级切

  • 按自然段切

  • 固定长度 + 重叠窗口

第三步:Embedding 向量化

把文本转成向量表示。
可使用:

  • OpenAI Embedding

  • Ollama 本地模型

  • 其他兼容模型

第四步:写入向量数据库

常见选择:

  • Milvus

  • Chroma

  • Redis Vector

第五步:检索增强生成

用户提问后:

  1. 把问题向量化

  2. 查最相关知识片段

  3. 拼到 Prompt

  4. 再交给模型生成答案

Spring AI 的价值

Spring AI 可统一:

  • 模型调用

  • Prompt 构造

  • Embedding

  • 向量检索

  • 工具调用接入


10. 如何避免 AI 幻觉和医疗风险?

业务场景

用户问的问题可能涉及:

  • 药品服用

  • 病情判断

  • 治疗建议

这些属于高风险场景,不能让模型“自由发挥”。

风险控制策略

1)角色定位

AI 不是医生,而是信息辅助助手

2)只基于知识库回答

知识库没有的信息:

  • 明确说不知道

  • 转人工

  • 引导咨询医生

3)来源引用

回答附带:

  • 文档来源

  • 相关片段

  • 更新时间

4)高风险问题拦截

例如:

  • 剂量建议

  • 处方推荐

  • 诊断结论

  • 生死攸关判断

这些问题必须:

  • 转人工

  • 转医生

  • 或只返回标准免责声明

5)Prompt 约束

提示模型:

  • 不允许编造

  • 没依据就拒答

  • 只能使用检索内容

6)审核规则

用规则引擎、关键词、分类模型做二次风控。


11. Agent、工具执行框架、MCP、Agentic RAG 怎么理解?

业务场景

用户说:“帮我查体检报告、预约下周复诊、顺便提醒我今晚吃药。”

这已经不是单一问答,而是多步骤任务执行

工具执行框架怎么设计?

工具标准化

定义统一工具接口:

  • queryReport

  • queryDoctorSchedule

  • createAppointment

  • sendMedicationReminder

AI 的职责

AI 负责:

  • 理解用户意图

  • 决定下一步调用什么工具

  • 组织结果反馈

后端服务负责:

  • 权限校验

  • 参数校验

  • 真正执行业务操作

  • 审计留痕

为什么不能让模型直接连数据库?

因为风险太高:

  • 权限不可控

  • 参数可能错

  • 难审计

  • 难回滚

MCP 的意义

MCP 可以理解为模型与外部工具/上下文交互的一种标准化协议思路,让不同工具能力更容易被模型发现和调用。

Agentic RAG 和普通 RAG 区别

普通 RAG

一次检索,拿结果,生成回答。

Agentic RAG

模型会自己规划:

  • 先查哪个知识库

  • 不够再查哪个系统

  • 是否需要多跳检索

  • 是否调用额外工具

  • 是否先总结再回答

它更像:
“检索 + 推理 + 工具协作”


12. 如何保证持续交付?

测试分层

单元测试
  • JUnit 5

  • Mockito

  • AssertJ

适合测试:

  • Service 逻辑

  • 工具类

  • 参数校验

  • 规则判断

遗留代码测试
  • TestNG、PowerMock 可能在老项目里会遇到

  • 新项目尽量少依赖 PowerMock

集成测试
  • Spring Boot Test

  • Testcontainers(如果项目里使用)

UI 自动化
  • Selenium

验收测试
  • Cucumber,适合业务语言描述流程

构建与发布

  • Maven / Gradle 构建

  • Jenkins / GitLab CI / GitHub Actions 执行流水线

  • Docker 打包镜像

  • Kubernetes 部署

数据库变更管理

  • Flyway

  • Liquibase

避免手工改库导致环境不一致。

发布策略

  • 滚动发布

  • 灰度发布

  • 蓝绿发布

上线后保障

  • Prometheus 监控

  • Grafana 大盘

  • ELK 日志

  • Jaeger/Zipkin 链路追踪

发现异常立即:

  • 降级

  • 限流

  • 回滚


这场面试真正想考什么?

表面上,面试官问的是:

  • Spring Boot

  • Redis

  • Kafka

  • Spring Security

  • Spring AI

  • Kubernetes

实际上,他在看四件事:

1. 你是否理解业务

不是会背八股,而是知道“挂号、支付、病历、客服”分别怕什么问题。

2. 你是否有系统设计能力

不是会写接口,而是能把缓存、消息、数据库、微服务、安全、监控串起来。

3. 你是否知道边界

比如 AI 不是万能的,医疗建议不能乱答,缓存不能替代数据库,重试不能无限开。

4. 你是否有工程意识

测试、发布、监控、回滚、审计、幂等、限流,这些才是大厂真正关心的稳定性能力。


结尾小结

王小二不是完全不会。
他的问题在于:简单问题答得流畅,复杂问题一深入就开始“这个要看场景”“这个一般都能做”
而真正的大厂面试,希望听到的是:

  • 为什么这样设计

  • 不这样设计会出什么问题

  • 高并发下怎么兜底

  • 高风险场景怎么控边界

  • 出故障后怎么排查

所以,小白如果想从这篇文章学东西,可以记住一条主线:

先学会把一个 Java 业务系统做出来,再学会把它做稳,最后再学会把 AI 安全地接进去。


文章标签
Java,SpringBoot,SpringCloud,Redis,Kafka,MyBatis,JPA,SpringSecurity,JWT,SpringAI,RAG,Agent,Kubernetes,Prometheus,Grafana,Micrometer,JUnit5,OpenFeign,Resilience4j,Elasticsearch

文章简述(100字)
本文以互联网医疗+AIGC平台面试为主线,通过严肃面试官与搞笑程序员王小二的三轮对话,串联 Java 17、Spring Boot、微服务、缓存、消息队列、安全、监控、Spring AI、RAG、Agent、CI/CD 等核心知识,并在文末给出详细答案解析,帮助初学者理解真实业务场景下的技术设计思路。

文章标题
《Java 17、Spring Boot、Spring Cloud、Redis、Kafka、Spring AI 与 Kubernetes:互联网医疗+AIGC平台的大厂面试实录》

文章内容

凌晨十点,某互联网大厂会议室。
玻璃门一关,气压立刻低了三度。

面试官周工,表情严肃,像是连 NullPointerException 都不敢在他面前随便抛。
求职者王小二,简历写着“精通 Java 全家桶,熟悉 AI Agent、RAG、微服务、云原生、大数据生态”。
他坐下时很自信,坐稳后又有点像刚被 GC 标记过。

这次面试的业务背景,是一套互联网医疗健康管理+AIGC智能客服平台
平台包含在线问诊、健康档案、药品商城、医生排班、智能客服、企业知识库问答、订单支付、风控审计等模块,技术栈以 Java 为主,运行在 Kubernetes 上。


第一轮:从单体到微服务,先看你能不能把系统搭起来

问题1:

面试官:
假设我们要做一个互联网医疗平台,包含用户、医生、挂号、订单、支付、病历、智能客服几个核心模块。你会怎么用 Java 技术栈做第一版架构?选型也说一下。

王小二:
这个……我会用 Java 17,因为新一点,看起来比较高级。然后框架嘛,肯定 Spring Boot,启动快,面试也爱听。
服务拆分的话,就拆成用户服务、医生服务、订单服务、支付服务、病历服务、客服服务。
数据库用 MySQL,ORM 我一般 MyBatis 和 JPA 都能写,看团队风格。
服务之间可以用 OpenFeign 调,注册发现可以用 Eureka 或 Consul。
缓存上 Redis,消息队列上 Kafka 或 RabbitMQ。
部署的话 Docker 加 Kubernetes,监控就 Prometheus 和 Grafana。

面试官:
回答得还算完整,至少不是“一个 Controller 走天下”。
那你继续说,为什么第一版不是直接上 WebFlux 和 R2DBC 全异步?

王小二:
因为……因为先活下来比较重要。大部分医疗后台还是 CRUD 比较多,Spring MVC 配合 JPA、MyBatis 更稳。WebFlux 更适合高并发 I/O 场景,比如流式推送、AI 对话。

面试官:
不错,这句说到点子上了。


问题2:

面试官:
挂号服务里,医生排班和患者预约很容易出现并发冲突。比如同一个号源最后一个名额,被两个人同时抢到。你怎么处理?

王小二:
这个我会先想到数据库层。
比如库存字段 remaining_count,更新时带条件:where remaining_count > 0,更新成功才算抢到。
也可以用乐观锁版本号,比如 JPA 的 @Version
如果并发更大,就加 Redis 做预扣减,再异步落库。
实在不放心,还可以把预约请求丢 Kafka,排队串行消费。

面试官:
行,知道“别让两个病人拿同一个号”这件事要靠数据一致性,不靠祈祷。
那 Redis 预扣减失败和数据库写入失败的补偿,你考虑了吗?

王小二:
这个……一般会有补偿任务。
或者用消息事务……或者本地消息表……
大概就是,不能让 Redis 和数据库各过各的。

面试官:
嗯,后半句开始有点飘了,不过方向没错。


问题3:

面试官:
你说说 MyBatis、JPA、Hibernate 在这个场景里怎么选。别背定义,说实际业务。

王小二:
如果是用户、医生、病历这种对象关系比较明确、关联也比较多的模块,我会偏 JPA/Hibernate,开发快,适合后台管理系统。
如果是订单、报表、复杂查询、分页筛选、多表统计,我更倾向 MyBatis,SQL 可控。
有些简单服务也可以用 Spring Data JDBC,模型更轻。
连接池用 HikariCP,性能和稳定性都更主流。
数据库版本管理可以上 Flyway 或 Liquibase。

面试官:
不错,这个回答挺像干过活。
那病历查询为什么不全上 Elasticsearch?

王小二:
因为 Elasticsearch 适合检索,不适合做强事务主存储。
病历原始数据还是落 MySQL,检索索引异步同步到 Elasticsearch 比较稳。

面试官:
很好。


问题4:

面试官:
如果挂号成功后,需要发送短信、站内信、医生工作台提醒、患者 App 消息,你会怎么设计消息链路?

王小二:
我会把“挂号成功”作为领域事件发出去。
订单服务提交成功后,发 Kafka 消息,多个消费者分别处理短信、App Push、医生提醒。
如果业务需要更强路由能力,也可以用 RabbitMQ。
消息体可以用 Jackson 序列化 JSON;如果追求高性能和跨语言,可以用 Protobuf 或 Avro。
为了避免重复消费,要做幂等,比如消息表、业务唯一键、去重 Redis Key。

面试官:
可以,至少你知道 MQ 不是“发了就一定成”。
第一轮到这里。


第二轮:系统能跑起来还不够,你得让它撑住、守住、看得见

问题5:

面试官:
现在平台用户量起来了,问诊高峰期每秒几千请求。你怎么做缓存设计?说说 Redis、Caffeine、Spring Cache 分别怎么用。

王小二:
Redis 适合分布式缓存,比如医生详情、科室列表、号源快照。
Caffeine 适合单机热点缓存,比如本机短期高频字典数据。
Spring Cache 可以统一缓存注解,底层接 Redis 或 Caffeine。
缓存要注意穿透、击穿、雪崩。
穿透可以布隆过滤器或缓存空值;击穿可以互斥锁或热点永不过期加异步刷新;雪崩要加过期时间随机化和多级缓存。

面试官:
不错,这段答得挺顺。
那患者健康档案能不能直接全部丢 Redis?

王小二:
不能。这个数据敏感、体量大、更新也复杂。Redis 更适合热点读,不适合作为长期主存。
核心还是数据库,缓存只是加速层。

面试官:
嗯,没把 Redis 当万能冰箱,这点很好。


问题6:

面试官:
支付和医疗数据都很敏感。你说说 Spring Security、JWT、OAuth2、Keycloak 在这个系统里怎么落地。

王小二:
用户登录可以用 Spring Security 做认证鉴权。
移动端和小程序登录后签发 JWT,网关校验令牌。
如果平台有医生端、患者端、运营后台、第三方药企后台,多租户和统一身份管理可以引入 OAuth2 或 Keycloak。
权限模型上可以做 RBAC,接口按角色、资源、数据范围控制。
敏感字段比如身份证号、手机号可以加密存储,必要时用 Bouncy Castle 做加解密能力支持。
此外,操作病历、处方这些高风险接口,要做审计日志。

面试官:
回答合格。
那 JWT 一旦签发,用户被封禁了怎么办?

王小二:
这个……可以缩短 JWT 有效期,再配合 Redis 黑名单。
或者做双 Token 机制,Access Token 短效,Refresh Token 控制续签。

面试官:
行,比“让用户重新登录试试”强。


问题7:

面试官:
微服务之间经常有超时、雪崩。你说说 OpenFeign、Resilience4j、网关限流、熔断降级怎么配合。

王小二:
服务调用可以用 OpenFeign。
如果医生服务慢了,订单服务直接同步等,就容易把线程池拖死。
所以要做超时控制、重试、舱壁隔离、熔断和限流,Resilience4j 很适合。
比如查询医生画像失败,就降级返回基础信息;推荐标签失败,不影响挂号主链路。
API 网关层可以做统一限流和鉴权,防止恶意刷接口。
下游不可用时,可以快速失败,不要层层等待。

面试官:
不错。
那重试是不是越多越好?

王小二:
不是。重试太多可能把本来就快挂的服务彻底按死。
重试只适合幂等读操作或少量可控场景,支付扣款这类要非常谨慎。

面试官:
很好,这句靠谱。


问题8:

面试官:
线上出了问题,你怎么排查?把日志、指标、链路追踪说完整。

王小二:
日志方面我会统一 SLF4J 门面,底层用 Logback 或 Log4j2。
把 traceId、userId、orderId 放到 MDC 里,便于串联日志。
指标方面用 Micrometer 暴露 JVM、线程池、HTTP、数据库连接池指标给 Prometheus,再用 Grafana 做看板。
链路追踪可以接 Jaeger 或 Zipkin,看一次请求经过了哪些服务。
日志聚合可以上 ELK Stack。
如果发现接口 RT 飙升,要看是 CPU 高、GC 频繁、数据库慢查询、MQ 堆积还是外部依赖超时。

面试官:
不错,排障思路比很多只会说“重启试试”的强。
第二轮结束。


第三轮:现在加 AI,别把系统做成“智能胡说平台”

问题9:

面试官:
公司现在要做 AI 智能客服,支持医保政策问答、医院流程问答、药品说明检索。你会怎么用 Spring AI 和 RAG 落地?

王小二:
这个我熟,我简历上写了三遍。
大概流程是:先把医院制度、药品说明书、医保文档、常见问答导入知识库;然后切片;然后向量化;再存到向量数据库,比如 Milvus、Chroma 或 Redis Vector。
用户提问后,先做语义检索,拿到相关片段,再拼进 Prompt,最后交给大模型回答。
Spring AI 可以帮我们统一模型调用、Embedding、向量检索这些流程。
这样比模型“裸答”更靠谱,能减少幻觉。

面试官:
嗯,这个回答不错。
那你继续说,文档切片怎么做?是按 1000 字一刀切?

王小二:
这个……也不一定。
有时候按标题层级切,有时候按段落切。
反正就是,切得太大检索不准,切得太小上下文不够。
要根据业务调。

面试官:
你这句虽然有点像废话,但确实是对的。


问题10:

面试官:
如果用户问:“我高血压还能不能吃这个药?”你觉得企业文档问答和医疗建议之间的边界怎么控制?怎么避免 AI 幻觉带来风险?

王小二:
这个不能让 AI 直接当医生。
可以把它定位成“信息辅助”,比如引用药品说明书、医院规范、挂号流程,而不是直接给诊断结论。
回答里要带来源片段、免责声明。
高风险问题可以触发转人工或转医生。
还可以做提示词约束,不在知识库里的问题不要乱答。
另外把审核规则加上,比如命中禁答词、处方建议、高风险病症,就不让模型自由发挥。

面试官:
可以,风险意识合格。
那如果用户追问十轮,系统怎么保留会话上下文?

王小二:
可以做聊天会话内存。
短期上下文存在 Redis,长期摘要落库。
也可以把历史对话摘要后再拼接到 Prompt 里,避免 Token 爆炸。

面试官:
嗯,还行。


问题11:

面试官:
如果我们要做 Agent,让 AI 帮用户完成“查报告、预约复诊、推送用药提醒”这种复杂工作流,你怎么设计工具执行框架?

王小二:
我会把 AI 当成决策层,不让它直接乱调内部系统。
先定义标准化工具接口,比如查询报告、查询排班、创建预约、发送提醒。
工具调用要有权限校验、参数校验、审计日志。
模型只负责决定“该调哪个工具”,真正执行还是后端服务做。
如果是多步骤流程,可以做状态机或者编排流。
如果再高级一点,还可以做 MCP 或类似协议,把工具能力标准化接入。

面试官:
前面说得不错。
那 Agentic RAG 和普通 RAG 的区别呢?

王小二:
这个……普通 RAG 就是检索再回答。
Agentic RAG 可能就是……更聪明一点?
会自己规划、多跳检索、可能还会调用工具。
大概是从“查一遍”升级成“边查边想边干”。

面试官:
你最后这句,土是土了点,但意思差不多。


问题12:

面试官:
最后一个问题。你怎么保证这套系统能持续交付?从测试、CI/CD 到上线发布说一下。

王小二:
单元测试用 JUnit 5、Mockito、AssertJ。
历史遗留不好 mock 的代码,可能会碰到 PowerMock,但新项目尽量少用。
接口测试可以用 Spring Boot Test,端到端页面流程可以用 Selenium,业务验收可以用 Cucumber。
构建用 Maven 或 Gradle。
CI/CD 用 Jenkins、GitLab CI 或 GitHub Actions。
打包 Docker 镜像,发到 Kubernetes。
数据库变更用 Flyway 或 Liquibase 管理。
发布可以做灰度、蓝绿或滚动更新。
上线后通过 Prometheus、Grafana、ELK 看指标和日志,不行就回滚。

面试官:
整体还行。
你会的东西不少,懂的深浅嘛……有些地方像温水泡枸杞,颜色有了,药劲差点。
今天先到这里,回去等通知吧。

王小二:
好的老师。我这边如果有结果,是您通知我,还是 Kafka 异步通知我?

面试官:
……门在你右手边。


面试题答案精讲

下面把上面 12 个问题的标准答案,用小白也能看懂的方式详细展开。


1. 互联网医疗平台第一版架构怎么设计?

业务场景

一个互联网医疗平台,至少会有这些核心能力:
用户注册登录、医生信息展示、排班挂号、订单支付、病历查看、消息通知、智能客服。

推荐技术方案

  • Java 版本:优先 Java 17,兼顾性能、语法增强、LTS 支持

  • 基础框架:Spring Boot

  • Web 层:大多数后台接口用 Spring MVC

  • AI 对话或流式返回:可局部使用 Spring WebFlux

  • 服务治理:Spring Cloud、OpenFeign、Consul/Eureka

  • 数据库:MySQL/PostgreSQL

  • ORM:JPA/Hibernate 处理标准对象模型,MyBatis 处理复杂 SQL

  • 缓存:Redis

  • 消息队列:Kafka 或 RabbitMQ

  • 部署:Docker + Kubernetes

  • 监控:Micrometer + Prometheus + Grafana

  • 日志:SLF4J + Logback/Log4j2

  • 文档:Swagger/OpenAPI

初期为什么不建议一上来全异步?

因为大部分业务是标准事务型接口,例如注册、挂号、支付订单查询,这类场景:

  • 逻辑清晰

  • 阻塞式开发更直接

  • 团队更容易维护

  • 排错更简单

WebFlux/R2DBC 更适合

  • 流式 AI 对话

  • 长连接消息推送

  • 高并发 I/O 聚合场景

所以第一版系统通常是:
核心交易链路走 Spring MVC,局部高并发/流式模块再引入 WebFlux。


2. 医生号源并发抢占怎么处理?

业务场景

医生某时间段只剩 1 个号源,两个用户同时点击预约。

风险

如果处理不好,就会出现:

  • 超卖

  • 重复挂号

  • 数据不一致

常见方案

方案一:数据库条件更新
update doctor_schedule
set remaining_count = remaining_count - 1
where schedule_id = ? and remaining_count > 0;

如果更新行数为 1,说明抢号成功;为 0,说明没抢到。

优点:简单可靠
缺点:高并发下数据库压力大

方案二:乐观锁

JPA/Hibernate 可用 @Version 字段控制版本号。

适合:

  • 冲突不是特别极端

  • 需要在应用层处理重试逻辑

方案三:Redis 预扣减 + 异步落库

流程:

  1. Redis 先扣号源

  2. 扣减成功后发 MQ

  3. 消费者写数据库

  4. 失败时做补偿

适合高并发秒杀式场景。

补偿机制

如果 Redis 扣了,但数据库失败,需要:

  • 本地消息表

  • 死信队列

  • 重试任务

  • 对账任务

核心原则

强一致核心数据不能只信缓存,一定要以数据库或可靠事务机制兜底。


3. MyBatis、JPA、Hibernate、Spring Data JDBC 怎么选?

JPA/Hibernate 适合什么?

适合:

  • 用户、医生、科室、权限等标准领域模型

  • 对象关系清晰

  • 开发效率优先

优点:

  • 开发快

  • 统一实体管理

  • 支持懒加载、级联、乐观锁

缺点:

  • 复杂 SQL 可控性不如 MyBatis

  • 不熟悉容易踩 N+1 查询坑

MyBatis 适合什么?

适合:

  • 复杂列表查询

  • 多表 join

  • 统计报表

  • 动态 SQL

  • 性能调优要求高的模块

优点:

  • SQL 完全可控

  • 易做复杂查询优化

缺点:

  • 模板代码较多

  • 纯 CRUD 时开发效率不如 JPA

Spring Data JDBC 适合什么?

适合:

  • 模型简单

  • 不需要复杂对象关联

  • 希望比 JPA 更轻量

实战建议

一个大型项目里,JPA 和 MyBatis 混用非常常见:

  • 核心后台管理模型:JPA/Hibernate

  • 复杂查询与报表:MyBatis

  • 连接池:HikariCP

  • 数据库变更:Flyway/Liquibase


4. 挂号成功后的通知链路怎么设计?

业务场景

挂号成功后,要同时触发:

  • 短信通知

  • App 推送

  • 医生工作台待办

  • 站内信

  • 后续统计埋点

为什么不用同步串行调用?

如果订单服务在一个请求里同步调完所有通知服务,会导致:

  • 耦合严重

  • 响应变慢

  • 某个通知服务挂了影响主流程

正确做法:事件驱动

订单服务完成后发一个事件,比如:
AppointmentCreatedEvent

由多个消费者分别处理:

  • 短信服务

  • Push 服务

  • 医生待办服务

  • BI 埋点服务

Kafka vs RabbitMQ

Kafka

适合:

  • 吞吐高

  • 日志型事件流

  • 多消费者订阅

  • 数据回放

RabbitMQ

适合:

  • 路由灵活

  • 延迟队列

  • 业务消息编排

幂等设计

MQ 至少一次投递时,要避免重复处理:

  • 消息唯一 ID

  • 数据库唯一约束

  • Redis 去重键

  • 消费记录表


5. Redis、Caffeine、Spring Cache 怎么组合用?

业务场景

热门医生详情页、科室列表、医院公告、药品基础信息访问量极高。

三级思路

1)Caffeine:本地缓存

适合单机热点数据:

  • 科室字典

  • 配置项

  • 高频静态数据

优点:

  • 速度极快

  • 不走网络

缺点:

  • 多实例之间不共享

2)Redis:分布式缓存

适合多个服务节点共享的数据:

  • 医生详情

  • 号源快照

  • 会话信息

  • 黑名单 Token

3)Spring Cache:统一抽象

通过注解:

  • @Cacheable

  • @CachePut

  • @CacheEvict

底层可接 Redis 或 Caffeine。

三大缓存问题

缓存穿透

查询不存在的数据,导致请求每次打数据库。
方案:

  • 缓存空值

  • 布隆过滤器

缓存击穿

热点 Key 过期瞬间,大量请求打数据库。
方案:

  • 互斥锁

  • 热点永不过期

  • 后台刷新

缓存雪崩

大量 Key 同时过期。
方案:

  • 过期时间加随机值

  • 多级缓存

  • 限流降级


6. Spring Security、JWT、OAuth2、Keycloak 怎么落地?

业务场景

平台有:

  • 患者端 App

  • 医生端工作台

  • 运营后台

  • 第三方合作机构接口

认证与鉴权分层

Spring Security

负责基础认证鉴权框架:

  • 登录

  • 权限拦截

  • 过滤器链

  • 方法级权限控制

JWT

适合无状态认证:

  • 用户登录后签发 Token

  • 网关或服务端校验

优点:

  • 不用每次查 Session

  • 适合分布式系统

缺点:

  • 签发后难立刻失效

OAuth2

适合:

  • 第三方授权

  • 统一身份平台

  • 多客户端接入

Keycloak

适合:

  • 企业统一身份认证

  • 单点登录

  • 多租户

  • 统一权限中心

安全增强

  • Access Token 短期有效

  • Refresh Token 控制续签

  • Redis 黑名单处理封禁/登出

  • 敏感字段脱敏/加密

  • 审计日志记录谁看了谁的病历


7. OpenFeign、Resilience4j、限流熔断怎么配合?

业务场景

订单服务要调用:

  • 用户服务

  • 医生服务

  • 优惠券服务

  • 支付服务

任何一个慢了,整条链路都可能被拖垮。

OpenFeign

用于服务间声明式调用,代码简洁。

Resilience4j 能做什么?

  • 超时控制

  • 重试

  • 熔断

  • 限流

  • 舱壁隔离

典型策略

超时

给每个下游调用设最大等待时间,避免线程长时间阻塞。

熔断

如果某服务持续失败,暂时不要继续打它,先快速失败。

降级

比如推荐服务挂了,只返回基础信息,不影响挂号主链路。

限流

避免某接口被刷爆,保护系统。

舱壁隔离

不同依赖使用不同线程池/信号量,防止一个服务故障拖死全系统。

注意

重试不是越多越好。
高峰期盲目重试,只会把故障扩大。


8. 线上故障怎么排查?

三大可观测性

1)日志
  • 门面:SLF4J

  • 实现:Logback / Log4j2

  • 关键字段:traceId、spanId、userId、orderId

为什么要 MDC?

MDC 能把同一请求的关键字段自动打到所有日志里,方便串联。

2)指标

Micrometer 暴露:

  • JVM 内存

  • GC 次数与耗时

  • 线程池状态

  • HTTP RT/QPS

  • 数据库连接池

  • MQ 消费积压

Prometheus 负责采集,Grafana 负责展示。

3)链路追踪

Jaeger / Zipkin 追踪一次请求流经了哪些服务。

常见排查路径

接口慢时按顺序看:

  1. 网关 RT 是否异常

  2. 某个服务 CPU 是否高

  3. JVM 是否频繁 Full GC

  4. 数据库是否有慢 SQL

  5. MQ 是否堆积

  6. 外部依赖是否超时

  7. 是否有缓存失效


9. Spring AI + RAG 怎么做企业文档问答?

业务场景

智能客服回答:

  • 医保报销流程

  • 住院须知

  • 医院制度

  • 药品说明书

  • 术前术后注意事项

RAG 流程

第一步:文档加载

来源可能包括:

  • PDF

  • Word

  • Excel

  • 网页

  • 知识库文章

第二步:文档切片

把长文档拆成适合检索的小段。

切片原则:

  • 太大:检索不准

  • 太小:上下文不完整

常见方式:

  • 按标题层级切

  • 按自然段切

  • 固定长度 + 重叠窗口

第三步:Embedding 向量化

把文本转成向量表示。
可使用:

  • OpenAI Embedding

  • Ollama 本地模型

  • 其他兼容模型

第四步:写入向量数据库

常见选择:

  • Milvus

  • Chroma

  • Redis Vector

第五步:检索增强生成

用户提问后:

  1. 把问题向量化

  2. 查最相关知识片段

  3. 拼到 Prompt

  4. 再交给模型生成答案

Spring AI 的价值

Spring AI 可统一:

  • 模型调用

  • Prompt 构造

  • Embedding

  • 向量检索

  • 工具调用接入


10. 如何避免 AI 幻觉和医疗风险?

业务场景

用户问的问题可能涉及:

  • 药品服用

  • 病情判断

  • 治疗建议

这些属于高风险场景,不能让模型“自由发挥”。

风险控制策略

1)角色定位

AI 不是医生,而是信息辅助助手

2)只基于知识库回答

知识库没有的信息:

  • 明确说不知道

  • 转人工

  • 引导咨询医生

3)来源引用

回答附带:

  • 文档来源

  • 相关片段

  • 更新时间

4)高风险问题拦截

例如:

  • 剂量建议

  • 处方推荐

  • 诊断结论

  • 生死攸关判断

这些问题必须:

  • 转人工

  • 转医生

  • 或只返回标准免责声明

5)Prompt 约束

提示模型:

  • 不允许编造

  • 没依据就拒答

  • 只能使用检索内容

6)审核规则

用规则引擎、关键词、分类模型做二次风控。


11. Agent、工具执行框架、MCP、Agentic RAG 怎么理解?

业务场景

用户说:“帮我查体检报告、预约下周复诊、顺便提醒我今晚吃药。”

这已经不是单一问答,而是多步骤任务执行

工具执行框架怎么设计?

工具标准化

定义统一工具接口:

  • queryReport

  • queryDoctorSchedule

  • createAppointment

  • sendMedicationReminder

AI 的职责

AI 负责:

  • 理解用户意图

  • 决定下一步调用什么工具

  • 组织结果反馈

后端服务负责:

  • 权限校验

  • 参数校验

  • 真正执行业务操作

  • 审计留痕

为什么不能让模型直接连数据库?

因为风险太高:

  • 权限不可控

  • 参数可能错

  • 难审计

  • 难回滚

MCP 的意义

MCP 可以理解为模型与外部工具/上下文交互的一种标准化协议思路,让不同工具能力更容易被模型发现和调用。

Agentic RAG 和普通 RAG 区别

普通 RAG

一次检索,拿结果,生成回答。

Agentic RAG

模型会自己规划:

  • 先查哪个知识库

  • 不够再查哪个系统

  • 是否需要多跳检索

  • 是否调用额外工具

  • 是否先总结再回答

它更像:
“检索 + 推理 + 工具协作”


12. 如何保证持续交付?

测试分层

单元测试
  • JUnit 5

  • Mockito

  • AssertJ

适合测试:

  • Service 逻辑

  • 工具类

  • 参数校验

  • 规则判断

遗留代码测试
  • TestNG、PowerMock 可能在老项目里会遇到

  • 新项目尽量少依赖 PowerMock

集成测试
  • Spring Boot Test

  • Testcontainers(如果项目里使用)

UI 自动化
  • Selenium

验收测试
  • Cucumber,适合业务语言描述流程

构建与发布

  • Maven / Gradle 构建

  • Jenkins / GitLab CI / GitHub Actions 执行流水线

  • Docker 打包镜像

  • Kubernetes 部署

数据库变更管理

  • Flyway

  • Liquibase

避免手工改库导致环境不一致。

发布策略

  • 滚动发布

  • 灰度发布

  • 蓝绿发布

上线后保障

  • Prometheus 监控

  • Grafana 大盘

  • ELK 日志

  • Jaeger/Zipkin 链路追踪

发现异常立即:

  • 降级

  • 限流

  • 回滚


这场面试真正想考什么?

表面上,面试官问的是:

  • Spring Boot

  • Redis

  • Kafka

  • Spring Security

  • Spring AI

  • Kubernetes

实际上,他在看四件事:

1. 你是否理解业务

不是会背八股,而是知道“挂号、支付、病历、客服”分别怕什么问题。

2. 你是否有系统设计能力

不是会写接口,而是能把缓存、消息、数据库、微服务、安全、监控串起来。

3. 你是否知道边界

比如 AI 不是万能的,医疗建议不能乱答,缓存不能替代数据库,重试不能无限开。

4. 你是否有工程意识

测试、发布、监控、回滚、审计、幂等、限流,这些才是大厂真正关心的稳定性能力。


结尾小结

王小二不是完全不会。
他的问题在于:简单问题答得流畅,复杂问题一深入就开始“这个要看场景”“这个一般都能做”
而真正的大厂面试,希望听到的是:

  • 为什么这样设计

  • 不这样设计会出什么问题

  • 高并发下怎么兜底

  • 高风险场景怎么控边界

  • 出故障后怎么排查

所以,小白如果想从这篇文章学东西,可以记住一条主线:

先学会把一个 Java 业务系统做出来,再学会把它做稳,最后再学会把 AI 安全地接进去。


文章标签
Java,SpringBoot,SpringCloud,Redis,Kafka,MyBatis,JPA,SpringSecurity,JWT,SpringAI,RAG,Agent,Kubernetes,Prometheus,Grafana,Micrometer,JUnit5,OpenFeign,Resilience4j,Elasticsearch

文章简述(100字)
本文以互联网医疗+AIGC平台面试为主线,通过严肃面试官与搞笑程序员王小二的三轮对话,串联 Java 17、Spring Boot、微服务、缓存、消息队列、安全、监控、Spring AI、RAG、Agent、CI/CD 等核心知识,并在文末给出详细答案解析,帮助初学者理解真实业务场景下的技术设计思路。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐