SpringCloud day05学习总结

SpringCloud Alibaba、Nacos、Sentinel、Seata

  • SpringCloud Alibaba
    • 学习资料获取
  • Nacos(取代Eureka、Config、Bus)
    • 1.运行Nacos
    • 2.nacos作为服务注册中心
      • nacos与其他注册中心的比较
    • 3.nacos作为配置中心--基础配置
      • @RefreshScpoe 与Cofig一样用Spring的通用API 支持动态刷新
      • Nacos自动刷新(只要controller上写了@RefreshScope)
    • 4.nacos作为配置中心--分类配置
      • 三种方案加载配置
    • 5.nacos集群和持久化配置(⭐⭐⭐⭐⭐)
      • 官网说明
      • nacos持久化配置解释
      • Linux版Naocs+mysql生产环境配置
      • 集群的配置步骤(⭐⭐⭐⭐⭐)
  • Sentinetl(取代Hystrix)
    • 1.Sentinel控制台
      • Sentinel由两部分组成
      • 安装步骤
    • 2.初始化演示工程
    • 3.流控规则
      • 基本介绍
      • 流控模式1:直接
      • 流控模式2:关联
      • 流控模式3:链路
      • 流控效果1:快速失败
      • 流控效果2:预热Warm Up
      • 流控效果3:排队等待
    • 5.降级规则(熔断降级)
      • 官网
      • 基本介绍
      • 降级策略实战1:RT
      • 降级策略实战2:异常比例
      • 奖及策略实战3:异常数
    • 6.热点Key限流
      • 官网
      • 承Hystrix启热点Key(从@HystrixCommand--->`@SentinelResource`)
      • 源码:
      • 代码:
      • 配置:
      • 参数例外项
      • 其他:手贱添加异常时
    • 7.系统规则(⭐⭐⭐⭐)
      • 官网
      • 各配置参数说明
    • 8.@SentinelResource
      • 按资源名称限流+后续处理
      • 按URL地址限流+后续处理
      • 上面两个主要讲了既可以用@GetMapping("/rateLimit/byUrl")中URL来配,也可以用@SentinelResource(value = "byUrl")中的资源名来配
      • 兜底方案面临的问题(和豪猪哥Hystrix一样)
      • 客户自定义限流处理逻辑
      • 更多注解属性说明
    • 9.服务熔断功能
      • Ribbon系列(没讲整合Ribbon不过OpenFeign也整合了Ribbon)
      • OpenFeign系列
      • 熔断框架对比
    • 10.规则持久化
      • 怎么玩
      • 步骤
  • Seata( @GlobalTransactional(name = "唯一",rollbackFor = 某个异常.class))
    • 1.简介
    • 2.Seata的安装
    • 3.订单/库存/账户业务数据库准备
    • 4.订单/库存/账户业务微服务准备

SpringCloud Alibaba

学习资料获取

0.曾经的官网https://spring.io/projects/sprinq-cloud-alibaba#overview
1.中文版官网https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md
2.英文版官网https://spring-cloud-alibaba-group.github.io/github-pages/greenwich/spring-cloud-alibaba.html、https://github.com/alibaba/spring-cloud-alibaba

Nacos(取代Eureka、Config、Bus)

1.为什么叫Nacos?
在这里插入图片描述
2.是什么?
就是注册中心+配置中心
Nacos = Eureka + Config + Bus
3.下载地址https://github.com/alibaba/Nacos
官网https://nacos.io/zh-cn/index.html
参考文档https://spring-cloud-alibaba-group.github.io/github-pages/greenwich/spring-cloud-alibaba.html#_spring_cloud_alibaba_nacos_discovery
4.各注册中心比较
SpringCloud day05学习总结_第1张图片

1.运行Nacos

SpringCloud day05学习总结_第2张图片
账户名、密码都是nacos

2.nacos作为服务注册中心

1.建modal cloudalibaba-provider-payment9001
2.改pom

    <dependencies>
        <!--SpringCloud ailibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- SpringBoot整合Web组件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--日常通用jar包配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

3.写yml

server:
  port: 9002
spring:
  application:
    name: nacos-provider-payment
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
management:
  endpoints:
    web:
      exposure:
        include: '*'

4.主启动@EnableDIscoveryClient
5.业务类
controller

package com.atguigu.springcloud.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class PaymentController {

    @Value("${server.port}")
    private String serverPort;

    @GetMapping("/payment/nacos/{id}")
    public String getPayment(@PathVariable("id") Long id) {
        return "nacos registry,serverport:" + serverPort + "\tid:" + id;
    }
}

