Java 八股文:微服务篇

2 - 微服务篇

2.1 Spring Cloud

2.1.1 服务注册
2.1.1.1 微服务常用框架?Spring Cloud 五大组件?

1. 微服务常用框架

  1. Spring Cloud:基于Spring Boot的一系列框架的集合,用于简化分布式系统的开发,如配置管理、服务发现、断路器等。
  2. Dubbo:由阿里巴巴开源的分布式服务化治理框架,通过RPC请求方式访问。

2. Spring Cloud 五大组件

  1. 注册中心 / 配置中心:Nacos。就像是服务的黄页,服务们都在这里登记,方便互相发现和联系,还能统一管理配置信息。
  2. 负载均衡:Ribbon。就像流量分配器,能让请求均匀地分散到不同的服务器上,防止某个服务器因为请求太多而崩溃。
  3. 服务调用:Feign。这个组件让服务之间的调用变得简单,就像打电话一样,直接就能联系到其他服务。
  4. 服务保护:sentinel。它是一个保护机制,当服务接收到的请求太多时,它会介入,防止服务因为过载而崩溃。
  5. 服务网关:Gateway。作为服务的入口,它控制着哪些请求可以进入,就像门卫,确保只有合法的请求才能访问到服务。
2.1.1.2 服务注册和发现?服务调用?

1. 注册和发现

  • 服务注册:服务提供者需要把自己的信息注册到 nacos ,由 nacos 来保存这些信息,比如服务名称、ip、端口等。
  • 服务发现:消费者向 nacos 拉取服务列表信息,如果服务提供者有集群,则消费者会用负载均衡算法,选择一个发起调用。
  • 服务监控:服务提供者会每隔 30 秒向 nacos 发送心跳,报告健康状态,如果 90 秒没接收到心跳,从 nacos 中剔除。

2. 服务调用

  1. 添加依赖:在项目的pom.xml文件中添加 OpenFeign 的依赖。
  2. 启用 OpenFeign:在服务消费者的启动类上添加@EnableFeignClients注解,开启 OpenFeign 功能。
  3. 定义 Feign 接口:创建一个接口,并使用@FeignClient注解指定服务名,服务名与Nacos中注册的服务名一致。
  4. 使用 Feign 客户端:在需要调用远程服务的类中,直接注入上面定义的Feign客户端接口,并调用其方法即可。
2.1.1.3 谈谈你对 RPC 框架的理解?
  • RPC(远程过程调用)框架允许程序像调用本地函数一样调用远程服务器上的方法。

    它通过序列化和网络传输隐藏了网络通信的复杂性,使得开发者可以跨语言、跨平台进行服务调用。

    常见的 RPC 框架有 Dubbo。在微服务架构中,RPC 框架用于服务间的通信,支持服务的动态发现和负载均衡。

  • 在 Spring Cloud 中,服务间的通信通常是基于 HTTP 协议的 RESTful API,而不是传统的 RPC 机制。

2.1.2 负载均衡
2.1.2.1 你项目的负载均衡如何实现的?

负载均衡用于在多个服务器之间分配网络或请求负载,以确保没有单个服务器因过载而成为性能瓶颈。

负载均衡的实现:

  1. Ribbon: 客户端负载均衡器,它提供了一系列策略(如轮询、随机、响应时间加权等)来控制服务之间的请求路由。
  2. Feign: 声明式的Web服务客户端,简化了Web服务客户端的编写,并内置了对Ribbon的支持,可以自动进行负载均衡。
  3. Zuul: Netflix提供的API网关服务,它提供了动态路由、监控、弹性和安全的功能,也可以用来实现负载均衡。

实现步骤:

  1. 在服务消费者中引入Ribbon或Feign客户端。
  2. 配置负载均衡策略,如在application.yml中设置。
  3. 使用@LoadBalanced注解启用Ribbon的负载均衡功能。
2.1.2.2 Ribbon 负载均衡策略有哪些 ?
  1. RandomRule随机 选择一个可用的服务器

  2. RoundRobinRule:简单 轮询 服务列表来选择服务器

  3. WeightedResponseTimeRule:按照 权重 来选择服务器,响应时间越长,权重越小

  4. ZoneAvoidanceRule区域 敏感策略,以区域可用的服务器为基础进行服务器的选择

2.1.2.3 自定义负载均衡策略如何实现 ?
  1. 扩展Ribbon: 创建一个继承com.netflix.loadbalancer.AbstractLoadBalancingRule的类,并重写choose方法。
  2. 注册自定义策略: 将自定义策略注册到Spring容器中,通常是通过@Bean注解。
  3. 指定使用自定义策略: 在配置文件中指定使用你的自定义策略。
public class CustomRule extends AbstractLoadBalancingRule {
    @Override
    public Server choose(Object key) { ... }
}
@Configuration
public class RibbonConfig {
    @Bean
    public IRule customRule() { return new CustomRule(); }
}
2.1.3 服务雪崩、服务降级、服务熔断
  1. 服务雪崩: 指一个服务的故障导致依赖它的服务也发生故障,从而引发连锁反应,最终导致系统崩溃。
  2. 服务降级: 指在系统负载过高或服务不可用时,临时关闭一些服务功能,以释放资源保证核心服务的正常运行。
  3. 服务熔断: 是一种保护机制,当服务故障达到一定阈值时,自动“断开”服务调用,避免服务雪崩。
2.1.4 服务监控

服务监控的目的:监控服务的健康状况、性能指标等,及时发现并处理问题。

监控工具:

  • Spring Boot Actuator: 提供了一系列监控和管理的端点。
  • Prometheus: 一个开源监控系统,可以与Spring Boot Actuator集成。
  • Grafana: 一个开源的数据可视化和监控平台,可以展示Prometheus的数据。

