微服务组件篇(含业务问题)
大家好我是小明,今天学习微服务
文章目录
总体复习方案

1. Spring Cloud常见组件(最基础面试题)
- 注册中心/配置中心 Nacos
- 负载均衡 Ribon
- 服务调用 Feign
- 服务保护 sentinel
- 服务网关 Gateway
2. 注册中心
注册中心的主要作用是服务注册服务发现
常见的注册中心:eueka, nacos, zookeeper
服务注册: 微服务启动时,把自己的地址(IP + 端口)、服务名、版本等信息上报到注册中心,
服务发现: 消费方(调用方)从注册中心获取目标服务的地址列表,实现动态调用(不用硬编码地址);
服务监控: 注册中心会发心跳包验证服务是否健康
具体的流程,面试的时候说具体一点

比如说:负载均衡负载均衡算法选择一个实例(比如 localhost:8081)再通过远程调用对应的服务。

eueka和nacos区别
Nacos 与 eureka 的共同点(注册中心)
- 都支持服务注册和服务拉取
- 都支持服务提供者心跳方式做健康检测
Nacos 与 Eureka 的不同点
- Nacos 支持服务端主动检测提供者状态:临时实例采用心跳模式,非临时实例采用主动检测模式
- Nacos 支持服务列表变更的消息推送模式(push),服务列表更新更及时
- Nacos 还支持了配置中心,eureka 则只有注册中心,也是选择使用 nacos 的一个重要原因
3. 项目如何实现负载均衡(LoadBalancer)
如果你是使用Nacos的用户,它自定义了一个NacosLoadBalancer的负载均衡算法,也是其默认算法。
下面说的是
Spring Cloud LoadBalancer
LoadBalancer负载均衡的流程

LoadBalancer负载均衡策略有哪些(重点)
默认是轮询
- RoundRobinRule(轮询):简单轮询服务列表来选择服务器
- WeightedResponseTimeRule(随机):按照权重来选择服务器,响应时间越长,权重越小
- RandomRule(响应时间权重):随机选择一个可用的服务器
- ZoneAvoidanceRule(区域回避):多机房部署、需要减少跨区域延迟,优先选择性能最好的区域(故障率低、响应快)
LoadBalancer负载均衡自定义策略如何实现??
LoadBalancer 自定义策略的核心是实现 ReactorServiceInstanceLoadBalancer 接口,重写 choose() 方法 —— 这个方法的作用就是从服务实例列表中选一个实例。
4. 什么是服务雪崩怎么解决?
即:一个服务挂了 → 调用它的服务也跟着挂
解决方法:
服务熔断
熔断的作用: 当某个服务失败率过高时,自动 “断开” 调用,避免继续请求导致雪崩。

熔断有三个状态:
- 关闭(Closed):正常调用
- 打开(Open):失败率过高,直接熔断,不再请求
- 半开(Half-Open):尝试恢复,允许少量请求测试服务是否恢复
服务降级
服务不可用时,返回一个兜底结果,而不是直接报错。
常见降级方式:
- 返回默认值
- 返回空列表
- 返回友好提示
5.你们的微服务是怎么监控的(SkyWalking)?

问题我们某一个服务挂了,这么确定是哪一个服务挂了。
为什么需要服务监控??
- 问题的定位
- 性能分析
- 服务间的关系
- 服务警告
介绍工具
SkyWalking 就是用来帮你自动收集这些调用链路数据,把它们画成图,告诉你慢在哪里、错在哪里。
具体功能
这个工具会帮我们解决上面问题,进行压测的时候,就可以看到哪一个接口比较慢,哪个服务员有问题。
6. 为什么要限流?
为什么要限流??
- 服务并发量大
- 防止用户恶意刷接口
解决办法
Nginx限流
-
控制速率: 解决突发流量,使用漏桶算法来过滤,让请求以固定的速率处理请求,可以应对突发流量。
-
控制并发数: 限制单个ip的连接数和并发连接总数。

-
进水: 请求就像水一样,不管是一滴一滴慢慢滴,还是突然一盆水倒进去,都先进入水桶。
-
出水: 水桶底部的小孔出水速度是恒定的(比如每秒流出 10 滴)。
-
溢出: 如果进水太快,水桶满了,多余的水就会溢出(请求被丢弃或报错)。
总结:严格限制速度
网关限流
- 在spring cloud gateway中支持局部过滤器RequestRateLimiter来做限流,使用的是令牌桶算法。
- 可以根据ip或者路径进行限流,可以设置每秒填充平均速率,和令牌桶总容量。