6.测试
①先启动nacos
②启动9001 发送http://localhost:9001/payment/nacos/55

按照payment9001的方法创建payment9002

如果想取巧不想新建重复劳动,也可以直接拷贝虚拟端口映射
SpringCloud day05学习总结_第3张图片
SpringCloud day05学习总结_第4张图片
7.模块cloudalibaba-consumer-nacos-order83 懂得都懂

server:
  port: 83
spring:
  application:
    name: nacos-order-consumer
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
service-url:
  nacos-user-service: http://nacos-provider-payment

8.业务类
配置类,获取RestTemplate

package com.atguigu.springcloud.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class ApplicationContextConfig {

    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}

controller

package com.atguigu.springcloud.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class OrderNacosController {

    @Autowired
    private RestTemplate restTemplate;

    @Value("${service-url.nacos-user-service}")
    public String SERVER_URL;

    @GetMapping("/consumer/payment/nacos/{id}")
    public String paymentInfo(@PathVariable("id") Long id) {
        return restTemplate.getForObject(SERVER_URL + "/payment/nacos/" + id, String.class);
    }
}

9.测试 http://localhost:83/consumer/payment/nacos/55

nacos与其他注册中心的比较

SpringCloud day05学习总结_第5张图片
SpringCloud day05学习总结_第6张图片

3.nacos作为配置中心–基础配置

1.建modal cloudalibaba-config-nacos-client3377
2.pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud2020</artifactId>
        <groupId>com.atguigu.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloudalibaba-config-nacos-client3377</artifactId>
    <dependencies>
        <!--nacos-config-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <!--nacos-discovery-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--web + actuator-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--一般基础配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

3.yml
SpringCloud day05学习总结_第7张图片
bootstrap.yml

server:
  port: 3377
spring:
  application:
    name: nacos-config-client
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848  #nacos作为服务注册中心
      config:
        server-addr: localhost:8848  #nacos作为配置中心
        file-extension: yaml  #指定yaml格式的配置

# ${prefix}-${spring.profile.active}.${file-extension}默认为
# ${spring.application.name}-${spring.profile.active}.${file-extension}
# nacos-config-client-dev.yaml

application.yml

spring:
  profiles:
    active: dev  #表示开发环境

4.主启动

package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class NacosConfigClientMain3377 {
    public static void main(String[] args) {
        SpringApplication.run(NacosConfigClientMain3377.class, args);
    }
}

5.业务类

@RefreshScpoe 与Cofig一样用Spring的通用API 支持动态刷新

package com.atguigu.springcloud.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RefreshScope  //支持nacos动态刷新
public class ConfigClientController {

    @Value("${config.info}")
    private String configInfo;

    @GetMapping("/config/info")
    public String getConfigInfo() {
        return configInfo;
    }
}

6.在nacos的配置列表中添加yaml文件,添加规则:
SpringCloud day05学习总结_第8张图片
SpringCloud day05学习总结_第9张图片
SpringCloud day05学习总结_第10张图片
7.测试http://localhost:3377/config/info
8.修改配置列表中的配置文件,重新访问http://localhost:3377/config/info 发现直接自动刷新

Nacos自动刷新(只要controller上写了@RefreshScope)

在这里插入图片描述

4.nacos作为配置中心–分类配置

1.问题:多环境多项目管理
SpringCloud day05学习总结_第11张图片
2.nacos图形化管理界面
SpringCloud day05学习总结_第12张图片
SpringCloud day05学习总结_第13张图片
3.在这里插入图片描述
SpringCloud day05学习总结_第14张图片
SpringCloud day05学习总结_第15张图片

三种方案加载配置

SpringCloud day05学习总结_第16张图片
1.DataID方案-----------最常用的,就是上面使用的
SpringCloud day05学习总结_第17张图片
SpringCloud day05学习总结_第18张图片
2.Group方案
1.建不同group的配置文件
SpringCloud day05学习总结_第19张图片
2.在config下增加
SpringCloud day05学习总结_第20张图片

SpringCloud day05学习总结_第21张图片
3.Namespace方案
1.新建dev/test的Namespace
SpringCloud day05学习总结_第22张图片
2.回到服务管理服务列表里查看
SpringCloud day05学习总结_第23张图片
3.按照域名配置填写
SpringCloud day05学习总结_第24张图片
4.bootstrap.yml与application.yml
读取顺序:namespace下的group中的${spring.application.name}-${spring.profile.active}.${file-extension}
SpringCloud day05学习总结_第25张图片
SpringCloud day05学习总结_第26张图片
5.测试:http://localhost:3377/config/info
得到的的确是namespace下的group中的${spring.application.name}-${spring.profile.active}.${file-extension}中的配置信息
SpringCloud day05学习总结_第27张图片

