day03

微服务保护和分布式事务

微服务保护

微服务雪崩问题:某个微服务出现故障,导致调用链上的集群都被阻塞

解决方案:

  • 请求限流:限制或控制接口访问的并发流量,避免服务因流量激增而出现故障。
  • 线程隔离:控制业务可用的线程数量,将故障隔离在一定范围内
  • 服务熔断:将异常比例过高的接口断开,拒绝所有请求,直接走fallback
    • fallback:失败处理逻辑,让业务失败时不抛出异常,返回默认数据或友好提示

常用工具:sentinel

sentinel是阿里云开源的一个微服务保护方案,主要包括核心jar包和控制台两个模块

请求限流

在sentinel中,针对某个簇点进行流控,限制QPS,簇点就是controller层的一个个请求方法

线程隔离

在sentinel中,针对某个簇点进行流控,设置并发线程数,这样就能限制该业务的线程资源

由于是对微服务调用,所以我们要配置openFeign整合sentinel:

<!--sentinel-->
<dependency>
    <groupId>com.alibaba.cloud</groupId> 
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
  1. openFeign整合sentinel
feign:
  sentinel:
    enabled: true # 开启feign对sentinel的支持
  1. 默认情况下SpringBoot项目的tomcat最大线程数是200,允许的最大连接是8492,单机测试很难打满。因此修改tomcat连接配置
server:
  port: 8082
  tomcat:
    threads:
      max: 50 # 允许的最大线程数
    accept-count: 50 # 最大排队等待数量
    max-connections: 100 # 允许的最大连接
  1. 在sentinel中设置簇点并发线程数即可实现线程隔离

服务熔断

由于设置请求限流和线程隔离,这样会导致接口的QPS较低,对于这些请求,我们不一定要抛出异常,可以进行降级熔断处理

  • 降级处理

触发限流或熔断后,不一定要直接抛出异常,可以让该请求走降级逻辑fallback,返回一些默认数据或友好数据

给FeignClient编写失败后的降级逻辑有两种方式:

方式一:FallbackClass,无法对远程调用的异常做处理

方式二:FallbackFactory,可以对远程调用的异常做处理,我们一般选择这种方式。

降级处理实现(针对ItemClient):

  1. 定义一个类实现FallbackFactory<ItemClient>,这里指定泛型为<ItemClient>表明是ItemClient的降级处理逻辑
  2. 重写create方法,该方法的目的是返回一个新ItemClient对象
  3. return new ItemClient(){}中重写接口方法,为各个接口添加降级处理
  4. 当触发限流时,就会走这里的降级逻辑
package com.hmall.api.fallback;

import com.hmall.api.client.ItemClient;
import com.hmall.api.dto.ItemDTO;
import com.hmall.api.dto.OrderDetailDTO;
import com.hmall.common.exception.BizIllegalException;
import com.hmall.common.utils.CollUtils;
import org.springframework.cloud.openfeign.FallbackFactory;

import java.util.Collection;
import java.util.List;

public class ItemFallbckFactory implements FallbackFactory<ItemClient> {
    /**
     * 创建并返回一个新的ItemClient类
     * @param cause
     * @return
     */
    @Override
    public ItemClient create(Throwable cause) {
        return new ItemClient() {
            //对queryItemByIds接口做降级处理
            @Override
            public List<ItemDTO> queryItemByIds(Collection<Long> ids) {
                return CollUtils.emptyList();
            }

            //对deductStock接口做降级处理
            @Override
            public void deductStock(List<OrderDetailDTO> items) {
                throw new BizIllegalException(cause);
            }
        };
    }
}

  1. 同时,要将ItemFallbckFactory注册为一个bean,在配置类中声明
@Bean
    public ItemFallbckFactory itemFallbckFactory(){
        return new ItemFallbckFactory();
    }
  1. 为ItemClient添加fallback参数
@FeignClient(value = "item-service", fallbackFactory = ItemFallbckFactory.class)
public interface ItemClient {...}
  • 服务熔断

在sentinel控制台中可针对某个簇点配置熔断策略,配置策略主要有三种:慢调用比例、异常比例、异常数

分布式事务

分布式事务指多个微服务的分支事务关联形成的全局事务,无法满足事务的ACID特性,因此需要引入外部服务来解决分布式事务

分布式事务解决方案——Seata

Seata架构

  • TC (Transaction Coordinator) -协调者:维护全局和分支事务的状态,协调全局事务提交或回滚。
  • TM (Transaction Manager) - 事务管理器:定义全局事务的范围、开始全局事务、提交或回滚全局事务。
  • RM (Resource Manager) - 资源管理器:管理分支事务,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。

image-20240528122820761

Seata服务部署

  1. docker部署seata文档

  2. 微服务集成seata