2.2 业务相关

2.2.1 你项目中做过限流吗?怎么做的?

限流的目的: 防止系统过载,保证服务的稳定性。

先介绍业务:项目中有一个活动,到了假期就会抢购优惠券,QPS 最高可以达到 2000,平时在 10-50 之间。

  1. nginx 限流:使用漏桶算法,让请求以固定的速率处理请求,应对突发流量控制并发数,限制单个 ip 的链接数和并发总数。
  2. 网关限流:使用令牌桶算法,gateway 中支持局部过滤器。根据 ip 或路径进行限流,设置每秒填充平均速率和令牌桶总容量。
2.2.2 什么是 CAP 和 BASE?

1. CAP 定理:

  • 一致性(Consistency):在分布式系统中的所有数据副本中,如果在某个节点上更新了一个数据项,

    那么在其他节点上读取时,应该能够看到最新的数据项,即所有节点的数据保持一致。

  • 可用性(Availability):系统在任何时候都能够响应用户的请求,即使在出现网络分区的情况下,系统仍然能够提供服务。

  • 分区容错性(Partition tolerance):分布式系统在遇到网络分区(网络中某些节点之间的连接断开)时,仍然能够继续运行。

CAP 定理指出,在设计分布式系统时,只能同时满足其中的两个属性,而不可能同时满足所有三个属性。

2. BASE 理论:

  • 基本可用(Basically Available):分布式系统在出现故障时,允许损失部分可用性,但系统仍然能够继续运行。
  • 软状态(Soft state):系统的数据状态不需要严格一致,可以容忍中间状态的存在,这种状态称为软状态。
  • 最终一致(Eventual consistency):系统不保证数据的即时一致性,但保证经过一段时间后,数据最终会达到一致状态。

BASE 理论是相对于传统的 ACID 事务模型提出的,它更适用于分布式系统,强调系统的可用性和容错性,而不是严格的一致性。

2.2.3 分布式事务的解决方案?

在微服务架构中,分布式事务是一个常见的问题,因为一个业务操作可能需要跨越多个服务。

  1. 两阶段提交(2PC):强一致性的解决方案,它通过准备和提交阶段来确保所有参与事务的服务要么全部提交,要么全部回滚。

  2. 三阶段提交(3PC):这是2PC的改进版本,增加了一个超时机制,以减少事务管理器在网络分区时的阻塞。

  3. 消息队列(MQ):这是一种最终一致性的解决方案,通过消息队列来异步处理事务。

    当一个服务完成本地事务后,它会发送一个消息到消息队列,然后由消息队列确保消息被消费并触发另一个服务的事务。

2.2.4 分布式服务的接口幂等性如何设计?

幂等性是指执行多次和执行一次的效果相同。幂等性的实现:

  1. 乐观锁: 通过版本号或时间戳来控制更新操作的幂等性。
  2. 业务规则: 确保业务逻辑的幂等性,如检查操作是否已经执行。
  3. 分布式锁: 使用Redis、Zookeeper等实现分布式锁,保证操作的原子性。
2.2.5 分布式任务调度
2.2.5.1 XXL-JOB 路由策略有哪些?
  1. 轮询:任务按照顺序轮流分配给每个可用的执行器。
  2. 随机:任务随机分配给任意一个可用的执行器。
  3. 故障转移:任务首先尝试分配给第一个可用的执行器,如果失败,则自动转移到下一个。
  4. 分片广播:任务被分成多个片段,每个片段都广播到所有可用的执行器,由所有执行器并行处理。
2.2.5.2 XXL-JOB 任务执行失败怎么解决?
  1. 重试机制: XXL-JOB支持失败重试,可以配置重试次数和重试间隔。
  2. 报警通知: 配置失败报警,如邮件、短信等。
  3. 日志分析: 查看任务执行日志,分析失败原因。
2.2.5.3 如果有大数据量的任务同时都需要执行,怎么解决?
  1. 任务分片: 将大任务拆分成多个小任务并行执行。
  2. 资源隔离: 为不同任务分配不同的执行器,避免资源竞争。
  3. 限流控制: 控制任务的提交速率,避免瞬间高并发导致系统压力过大。
2.2.6 分布式锁的三种实现方式?
  1. 基于 MySQL 的分布式锁

    • 创建锁表: 在MySQL中创建一个表,通常包含一个唯一的主键ID或唯一索引字段。

    • 获取锁: 当需要获取锁时,尝试插入一条记录,如果插入成功(即没有违反唯一性约束),则认为获取了锁。

    • 释放锁: 完成操作后,删除对应的记录以释放锁。

  2. 基于 Redis 的分布式锁

    • SET NX: 使用SET NX命令尝试设置一个键,如果键不存在,则设置成功,获取锁;如果键已存在,则获取失败。

    • Lua脚本: 为了确保原子性,通常使用Lua脚本来实现锁的获取和释放,这样可以在一个原子操作中完成检查和设置。

    • 设置过期时间: 为了避免死锁,设置键的过期时间,即使持有锁的进程崩溃,锁也会在一定时间后自动释放。

  3. 基于 Zookeeper 的分布式锁

    • 创建临时节点: 客户端在Zookeeper中创建一个临时节点来表示它想要获取锁。

    • 创建顺序节点: 如果需要多个客户端按顺序获取锁,可以创建顺序节点,Zookeeper会为每个节点分配一个唯一的序号。

    • 获取最小序号: 客户端检查自己创建的节点是否是序号最小的,如果是,则认为获取了锁。

    • 监听节点变化: 客户端监听比自己序号小的前一个节点的删除事件,一旦前一个节点被删除,当前客户端就获取了锁。

#java##后端开发##八股文#
全部评论

相关推荐

评论
5
15
分享

创作者周榜

更多
牛客网
牛客企业服务