5.nacos集群和持久化配置(⭐⭐⭐⭐⭐)

官网说明

1.https://nacos.io/zh-cn/docs/cluster-mode-quick-start.html

2.对官网的翻译
SpringCloud day05学习总结_第28张图片
3.说明
按照官网的说明 我们需要mysql数据库
SpringCloud day05学习总结_第29张图片
SpringCloud day05学习总结_第30张图片
在这里插入图片描述

nacos持久化配置解释

1.nacos默认自带的是嵌入式数据库derby
https://github.com/alibaba/nacos/blob/develop/config/pom.xml
SpringCloud day05学习总结_第31张图片
因为每个nacos都自带一个derby嵌入式数据库,所以集群就会造成数据一致性问题

2.derby到MySQL切换配置步骤

①nacos-server-1.1.4\nacos\conf目录下找到sql文件nacos-mysql.sql
在mysql中执行语句sql文件的语句(要先创建数据库nacos_config 再use config)
内容:https://github.com/alibaba/nacos/blob/master/distribution/conf/nacos-mysql.sql
这样改了以后,nacos的配置将会从自带的嵌入式derby迁到MySQL

②nacos-server-1.1.4\nacos\conf目录下找到properties文件application.properties
.修改conf/application.properties文件,增加支持mysql数据源配置(目前只支持mysql),添加mysql数据源的url、用户名和密码。
如下:
spring.datasource.platform=mysql

db.num=1
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=root

③重启nacos
发现之前的yaml文件、namespace命名空间都没了,表示切换数据库成功

测试:
SpringCloud day05学习总结_第32张图片
SpringCloud day05学习总结_第33张图片

Linux版Naocs+mysql生产环境配置

1.预计需要 1个Nginx+3个nacos注册中心+1个MySQL
2.Nacos下载Linux版本
SpringCloud day05学习总结_第34张图片
https://github.com/alibaba/nacos/releases/tag/1.1.4
下载nacos-server-1.1.4.tar.qz
解压后安装

集群的配置步骤(⭐⭐⭐⭐⭐)

Linux服务器上MySQL数据库配置
1.SQL语句脚本在哪,进行copy
SpringCloud day05学习总结_第35张图片
2.去自己的MySQL下执行

application.properties配置
1.位置 命令
SpringCloud day05学习总结_第36张图片
2.内容
spring.datasource.platform=mysql

db.num=1
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=root

Linux服务器上nacos的集群配置cluster.config
1.复制cluster.config备份
SpringCloud day05学习总结_第37张图片
2.修改cluster.config内容
注意:这个IP不能写127.0.0.1,要写Linux命令 hostname -i能识别的IP
SpringCloud day05学习总结_第38张图片
编辑Nacos的启动脚本startup.sh,使它能够接受不同的启动端口
1.位置:
在这里插入图片描述
2.内容:
SpringCloud day05学习总结_第39张图片
SpringCloud day05学习总结_第40张图片
3.执行
SpringCloud day05学习总结_第41张图片

Nginx修改,由它作为负载均衡器
1.位置
SpringCloud day05学习总结_第42张图片
2.内容
SpringCloud day05学习总结_第43张图片
3.按照指定配置启动
SpringCloud day05学习总结_第44张图片

截至到此,1个Nginx+3个nacos注册中心+1个MySQL
1.测试,通过nginx访问nacos http://192.168.111.144:1111/nacos/#/login
再nacos中新建一个配置,再MySQL中能发现插入了一条数据 成功

测试
微服务cloudalibaba-provider-payment9002启动注册进入集群
SpringCloud day05学习总结_第45张图片
高可用小总结
SpringCloud day05学习总结_第46张图片

Sentinetl(取代Hystrix)

官网https://github.com/alibaba/Sentinel
中文官网https://github.com/alibaba/Sentinel/wiki/介绍
SpringCloud day05学习总结_第47张图片
下载地址https://github.com/alibaba/Sentinel/releases
SpringCloud day05学习总结_第48张图片
能干嘛
SpringCloud day05学习总结_第49张图片

1.Sentinel控制台

Sentinel由两部分组成

SpringCloud day05学习总结_第50张图片

安装步骤

1.下载(上面有)
2.运行命令
前提:java8环境OK+8080端口不被占用
命令:java -jar .\sentinel-dashboard-1.7.0.jar
3.访问Sentinel管理界面
http://localhost:8080
SpringCloud day05学习总结_第51张图片
与nacos一样套路,用户名密码均为sentinel
SpringCloud day05学习总结_第52张图片