【核心思想】
想象你面前有一个不断产生令牌(Token)的机器,旁边有一个装令牌的桶。
- 发令牌: 系统以恒定的速率往桶里放令牌(比如每秒放 10 个)。
- 存令牌: 桶有容量上限,如果桶满了,新的令牌就会被丢弃。
- 拿令牌: 当一个请求来临时,它必须从桶里拿走一个令牌才能被处理。
- 拒绝: 如果桶里没有令牌了,请求就被拒绝。
限制平均速度,但允许偶尔的高峰
7. 分布式系统理论
解释一下CAP和BASE??
- 分布式事务的指导
- 分布式系统设计方向
- 根据业务指导使用正确的技术选择
7.1 CAP定理
CAP是分布式系统的三个指标

分布式无法同时满足这三个指标。
一致性
C - Consistency(一致性): 用户访问分布式任意节点数据必须是一致的。

A - Availability(可用性): 系统中非故障的节点,在合理的时间内必须返回合理的响应(不能报错,也不能超时)。

P - Partition tolerance(分区容错性): 当网络发生分区(Partition)故障时(即系统中的一部分节点无法与另一部分节点通信),系统仍然能够继续运行。

结论:
- 分布式系统节点肯定需要网络连接的,分区(p)是必然存在的
- 高可用(A)和数据强一致性(C)必须二选一
7.2 BASE 理论
即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性。
BASE 理论本质上是对 CAP 的延伸和补充,更具体地说,是对 CAP 中 AP 方案的一个补充。
结论:
AP 方案只是在系统发生分区的时候放弃一致性,而不是永远放弃一致性。在分区故障恢复后,系统应该达到最终一致性。这一点其实就是 BASE 理论延伸的地方。
BASE理论三要素

基本可用
基本可用是指分布式系统在出现不可预知故障的时候,允许损失部分可用性。
什么叫允许损失部分可用性呢?
比如说:响应时间上的损失:,正常情况下,处理用户请求需要 0.5s 返回结果,但是由于系统出现故障,处理用户请求的时间变为 3 s。
软状态
软状态指允许系统中的数据存在中间状态(CAP 理论中的数据不一致)
认为该中间状态的存在不会影响系统的整体可用性,即允许系统在不同节点的数据副本之间进行数据同步的过程存在延时。
最终一致性
最终一致性强调的是系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性。
8. 项目采用的是那种分布式事务解决方案?
一般来说只要分布式项目,就会使用分布式事务问题。
有好几种实现方案,但是我只接触过一种,下面:
这个问题还是比较好的,我的微服务使用的是MQ模式实现的分布式,A服务写数据的时候,需要在同一个事务内发送消息到另一个事务,异步,性能好。

如果说支付宝事务发生异常,只能人工手动解决了
8. 分布式服务接口幂等性如何设计??
幂等:多次调用同一个方法或者接口不会改变业务状态,可以保证重复调用的结果和单次调用的结果一致性。
比如说用户下单,因为网络波动,而产生了多个订单。
需要幂等性场景
- 用户重复点击(网络波动)
- MQ消息重复
- 应用使用失败或者超时重试机制
考虑常用接口
- get是查询操作肯定是幂等的。
- 新增操作请求多次就会造成结果不同,不是幂等的。
- 更新操作,如果是绝对值更新是幂等的,如果是增量的方式,则不是幂等性。