为了方便集成seata,将配置文件上传到nacos

  • 在微服务中引入相关依赖和seata依赖
<!--seata-->
  <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
  </dependency>
  • nacos添加seata配置文件.yaml,微服务拉取该配置文件
seata:
  registry: # TC服务注册中心的配置,微服务根据这些信息去注册中心获取tc服务地址
    type: nacos # 注册中心类型 nacos
    nacos:
      server-addr: 192.168.48.100:8848 # nacos地址
      namespace: "" # namespace,默认为空
      group: DEFAULT_GROUP # 分组,默认是DEFAULT_GROUP
      application: seata-server # seata服务名称
      username: nacos
      password: nacos
  tx-service-group: hmall # 事务组名称
  service:
    vgroup-mapping: # 事务组与tc集群的映射关系
      hmall: "default"
  • @Transactional注解改为seata提供的@GlobalTransactional注解,即开启分布式事务的入口

seata的分布式事务解决方案

seata提供了四种解决方案:

  • XA:当一个分支事务执行完毕后,不立刻提交,持有锁,报告状态,等所有分支事务完成后,由TC来通知提交/回滚
image-20240528152102943
  • TCC
  • AT:记录undo.log快照,分支事务执行成功后直接提交,释放锁,报告状态
image-20240528152319257
  • SAGA

简述AT模式与XA模式最大的区别是什么?

  • XA模式一阶段不提交事务,锁定资源;AT模式一阶段直接提交,不锁定资源。
  • XA模式依赖数据库机制实现回滚;AT模式利用数据快照实现数据回滚。
  • XA模式强一致;AT模式最终一致

RabbitMQ

RabbitMQ是基于Erlang语言开发的开源消息通信中间件,官网地址

RabbitMQ的docker部署

  • 15672:RabbitMQ提供的管理控制台的端口
  • 5672:RabbitMQ的消息发送处理接口
docker run \
 -e RABBITMQ_DEFAULT_USER=skywalker \
 -e RABBITMQ_DEFAULT_PASS=123321 \
 -v mq-plugins:/plugins \
 --name mq \
 --hostname mq \
 -p 15672:15672 \
 -p 5672:5672 \
 --network hm-net\
 -d \
 rabbitmq:3.8-management

RabbitMQ相关概念和原理

可将消息直接发给队列,或发给交换机,再由交换机转发给绑定的队列

  • publisher:生产者,也就是发送消息的一方
  • consumer:消费者,也就是消费消息的一方
  • queue:队列,存储消息。生产者投递的消息会暂存在消息队列中,等待消费者处理
  • exchange:交换机,负责消息路由。生产者发送的消息由交换机决定投递到哪个队列。
  • virtual host:虚拟主机,起到数据隔离的作用。每个虚拟主机相互独立,有各自的exchange、queue
image-20240528174513102

Spring集成RabbitMQ

RabbitMQ基于AMQP协议通信,Spring官方基于RabbitMQ提供了SpringAMQP消息收发模板工具,只需引入依赖并配置rabbitmq即可

  1. 引入依赖
<!--AMQP依赖,包含RabbitMQ-->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
  1. 配置rabbitmq
spring:
  rabbitmq:
    host: 192.168.150.101 # 你的虚拟机IP
    port: 5672 # 端口
    virtual-host: /hmall # 虚拟主机
    username: hmall # 用户名
    password: 123 # 密码
  1. 发送消息

注入SpringAMQP中的RabbitTemplate对象,调用convertAndSend(args[])方法发送消息

  1. 接收消息

在方法上声明@RabbitListener注解,指定交换机、队列等参数,即可通过形参接收到对应队列的消息

交换机类型

交换机的类型有四种:

  • Fanout:广播,将消息交给所有绑定到交换机的队列。我们最早在控制台使用的正是Fanout交换机
  • Direct:订阅,基于RoutingKey(路由key)发送给订阅了消息的队列
  • Topic:通配符订阅,与Direct类似,只不过RoutingKey可以使用通配符
  • Headers:头匹配,基于MQ的消息头匹配,用的较少。

声明队列和交换机

  • 方式一:基于Bean来声明
  • 方式二:基于@RabbitListener注解声明

配置JSON消息转换器

在生产者和消费者都要配置

//导入依赖
<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.9.10</version>
</dependency>

@Bean
public MessageConverter messageConverter(){
    // 1.定义消息转换器
    Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();
    // 2.配置自动创建消息id,用于识别不同消息,也可以在业务中基于ID判断是否是重复消息
    jackson2JsonMessageConverter.setCreateMessageIds(true);
    return jackson2JsonMessageConverter;
}
posted @ 2024-07-25 15:43  Arthur-Morgan  阅读(5)  评论(0编辑  收藏  举报