2.初始化演示工程

1.启动nacos8848成功(startup.cmd)
2.建modal cloudalibaba-sentinel-service8401

pom


    <dependencies>
        <dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!--SpringCloud ailibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--SpringCloud ailibaba sentinel-datasource-nacos 后续做持久化用到-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>
        <!--SpringCloud ailibaba sentinel -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <!--openfeign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!-- SpringBoot整合Web组件+actuator -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--日常通用jar包配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>4.6.3</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

yml

server:
  port: 8401
spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        #Nacos注册中心
        server-addr: localhost:8848
    sentinel:
      transport:
        #配置Sentinel dashboard地址
        dashboard: localhost:8080
        #默认端口就是8719,接入8719端口被占用会自动从8719开始依次+1扫描直到找到未被占用的端口
        port: 8719
management:
  endpoints:
    web:
      exposure:
        include: '*'

主启动

package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class MainApp8401 {
    public static void main(String[] args) {
        SpringApplication.run(MainApp8401.class, args);
    }
}

业务类

package com.atguigu.springcloud.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class FlowLimitController {

    @GetMapping("/testA")
    public String testA() {
        return "-----testA";
    }
    @GetMapping("/testB")
    public String testB() {
        return "-----testB";
    }
}

3.启动Sentinel8080:运行:java -jar sentinel-dashboard-1.7.0.jar
4.启动微服务8401
5.启动后查看sentinel控制台
啥都没有,因为sentinel采用的是懒加载机制
SpringCloud day05学习总结_第53张图片
执行一次访问即可http://localhost:8401/testA
SpringCloud day05学习总结_第54张图片

3.流控规则

SpringCloud day05学习总结_第55张图片

基本介绍

SpringCloud day05学习总结_第56张图片
SpringCloud day05学习总结_第57张图片

流控模式1:直接

第一种:直接->快速失败
①QPS
表示1秒钟内查询一次就OK,超过就直接->快速失败,报默认错误:Blocked by Sentinel (flow limiting)
SpringCloud day05学习总结_第58张图片
问题:直接报默认错误,技术方面OK,但是应该要有类似fallback的兜底方法
②线程数
SpringCloud day05学习总结_第59张图片
在这里插入图片描述

流控模式2:关联

B犯错 A买单
SpringCloud day05学习总结_第60张图片
测试:用postman模拟高密集访问
在这里插入图片描述

流控模式3:链路

(还没弄懂)

流控效果1:快速失败

源码:com.alibaba.csp.sentinel.slots.block.flow.controller.DefaultController

流控效果2:预热Warm Up

公式:阈值÷coldFactor(默认是3),经过预热时长后才会到达阈值
官网:https://github.com/alibaba/Sentinel/wiki/限流—冷启动
源码:com.alibaba.csp.sentinel.slots.block.flow.controller.WarmUpController

Warm Up配置
SpringCloud day05学习总结_第61张图片

流控效果3:排队等待

SpringCloud day05学习总结_第62张图片
源码:com.alibaba.csp.sentinel.slots.block.flow.controller.RateLimiterController

5.降级规则(熔断降级)

官网

https://github.com/alibaba/Sentinel/wiki/%E7%86%94%E6%96%AD%E9%99%8D%E7%BA%A7

基本介绍

SpringCloud day05学习总结_第63张图片
进一步说明
SpringCloud day05学习总结_第64张图片

注意:sentinel断路器是没有半开状态的

降级策略实战1:RT

平均响应时间 (DEGRADE_GRADE_RT):当 1s 内持续进入 N 个请求,对应时刻的平均响应时间(秒级)均超过阈值(count,以 ms 为单位),那么在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地熔断(抛出 DegradeException)。注意 Sentinel 默认统计的 RT 上限是 4900 ms,超出此阈值的都会算作 4900 ms,若需要变更此上限可以通过启动配置项 -Dcsp.sentinel.statistic.max.rt=xxx 来配置。
SpringCloud day05学习总结_第65张图片
代码:
SpringCloud day05学习总结_第66张图片
配置:
SpringCloud day05学习总结_第67张图片
jmete压力测试:
SpringCloud day05学习总结_第68张图片
SpringCloud day05学习总结_第69张图片
测试结果:
服务熔断了
在这里插入图片描述
停止压力测试后重新访问:
在这里插入图片描述

结论:
SpringCloud day05学习总结_第70张图片

降级策略实战2:异常比例

SpringCloud day05学习总结_第71张图片

