SpringCloud微服务架构面试题库
生成时间: 2026-05-21 21:14
本轮 SpringCloud微服务架构面试题库(带答案)
【面试题】1. Nacos作为注册中心,如何实现服务的优雅上下线?
【标准答案】 优雅上线:服务启动后先完成预热(缓存加载、连接池初始化),再向Nacos注册,注册成功后等待一小段时间让网关和其他服务同步到实例信息,最后才开始接收流量。可以通过spring.cloud.nacos.discovery.enabled=true配合@PostConstruct做初始化。
优雅下线:先从Nacos注销(调用注销API或设置enabled=false),让Nacos通知其他服务剔除该实例,等待正在处理的请求完成(设置缓冲期比如30秒),再真正停止服务。Spring Cloud提供了preStop钩子,在K8s中可以用lifecycle.preStop配合sleep实现。
核心是保证流量不丢失、请求不中断,生产环境建议配合健康检查和就绪探针一起使用。
【面试题】2. Sentinel的熔断降级策略有哪些?分别适用于什么场景?
【标准答案】 三种核心策略:
- 慢调用比例:统计一段时间内响应时间超过阈值的请求比例,超过设定值触发熔断。适合对响应时间敏感的业务,比如支付、下单场景。
- 异常比例:统计异常数占请求总数的比例,超过阈值熔断。适合外部依赖不稳定的情况,比如第三方API调用。
- 异常数:统计指定时间内的异常数量,达到阈值直接熔断。适合绝对不允许失败的敏感操作。
熔断后进入半开状态会放一个请求探测,成功恢复、失败继续熔断。实际项目中通常配合限流规则使用,熔断是兜底策略,限流是主动防护。
【面试题】3. OpenFeign如何实现动态修改超时时间?生产环境如何配置?
【标准答案】 动态超时可以通过两种方式:
- 配置中心动态刷新:在Nacos配置中设置
feign.client.config.default.connectTimeout和readTimeout,配合@RefreshScope实现热更新。 - 自定义Feign.Builder:通过拦截器或自定义
Request.Options,在每次请求时从配置中心拉取最新超时配置。
生产配置建议:
- 全局默认超时:连接3秒,读超时5秒
- 核心服务单独配置:支付类接口可以短一些,报表导出类可以长一些
- 必须配置重试策略,避免网络抖动导致的失败
- 开启Feign日志级别
FULL便于排查问题 - 配合Sentinel实现超时后的降级处理
关键是不同服务不同接口要差异化配置,不能一刀切。
【面试题】4. Spring Cloud Gateway如何实现统一的JWT认证鉴权?
【标准答案】 实现方案:
- 网关统一认证:在Gateway中配置
AuthGlobalFilter,解析请求头中的JWT Token,验证签名和有效期,提取用户信息放入请求头传递给下游服务。 - 服务间信任:下游服务信任网关传递的用户信息,无需再次验证JWT,通过
AddRequestHeader传递X-User-Id等关键信息。
关键代码:
@Component
public class AuthGlobalFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getHeaders().getFirst("Authorization");
// JWT验证逻辑
Claims claims = JwtUtil.parseToken(token);
ServerHttpRequest request = exchange.getRequest().mutate()
.header("X-User-Id", claims.getSubject())
.build();
return chain.filter(exchange.mutate().request(request).build());
}
}安全要点:
- 网关只做Token解析验证,不做权限校验
- 权限校验在具体服务中通过AOP或拦截器实现
- 敏感接口额外验证请求签名
【面试题】5. Seata的AT模式和TCC模式有什么区别?分别适合什么业务场景?
【标准答案】 AT模式:
- 原理:一阶段提交直接成功,二阶段根据Undo Log回滚或删除日志
- 特点:无侵入,基于数据库本地事务,支持MySQL/Oracle/PostgreSQL
- 适用:并发不高、对一致性要求不严格的业务,如积分、优惠券
TCC模式:
- 原理:Try-Confirm-Cancel三个阶段,业务代码需实现三个接口
- 特点:侵入性强,但性能好、一致性强
- 适用:高并发、对一致性要求高的核心业务,如支付、库存扣减
选择建议:
- 优先选AT,开发成本低
- 涉及资金、库存等核心数据用TCC
- TCC要注意幂等设计、空回滚、悬挂问题
- 跨公司服务调用考虑Saga模式
AT模式本质是补偿事务,TCC是预留资源事务,生产环境需要根据业务复杂度和一致性要求做取舍。
【面试题】6. Redis分布式锁使用Redisson实现,如何保证锁的可靠性?
【标准答案】 Redisson锁的核心机制:
- 锁续期(Watch Dog):默认30秒过期,后台线程每10秒自动续期,防止业务没执行完锁就释放
- 可重入锁:基于Hash结构存储,同一线程可多次获取锁
- 等待队列:请求获取锁失败会进入等待队列,支持公平锁和非公平锁
可靠性保证:
RLock lock = redissonClient.getLock("order:123");
try {
// 尝试获取锁,最多等待5秒,锁30秒后自动释放
boolean acquired = lock.tryLock(5, 30, TimeUnit.SECONDS);
if (acquired) {
// 执行业务逻辑
}
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}生产注意:
- 开启Watch Dog防止锁提前过期
- finally中判断是否持有锁再释放
- 集群环境用RedLock保证高可用
- 锁粒度尽量小,避免大key
【面试题】7. 微服务架构下,如何实现配置的热更新而不重启服务?
【标准答案】 核心方案:
- Nacos Config动态刷新:使用
@RefreshScope注解配置类,Nacos配置变更后自动刷新Bean - 配置变更监听:通过
@NacosConfigListener监听配置变化,手动更新内存中的配置
实现方式:
@RefreshScope
@RestController
public class ConfigController {
@Value("${app.config.key}")
private String configValue;
@NacosConfigListener(dataId = "app.properties")
public void onConfigChange(String newConfig) {
// 配置变更回调
}
}注意事项:
@RefreshScope会重建Bean,有状态的服务要注意数据丢失- 数据库连接、线程池等初始化类配置无法热更新,需要重启
- 复杂配置建议用配置中心SDK的API手动刷新
- 开发环境可以关闭自动刷新,避免意外变更
配置热更新适合开关类、阈值类配置,核心配置变更还是建议重启。
【面试题】8. SkyWalking链路追踪对性能有什么影响?如何优化?
【标准答案】 性能影响:
- CPU开销:每个请求创建Span、传递Context,约占请求处理的2-5%CPU
- 内存开销:Span对象会占用堆内存,高并发时Full GC频繁
- 网络IO:Span数据异步上报到OAP,网络带宽消耗
优化方案:
- 采样策略:高并发服务设置1%-10%采样率,核心服务100%
- 异步上报:使用gRPC异步发送,避免阻塞业务线程
- Span精简:只追踪关键调用链,非核心操作跳过追踪
- 部署优化:OAP集群独立部署,ES分片扩容
配置示例:
agent.sample_n_per_3_secs: 3 # 每3秒采样3个请求
agent.span_limit: 200 # 单个Span最大标签数生产经验:QPS超过1万的服务必须降采样,否则链路追踪组件本身会成为瓶颈。
【面试题】9. Spring Cloud Stream如何保证消息的可靠性投递?
【标准答案】 可靠性三阶段:
- 生产端:开启事务消息或Confirm确认机制,消息持久化后再返回成功
- 消费端:手动ACK机制,业务处理成功后再确认,失败则重试或进入死信队列
- Broker端:配置消息持久化、多副本同步复制
实现代码:
@StreamListener(MySink.INPUT)
public void handleMessage(Message<String> message) {
try {
// 业务处理
process(message.getPayload());
// 手动确认
AckUtils.acknowledge(message);
} catch (Exception e) {
// 重试或进入死信队列
AckUtils.nack(message);
}
}配置要点:
- 消费组隔离:每个服务配置独立的group,避免消息竞争
- 重试策略:配置重试次数和间隔,避免无限重试
- 死信队列:重试失败的消息进入DLQ,人工处理
- 消息去重:使用业务唯一键配合Redis去重
生产环境必须配合监控告警,对积压和失败消息及时处理。
【面试题】10. Kubernetes环境下部署微服务,如何实现服务的灰度发布?
【标准答案】 灰度发布方案:
- Deployment版本控制:通过镜像Tag区分版本,部署新版本Deployment
- Service流量切分:通过label selector控制流量比例
- Ingress/Nginx路由:基于Header、Cookie、权重进行流量分流
具体实现:
# 新版本Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-v2
spec:
replicas: 2
selector:
matchLabels:
app: myapp
version: v2
---
# Service同时暴露两个版本
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
selector:
app: myapp # 同时匹配v1和v2
---
# Ingress基于权重分流
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10"灰度流程:
- 先部署新版本Pod,初始副本数为1
- 通过Ingress控制10%流量进入新版本
- 观察监控指标(错误率、延迟、资源使用)
- 逐步增加权重:10%→30%→50%→100%
- 确认稳定后下线旧版本
推荐使用Argo Rollouts或Flagger实现自动化灰度,配合Prometheus指标自动判断是否继续发布。
题目数量: 10题
知识点覆盖: 服务注册发现、熔断限流、服务调用、API网关、分布式事务、分布式锁、配置中心、链路追踪、消息队列、容器化部署