- 删除操作,根据唯一值删除,是幂等的。
解决方案:
- mysql唯一索引
- token+ redis
1. mysql唯一索引
可以解决新增的幂等性问题,解决不了修改的幂等性
核心原因是: 唯一索引的排他性约束,能从数据库层面强制保证相同的关键数据只能被插入一次,无论你的代码重复执行多少次,最终只会有一条有效记录。
唯一索引: MySQL 中给字段(或字段组合)创建唯一索引后,数据库会强制校验 —— 新插入的记录,其唯一索引字段的值必须是表中没有的,否则插入失败(报 Duplicate entry 错误)。
我们用「用户创建订单」这个典型场景举例:
-- 创建订单表
CREATE TABLE t_order (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT NOT NULL COMMENT '用户ID',
biz_no VARCHAR(32) NOT NULL COMMENT '订单业务唯一编号',
amount DECIMAL(10,2) NOT NULL COMMENT '订单金额',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
-- 创建组合唯一索引,保证(user_id, biz_no)唯一
UNIQUE KEY uk_user_biz (user_id, biz_no)
);
订单表 t_order 中,「用户 ID + 订单业务号」是不会重复的核心标识(比如用户 A 的「20260121001」号订单)。
当用户提交订单时,代码执行插入操作:
// 伪代码:创建订单
public void createOrder(Long userId, String bizNo, BigDecimal amount) {
try {
// 执行插入SQL
String sql = "INSERT INTO t_order (user_id, biz_no, amount) VALUES (?, ?, ?)";
jdbcTemplate.update(sql, userId, bizNo, amount);
System.out.println("订单创建成功");
} catch (DuplicateKeyException e) {
// 捕获唯一索引冲突异常,说明订单已存在
System.out.println("订单已创建,无需重复处理");
}
}
代码执行:
- 第一次请求:数据库中无 (userId, bizNo) 这条记录,插入成功,生成 1 条订单。
- 第二次 / 第 N 次请求:数据库校验唯一索引,发现该组合值已存在,直接抛出 Duplicate entry 异常;代码捕获异常后,判定「订单已存在」,不再重复创建 —— 最终结果和执行一次完全一致,实现了新增的幂等性。
2. token+redis
这个方案可以解决新增和修改的幂等性问题
这么解决的呢?
比如说: 创建订单和修改订单场景
创建订单: 在进入购物界面前,生成一个token缓存在redis中,并把它返回前端,选购好商品之后。点击创建订单,这时候前端带着这个token过来服务器,服务器验证redis是否存在该token,存在创建完订单之后把redis相对应的token删除,这个过程是事务,这样即使后面网络波动,多次创建订单都不会影响其幂等性。

分布式锁
这个是可以解决新增修改的幂等性的。
这个就不用我说了吧

这个是线性的性能比较低。
面试回答:

9. 分布式任务调度??
分布式任务调度: 解决多台机器下定时任务不重复、不丢失、能并行执行的系统。
单机定时任务就会遇到三个致命问题:
重复执行问题(最严重):
比如你写了一个定时任务,每天凌晨 0 点给所有用户发优惠券。
现在你有 10 台服务器(集群),代码部署在这 10 台机器上。
如果不做处理,凌晨 0 点时,这 10 台机器都会跑这个任务。结果就是:用户收到了 10 张优惠券,公司亏惨了。
单点故障问题:
你的定时任务只部署在一台专门的机器上。
如果这台机器死机了、断电了,任务就彻底不跑了。比如工资单没生成,员工会炸锅。
任务堆积与性能瓶颈:
任务量非常大(比如要处理 1000 万条数据)。
单台机器 CPU 只有 8 核,处理完要 10 个小时,可能还没处理完第二天的任务又来了。
目前主流的是xxl-job,那他解决了什么问题
- 解决分布式集群的任务的重复执行问题
- cron表达式定义灵活
- 定时任务失败,重试和统计
- 任务量大分片执行
接下来到面试题了
9. 1 xxl-job路由策略有哪些?
常见路由策略有很多选择三种去面试
- ROUND(轮询)
- FAILOVER(故障转移):按照顺序进行心跳检测,第一个心跳检测成功的机器选定为执行目标的机器并发起调度
- 分片广播(SHARDING_BROADCAST):特殊策略:所有在线节点都会执行该任务,但每个节点会拿到不同的分片参数,并行处理海量任务,效率极高;
9.2 xxl-job任务执行失败怎么解决?

两步:设置路由策略为故障转移,失败重试次数调高
也可以查看xxl-job的任务失败日志,通过邮件告警对应的人解决问题
9.3 如果有大量数据的任务同时都需要执行,这么解决??
执行器集群部署时,任务路由策略选择分片广播情况下,一次任务调度会将广播触发对应集群中所有执行器执行一次任务。
即:把任务按照算法分给服务

面试回答:

好了今天就到这里
更多推荐
所有评论(0)