SpringCloud day05学习总结_第72张图片
代码:
SpringCloud day05学习总结_第73张图片
配置:
SpringCloud day05学习总结_第74张图片
jmeter压力测试:

在这里插入图片描述
压力测试停止后:正常报错
SpringCloud day05学习总结_第75张图片
总结:
SpringCloud day05学习总结_第76张图片

奖及策略实战3:异常数

SpringCloud day05学习总结_第77张图片
SpringCloud day05学习总结_第78张图片
代码:

    @GetMapping("/testE")
    public String testE()
    {
        log.info("testE 测试异常数");
        int age = 10/0;
        return "------testE 测试异常数";
    }

配置:
SpringCloud day05学习总结_第79张图片
测试:
5次前(包括5):正常报错
SpringCloud day05学习总结_第80张图片
5次后:熔断
在这里插入图片描述

6.热点Key限流

官网

https://github.com/alibaba/Sentinel/wiki/热点参数限流

承Hystrix启热点Key(从@HystrixCommand—>@SentinelResource)

SpringCloud day05学习总结_第81张图片

源码:

com.alibaba.csp.sentinel.slots.block.BlockException

代码:

@SentinelResource
属性value:资源名,没啥要求,除了唯一,一般是GetMapping的value去掉“/”
属性blockHandler:与Sentinel的配置不对应时的执行的函数

    @GetMapping("/testHotKey")
    @SentinelResource(value = "testHotKey",blockHandler = "deal_testHotKey")
    public String testHotKey(@RequestParam(value = "p1",required = false) String p1,
                             @RequestParam(value = "p2",required = false) String p2)
    {
        //int age = 10/0;
        return "------testHotKey";
    }
    public String deal_testHotKey (String p1, String p2, BlockException exception)
    {
        return "------deal_testHotKey,o(╥﹏╥)o";  //sentinel系统默认的提示:Blocked by Sentinel (flow limiting)
    }

配置:

注意:这第0个第1个参数看的不是URL中的第0、第1而是代码中的参数
SpringCloud day05学习总结_第82张图片
SpringCloud day05学习总结_第83张图片
在这里插入图片描述

参数例外项

SpringCloud day05学习总结_第84张图片

其他:手贱添加异常时

    @GetMapping("/testHotKey")
    @SentinelResource(value = "testHotKey",blockHandler = "deal_testHotKey")
    public String testHotKey(@RequestParam(value = "p1",required = false) String p1,
                             @RequestParam(value = "p2",required = false) String p2)
    {
        int age = 10/0;
        return "------testHotKey";
    }
    public String deal_testHotKey (String p1, String p2, BlockException exception)
    {
        return "------deal_testHotKey,o(╥﹏╥)o";  //sentinel系统默认的提示:Blocked by Sentinel (flow limiting)
    }

访问 http://localhost:8401/testHotKey?p1=a

报错:
SpringCloud day05学习总结_第85张图片
原因:因为
SpringCloud day05学习总结_第86张图片

7.系统规则(⭐⭐⭐⭐)

官网

https://github.com/alibaba/Sentinel/wiki/系统自适应限流

各配置参数说明

SpringCloud day05学习总结_第87张图片

8.@SentinelResource

按资源名称限流+后续处理

步骤:
1.启动Nacoc
2.启动Sentinel
3.modul
4.pom
5.yml
6.主启动
7.业务类

package com.atguigu.springcloud.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.atguigu.springcloud.entieies.CommonResult;
import com.atguigu.springcloud.entieies.Payment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @auther zzyy
 * @create 2020-02-25 15:04
 */
@RestController
public class RateLimitController
{
    @GetMapping("/byResource")
    @SentinelResource(value = "byResource",blockHandler = "handleException")
    public CommonResult byResource()
    {
        return new CommonResult(200,"按资源名称限流测试OK",new Payment(2020L,"serial001"));
    }
    public CommonResult handleException(BlockException exception)
    {
        return new CommonResult(444,exception.getClass().getCanonicalName()+"\t 服务不可用");
    }
}

7.Sentinel配置流控规则
SpringCloud day05学习总结_第88张图片
8.额外问题:微服务关闭,Sentinel控制台刷新,流控规则消失-----------临时的

按URL地址限流+后续处理

1.通过访问URL地址限流,返回Sentinel自带的默认限流处理信息
2.业务类

    @GetMapping("/rateLimit/byUrl")
    @SentinelResource(value = "byUrl")
    public CommonResult byUrl()
    {
        return new CommonResult(200,"按url限流测试OK",new Payment(2020L,"serial002"));
    }

