Java 求职面试实录:Spring Boot + Kafka + Redis + Spring Security 的互联网医疗场景攻防
(以下为富文本正文)
面试场景
今天的面试场景设定在一家互联网大厂的互联网医疗业务线,核心是“问诊预约 + 在线支付 + 检查报告回传 + 消息通知 + 风控审计”。面试官严肃克制,候选人是外号“燕双非”的水货程序员,平时嘴上很硬,关键问题一深就开始含糊其辞。
第一轮:系统架构与基础能力
面试官:先说说,如果你负责这个互联网医疗预约系统,你会怎么拆分服务?为什么不用一个大而全的单体?
燕双非:我会拆成用户服务、挂号服务、支付服务、消息通知服务、报告服务。单体嘛……也不是不行,就是后面人多了容易改着改着就炸了。拆服务之后,大家各做各的,互不打扰。
面试官:思路还可以。那你会优先选 Spring Boot 还是传统 Jakarta EE?为什么?
燕双非:大多数情况下我会选 Spring Boot,启动快、约定优于配置,接第三方组件也方便。Jakarta EE 也能做,但……我一般先看团队栈,能少配点 XML 就少配点。
面试官:那你在服务启动时,怎么做配置隔离和环境切换?
燕双非:我会用 profile,区分 dev、test、prod,再把数据库、MQ、缓存这些配置分开。这样在医院测试环境不会一不小心连到生产库。
面试官:嗯,这个很务实。最后一个问题,你知道 JVM 里线上系统最常见的卡顿来源有哪些吗?
燕双非:额,内存泄漏、频繁 GC、线程池打满、还有……日志打太多也会慢吧。
面试官:可以,至少方向没跑偏。
第二轮:核心链路与中间件设计
面试官:现在用户下单预约号源,支付成功后要发 Kafka 通知,并更新 Redis 缓存。你怎么保证支付幂等?
燕双非:我会加一个业务唯一单号,比如 orderId,支付回调时先查状态,如果已经支付过就直接返回成功。再配合数据库唯一约束,避免重复更新。
面试官:不错。那 Kafka 消息重复投递你怎么处理?
燕双非:消费者那边也做幂等,比如记录消息 ID,处理前先判断是否已消费。说白了就是,别让同一条通知短信发两遍,不然用户会以为医院很激动。
面试官:那 Redis 你会拿来做什么?
燕双非:号源库存、医生排班、热门科室列表这些都可以缓存。还可以给用户预约状态做短期缓存,减少数据库压力。
面试官:缓存穿透、击穿、雪崩你怎么防?
燕双非:穿透我会做空值缓存或者布隆过滤器;击穿我会加互斥锁;雪崩我会给过期时间加随机值,别让一堆缓存同一秒过期。
面试官:好。再说说 Spring Security 在这个系统里怎么落地?
燕双非:登录后发 JWT,接口侧做 token 解析和权限校验。医生、患者、管理员不同角色访问不同资源,比如医生能看报告,患者只能看自己的。
面试官:那如果要支持单点登录和第三方医院对接呢?
燕双非:可以接 OAuth2 或 Keycloak 做统一认证,外部系统通过授权码或者 client credentials 方式接入。
面试官:行,这一轮比上一轮扎实。
第三轮:高并发、可观测性与 AI 场景
面试官:现在我们要加一个智能客服功能,支持病人用自然语言问“我该挂哪个科”。你会怎么设计?
燕双非:我会考虑 Spring AI 接一个大模型,然后做 RAG。先把医院科室说明、常见症状、就诊指南做文档加载和向量化,再存到向量数据库里,用户提问时先语义检索,再把相关内容喂给模型,减少胡说八道。
面试官:不错。那 Agent 和普通问答有什么区别?
燕双非:普通问答更像“你问我答”,Agent 会自己规划步骤,比如先判断是挂号还是咨询,再决定要不要调用工具、查库存、查医生排班、查订单状态。
面试官:如果客服机器人要调用内部接口,你如何设计工具调用?
燕双非:我会把工具能力标准化,比如查科室、查号源、查订单、发短信都封装成工具,统一输入输出协议。这样模型就能按步骤调用,不至于把接口参数拼得像一锅粥。
面试官:那怎么降低 AI 幻觉?
燕双非:一是尽量基于检索结果回答,二是给模型明确提示,不知道就说不知道,三是对关键结论做后置校验,比如挂号建议必须落到真实科室数据上。
面试官:最后一个问题,系统高峰期,比如周一早上抢号,怎么做监控和限流?
燕双非:我会用 Micrometer 接 Prometheus 和 Grafana 看 QPS、延迟、错误率;网关和接口层做限流;必要时加熔断降级,支付、消息、缓存都做好兜底。
面试官:整体不错,但有些点还可以再沉淀一下。今天先到这里,你回家等通知吧。
面试问题详细解答
1. 互联网医疗系统如何拆分服务
在互联网医疗场景中,用户链路通常包括注册登录、预约挂号、支付、问诊、检验检查、报告回传、消息通知与售后服务。将系统拆分为用户服务、挂号服务、支付服务、通知服务、报告服务等微服务,有助于解耦业务边界、独立扩容和按需迭代。Spring Boot 适合快速搭建服务骨架,配合 Spring Cloud 或 OpenFeign 做服务调用,能较快支撑业务落地。
2. Spring Boot、Jakarta EE 与 JVM 相关考虑
Spring Boot 更适合现代互联网业务,核心优势是自动配置、starter 机制、嵌入式容器和生态丰富。Jakarta EE 更偏传统企业级规范。JVM 层面需关注类加载、GC、线程池、内存泄漏、对象分配速率等问题,特别是在高并发预约场景里,频繁创建短生命周期对象和日志过量都可能放大 GC 压力。
3. 配置隔离与环境切换
通常使用 profile 或外部配置中心将 dev/test/prod 环境隔离,数据库、缓存、MQ、第三方接口地址都应区分。生产环境避免硬编码敏感信息,建议结合环境变量、配置中心和密钥管理方案统一治理。
4. 支付幂等与消息重复消费
支付幂等的本质是“同一业务请求执行多次,结果一致”。常见做法是使用业务单号、订单状态机、数据库唯一索引和乐观锁。对于 Kafka 重复消息,消费者端必须幂等,可通过消费日志表、消息唯一 ID、状态机去重等方式防止重复处理。
5. Redis 的应用与缓存问题治理
Redis 可用于号源库存、排班信息、热门科室、验证码、会话状态等场景。缓存穿透可用空值缓存、布隆过滤器;缓存击穿可用互斥锁、热点预热;缓存雪崩可通过随机过期时间、分批预热、多级缓存和限流兜底缓解。
6. Spring Security、JWT、OAuth2 与 Keycloak
在医疗系统中,需要区分患者、医生、管理员等不同角色。JWT 适合无状态鉴权,Spring Security 负责认证与授权,OAuth2 适合第三方接入和统一授权。Keycloak 可作为统一身份提供者,支持单点登录、角色管理和外部系统接入,适合大型医疗集团或多院区平台。
7. 智能客服与 Spring AI / RAG / Agent
智能客服不应直接让大模型“自由发挥”,而应采用 RAG:先将医院制度、科室信息、疾病科普、常见问题等文档加载、切分、向量化,再写入向量数据库(如 Milvus、Chroma 或 Redis 向量能力),通过语义检索找到相关内容后再交给模型生成答案。Agent 比普通问答更进一步,它可以根据目标自主规划步骤,并调用工具查询号源、订单、医生排班等业务数据,适用于复杂工作流和企业文档问答。
8. 降低 AI 幻觉
降低幻觉的关键是“让模型少编”。方法包括:尽量基于检索结果回答;在提示词中明确边界;对医疗等高风险场景加入规则校验;对输出进行后处理与审核;对无法确认的信息要求模型直接说“不确定”。
9. 高并发监控与限流
高峰期抢号会给系统带来巨大压力。可通过 Micrometer 统一采集指标,接入 Prometheus 和 Grafana 做可视化监控;借助日志平台与链路追踪工具排查瓶颈;通过网关限流、接口降级、熔断和异步化处理保护核心链路。若库存抢占强一致性要求较高,还应结合数据库事务、分布式锁或原子扣减方案。
10. 总结
这类面试的核心不是背概念,而是能否把技术与业务场景真正连起来:预约、支付、通知、风控、客服、监控,每一个环节都有对应的工程实践。面试中只要思路清晰、边界明确、能讲出为什么这么设计,通常就能给面试官留下不错印象。
感谢阅读,希望这篇文章能帮助到正在准备 Java 面试的你,祝大家都能拿到心仪的 offer!