首页 > 其他分享 >day03

day03

时间:2024-07-25 15:54:59浏览次数:14  
标签:事务 seata day03 ItemClient hmall 线程 sentinel

微服务保护和分布式事务

微服务保护

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

解决方案:

  • 请求限流:限制或控制接口访问的并发流量,避免服务因流量激增而出现故障。
  • 线程隔离:控制业务可用的线程数量,将故障隔离在一定范围内
  • 服务熔断:将异常比例过高的接口断开,拒绝所有请求,直接走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;
}

标签:事务,seata,day03,ItemClient,hmall,线程,sentinel
From: https://www.cnblogs.com/six-years/p/18323334

相关文章

  • C语言学习day03
    变量概念表面:程序运行过程中取值可以改变的数据实质:变量其实代表了一块内存区域/单元/空间。变量名可视为该区域的标识。整个变量分为三部分:  变量名:这个只是变量的一个标识,我们借助变量名来存取数据。  变量空间/内存单元:这个就是内存中分配的一块用来存储数据的......
  • 嵌入式学习day03
    概念Linux中的角色:当前用户当前用户组其他用户组Linux中的权限:读写执行(不是所有文件都需要执行权限,仅限与应用程序)普通用户和最高管理员普通用户:安装系统时我们创建的用户,这个也可以由管理员来分配,如:myl最高管理员:root,Linux系统内置,当第一次使用root用户需要修改密......
  • day03Linux学习
    普通用户和最高管理员切换普通切换root用户sudo-i---没有设置密码的时候suroot---设置密码之后root切换普通用户su用户名添加新用户语法:useradd[选项]用户名选项:-d:设置新用户登陆时所使用的家目录-g(group):设置组-m(mkdir):没有主目录会自动创建用户主目录eg......
  • 黑马头条(day03)
    目录1)自媒体环境搭建1.1)后台搭建1.2)前台搭建 2)自媒体素材管理2.1)素材上传2.2.1)需求分析2.2.2)表结构2.2.3)实现思路2.2.4)接口定义2.2.5)集成heima-file-starter2.2.6)具体实现2.2)素材列表查询2.2.1)接口定义2.2.2)功能实现3)自媒体文章管理3.1)查询所有频道3.1.1)需求......
  • day03-Docker
    Docker实用篇javajdkmysqlmaven…0.学习目标什么是镜像?了解镜像操作(重点)容器操作(重点)数据卷操作(重点)查看、进入、操作文件、挂载自定义镜像(重点)集群部署微服务镜像仓库(了解)1.初识Docker1.1.什么是Docker微服务虽然具备各种各样的优势,但服务的拆分通用给部署带来......
  • day03:菜品管理
    文章目录数据库设计公共字段填充问题分析实现思路代码演示新增菜品-文件上传介绍实现方式前端使用文件上传三要素使用阿里云OSS服务进行文件存储阿里云OSS使用服务进行文件上传新增菜品接口设计代码书写分页查询接口设计代码书写批量删除接口设计代码书写修改菜品......
  • Day03
    Python3的安装在官网下载包,把安装包拖进虚拟机直接解压tar—zxvf进入解压后的目录找到可执行文件./configure--prefix=/usr/local/Python  //安装路径Make&&makeinstall  //变异并安装进入python3[root@zabbixserver Python-3.12.4]#/usr/local/Python/bin......
  • 云计算day03
    Python源码安装以及安装和运行redis和mongodb一、Python源码安装1.下载源码(3.12.4官网)tgz2.Tar-zxvf压缩文件名 [root@localhost~]#tar-zxvfPython-3.12.4.tgz3.安装依赖包yum-yinstallopenssl-develbzip2-devellibffi-develzlib-develgcc3.编译安装[root......
  • day03-loadbalancer
    1概述LoadBalancer:被包含于springcloudcommons下用来替换以前的ribbon组件,一个客户端负载均衡器。不仅支持RestTemplate,还支持WebClient(SpringWebFlux中提供的功能,可以实现响应式异步请求)。客户端负载均衡和服务端负载均衡有什么区别服务端负载均衡:负载均衡在服务器上......
  • python随笔day03
    python面试基础问题lambda表达式基本语法:变量=lambda[参数列表]:表达式(函数代码+返回值)#调用变量()例子如下:#加法求和函数a=lambdaa,b:a+bprint(a(1,2))#3#args元组类型b=lambda*args:argsprint(b('a','b','c','d',10))#('a','b&......