上面两个主要讲了既可以用@GetMapping("/rateLimit/byUrl")中URL来配,也可以用@SentinelResource(value = “byUrl”)中的资源名来配

注意:此时的流控规则的资源名要加“/”了
SpringCloud day05学习总结_第89张图片

兜底方案面临的问题(和豪猪哥Hystrix一样)

SpringCloud day05学习总结_第90张图片
https://editor.csdn.net/md?articleId=106291288#_1247

客户自定义限流处理逻辑

业务类:


    @GetMapping("/rateLimit/customerBlockHandler")
    @SentinelResource(value = "customerBlockHandler",
            blockHandlerClass = CustomerBlockHandler.class,
            blockHandler = "handlerException2")
    public CommonResult customerBlockHandler()
    {
        return new CommonResult(200,"按客戶自定义",new Payment(2020L,"serial003"));
    }

与豪猪哥Hystrix一样,方法的返回值要一样但参数的要多有一个BlockException exception(所有blockHandle都要多一个BlockException exception)*

package com.atguigu.springcloud.myhandler;

import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.atguigu.springcloud.entieies.CommonResult;

/**
 * @auther zzyy
 * @create 2020-02-25 15:32
 */
public class CustomerBlockHandler
{
    public static CommonResult handlerException(BlockException exception)
    {
        return new CommonResult(4444,"按客戶自定义,global handlerException----1");
    }
    public static CommonResult handlerException2(BlockException exception)
    {
        return new CommonResult(4444,"按客戶自定义,global handlerException----2");
    }
}

进一步说明:
SpringCloud day05学习总结_第91张图片

更多注解属性说明

https://github.com/alibaba/Sentinel/wiki/注解支持
SpringCloud day05学习总结_第92张图片
Sentinel三个核心API(了解)
1.SphU定义资源
2.Tracer定义统计
3.ContetxUtil定义上下文

9.服务熔断功能

总:sentinel整合Ribbon、OpenFeign、fallback

Ribbon系列(没讲整合Ribbon不过OpenFeign也整合了Ribbon)

SpringCloud day05学习总结_第93张图片
1.启动Nacos+Sentinel
2.新建cloudalibaba-provider-payment9003\9004两个服务类
3.pom

    <dependencies>
        <!--SpringCloud ailibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!-- SpringBoot整合Web组件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--日常通用jar包配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

4.yml

server:
  port: 9003

spring:
  application:
    name: nacos-payment-provider
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #配置Nacos地址

management:
  endpoints:
    web:
      exposure:
        include: '*'

5.主启动

package com.atguigu.springcloud.alibaba;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

/**
 * @auther zzyy
 * @create 2020-02-25 16:10
 */
@SpringBootApplication
@EnableDiscoveryClient
public class PaymentMain9003
{
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain9003.class, args);
    }
}

6.业务类

package com.atguigu.springcloud.alibaba.controller;

import com.atguigu.springcloud.entieies.CommonResult;
import com.atguigu.springcloud.entieies.Payment;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;

/**
 * @auther zzyy
 * @create 2020-02-25 16:11
 */
@RestController
public class PaymentController
{
    @Value("${server.port}")
    private String serverPort;

    public static HashMap<Long,Payment> hashMap = new HashMap<>();
    static
    {
        hashMap.put(1L,new Payment(1L,"28a8c1e3bc2742d8848569891fb42181"));
        hashMap.put(2L,new Payment(2L,"bba8c1e3bc2742d8848569891ac32182"));
        hashMap.put(3L,new Payment(3L,"6ua8c1e3bc2742d8848569891xt92183"));
    }

    @GetMapping(value = "/paymentSQL/{id}")
    public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id)
    {
        Payment payment = hashMap.get(id);
        CommonResult<Payment> result = new CommonResult(200,"from mysql,serverPort:  "+serverPort,payment);
        return result;
    }



}

7.消费微服务cloudalibaba-consumer-nacos-order84
8.pom,yml,主启动
9.业务类
①RestTemplate

package com.atguigu.springcloud.alibaba.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * @auther zzyy
 * @create 2020-02-25 16:06
 */
@Configuration
public class ApplicationContextConfig
{
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate()
    {
        return new RestTemplate();
    }
}

②controller

package com.atguigu.springcloud.alibaba.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.atguigu.springcloud.alibaba.service.PaymentService;
import com.atguigu.springcloud.entieies.CommonResult;
import com.atguigu.springcloud.entieies.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

/**
 * @auther zzyy
 * @create 2020-02-25 16:05
 */
@RestController
@Slf4j
public class CircleBreakerController
{
    public static final String SERVICE_URL = "http://nacos-payment-provider";

    @Resource
    private RestTemplate restTemplate;

    @RequestMapping("/consumer/fallback/{id}")
    //@SentinelResource(value = "fallback") //没有配置
    //@SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只负责业务异常
    //@SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只负责sentinel控制台配置违规
    @SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler",
            exceptionsToIgnore = {IllegalArgumentException.class})
    public CommonResult<Payment> fallback(@PathVariable Long id)
    {
        CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class,id);

        if (id == 4) {
            throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常....");
        }else if (result.getData() == null) {
            throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常");
        }

        return result;
    }
    //本例是fallback
    public CommonResult handlerFallback(@PathVariable  Long id,Throwable e) {
        Payment payment = new Payment(id,"null");
        return new CommonResult<>(444,"兜底异常handlerFallback,exception内容  "+e.getMessage(),payment);
    }
    //本例是blockHandler
    public CommonResult blockHandler(@PathVariable  Long id,BlockException blockException) {
        Payment payment = new Payment(id,"null");
        return new CommonResult<>(445,"blockHandler-sentinel限流,无此流水: blockException  "+blockException.getMessage(),payment);
    }

    //==================OpenFeign
    @Resource
    private PaymentService paymentService;

    @GetMapping(value = "/consumer/paymentSQL/{id}")
    public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id)
    {
        return paymentService.paymentSQL(id);
    }
}

目的:
fallback属性管运行时异常
blockHandler管配置违规

exceptionsToIgnore忽略异常,不在兜底方案
测试地址: http://localhost:84/consumer/fallback/1

一、controller的@SentinelResource没有任何配置
给客户的error界面,不友好
SpringCloud day05学习总结_第94张图片
二、controller的@SentinelResource只配置fallbcak
运行时出错,友好了
在这里插入图片描述
三、controller的@SentinelResource只配置blockHandle属性
只管配置违规,不管是否运行时异常
四、fallback和blockHandle都配置
很有可能会冲突,呐最后听谁的?
SpringCloud day05学习总结_第95张图片
五、忽略属性exceptionsToIgnore
SpringCloud day05学习总结_第96张图片

OpenFeign系列

1.修改84模块
84消费者调用提供者9003
Feign组件一般在消费者一端
2.pom

        <!--SpringCloud openfeign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

3.yml

# 激活Sentinel对Feign的支持
feign:
  sentinel:
    enabled: true

之间和豪猪哥整合是

feign:
  Hystrix:
    enabled: true

4.主启动
多个@EnableFeignClients
5.业务类
众所周知,OpenFeign是接口+实现类
service接口

package com.atguigu.springcloud.alibaba.service;

import com.atguigu.springcloud.entieies.CommonResult;
import com.atguigu.springcloud.entieies.Payment;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * @auther zzyy
 * @create 2020-02-25 18:15
 */
@FeignClient(value = "nacos-payment-provider",fallback = PaymentFallbackService.class)
public interface PaymentService
{
    @GetMapping(value = "/paymentSQL/{id}")
    public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id);
}

sevice接口实现类
切记@Componment

package com.atguigu.springcloud.alibaba.service;

import com.atguigu.springcloud.entieies.CommonResult;
import com.atguigu.springcloud.entieies.Payment;
import org.springframework.stereotype.Component;

/**
 * @auther zzyy
 * @create 2020-02-25 18:30
 */
@Component
public class PaymentFallbackService implements PaymentService
{
    @Override
    public CommonResult<Payment> paymentSQL(Long id)
    {
        return new CommonResult<>(44444,"服务降级返回,---PaymentFallbackService",new Payment(id,"errorSerial"));
    }
}

controller

    //==================OpenFeign
    @Resource
    private PaymentService paymentService;

    @GetMapping(value = "/consumer/paymentSQL/{id}")
    public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id)
    {
        return paymentService.paymentSQL(id);
    }

测试: http://localhost:84/consumer/paymentSQL/1

熔断框架对比

SpringCloud day05学习总结_第97张图片
在这里插入图片描述

10.规则持久化

一旦重启sentinel客户端或者微服务modal,sentinel规则将消失,生产环境想要将配置规则持久化

怎么玩

将限流规则保存到Nacos中(数据库、文件等持久化文件都行,但是官方要求Nacos),(以8401modal为例子)只要刷新8401某个rest地址,sentinel控制台的流控规则就能看到,只要Nacos里面的配置不删除,针对8401上sentinel上的流控规则持久有效

步骤

1.pom

        <!--SpringCloud ailibaba sentinel-datasource-nacos 后续做持久化用到-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>

2.yml

server:
  port: 8401
spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        #Nacos注册中心
        server-addr: localhost:8848
    sentinel:
      transport:
        #配置Sentinel dashboard地址
        dashboard: localhost:8080
        #默认端口就是8719,接入8719端口被占用会自动从8719开始依次+1扫描直到找到未被占用的端口
        port: 8719
      datasource:
        dsl:
          nacos:
            server-addr: loalhost://8848
            dataId: cloudalibaba-sentinel-service
            groupId: DEFAULT_GROUP
            data-type: json 
            rule-type: flow
management:
  endpoints:
    web:
      exposure:
        include: '*'

SpringCloud day05学习总结_第98张图片
3.新增Nacos业务规则
SpringCloud day05学习总结_第99张图片

[
    {
        "resource": "/rateLimit/byUrl",
        "limitApp": "default",
        "grade": 1,
        "count": 1,
        "strategy": 0,
        "controlBehavior": 0,
        "clusterMode": false
    }
]

SpringCloud day05学习总结_第100张图片
4.启动8401后刷新sentinel发现业务规则又有了

5.快速访问测试 http://localhost:8401/rateLimit/byUrl

SpringCloud day05学习总结_第101张图片
6.停止8401再看sentinel
SpringCloud day05学习总结_第102张图片
7.重启8401再看sentinel
测试http://localhost:8401/rateLimit/byUrl 降级规则等业务规则又有了

Seata( @GlobalTransactional(name = “唯一”,rollbackFor = 某个异常.class))

分布式之前:数据一致性能保证
分布式之后:
SpringCloud day05学习总结_第103张图片

1.简介

官网:http://seata.io/zh-cn,

分布式处理过程分为一ID+三组件模型
一ID:Transaction ID XID:全局唯一的事务ID
三组件:

TC - 事务协调者 维护全局和分支事务的状态,驱动全局事务提交或回滚。

TM - 事务管理器 定义全局事务的范围:开始全局事务、提交或回滚全局事务。

RM - 资源管理器 管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。

处理过程
SpringCloud day05学习总结_第104张图片
下载:https://github.com/seata/seata/releases

怎么玩:
本地@Transactional
全局@GrobalTransactional
SpringCloud day05学习总结_第105张图片

2.Seata的安装

1.修改conf目录下的file.conf配置文件
①先备份file.conf文件
②主要修改:自定义事务组名称+事务日志存储模式为db+数据库连接信息
③service模块
SpringCloud day05学习总结_第106张图片
store模块
SpringCloud day05学习总结_第107张图片
SpringCloud day05学习总结_第108张图片
④在MySQL只建数据库seata
⑤在seata数据库中建表,间表的
⑥修改config目录下的registry.conf
SpringCloud day05学习总结_第109张图片
⑦启动nacos
⑧启动seata

3.订单/库存/账户业务数据库准备

1.以下演示要保证先启动Nacos在启动Seata
2.分布式事务业务说明
SpringCloud day05学习总结_第110张图片
3.创建业务数据库
4.按照上面3个数据库创建对应的表
SpringCloud day05学习总结_第111张图片
SpringCloud day05学习总结_第112张图片
SpringCloud day05学习总结_第113张图片
5.按照上述3库分别创建对应回滚日志表
订单-库存-账户3个库下都需要建各自的回滚日志表:
conf目录下的db_undo_log.sql

4.订单/库存/账户业务微服务准备

业务需求:下订单-》减库存-》改余额-》改(订单)状态
(暂时写到这)

    @Override
    @GlobalTransactional(name = "fsp-create-order",rollbackFor = Exception.class)
    public void create(Order order) {
        //1.新建订单
        log.info("------>开始创建订单");
        orderDao.create(order);

        //2.扣减库存
        log.info("------>的单位服务调用库存,做扣减count");
        storageService.decrease(order.getProductId(), order.getCount());
        log.info("------>的单位服务调用库存,做扣减end");

        //3.扣减账户
        log.info("------>的单位服务调用账户,做扣减money");
        accountService.decrease(order.getUserId(),order.getMoney());
        log.info("------>的单位服务调用账户,做扣减end");

        //4.修改订单状态
        log.info("------>修改订单状态开始");
        orderDao.update(order.getUserId(),0);
        log.info("------>修改订单状态结束");

        log.info("------>下单结束");
    }

SpringCloud day05学习总结_第114张图片
SpringCloud day05学习总结_第115张图片

SpringCloud day05学习总结_第116张图片

你可能感兴趣的:(SpringCloud day05学习总结)