栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringCloud学习第四天 尚硅谷版本

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringCloud学习第四天 尚硅谷版本

SpringCloud学习
  • 17 SpringCloud Alibaba入门简介
  • 18 SpringCloud Alibaba Nacos服务注册和配置中心
    • 18.1 安装并运行 Nacos
    • 18.2 Nacos作为服务注册中心演示
      • 18.2.1 基于Nacos的服务提供者
      • 18.2.2 基于Nacos的服务消费者
    • 18.3 Nacos作为服务配置中心演示
      • 18.3.1 读取配置模块建立
      • 18.3.2 nacos配置中心文件建立
        • 18.3.2.1 根据id配置
        • 18.3.2.2 Group区分文件
        • 18.3.2.3 Namespace方案
    • 18.4 Nacos集群和持久化配置(重要)
      • 18.4.1 windows的持久化
      • 18.4.2 Linux版Nacos+MySQL生产环境配置
  • 19 SpringCloud Alibabasentinel实现熔断与限流
    • 19.1 实现服务监控
    • 19.2 实现控流
      • 19.2.1控流模式功能配置说明如下
      • 19.2.1 流控效果说明如下
    • 19.3 降级规则
      • 19.3.1 RT降级策略
      • 19.3.2 异常比例降级
      • 19.3.3 异常数降级
    • 19.4 热点key限流
      • 19.4.1 初级用法
      • 19.4.1 高级用法
    • 19.5 系统规则
    • 19.6 @SentinelResource注解
      • 19.6.1 资源名限流
      • 19.6.2 客户自定义限流处理逻辑
      • 19.6.3 更多注解属性说明
    • 19.7 服务熔断功能
      • 19.7.1 基于ribbon
      • 19.7.1 基于feign
    • 19.8 规则持久化

17 SpringCloud Alibaba入门简介

能干什么?

服务限流降级:默认支持 Servlet、Feign、RestTemplate、Dubbo 和 RocketMQ 限流降级功能的接入,可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级 Metrics 监控。
服务注册与发现:适配 Spring Cloud 服务注册与发现标准,默认集成了 Ribbon 的支持。
分布式配置管理:支持分布式系统中的外部化配置,配置更改时自动刷新。
消息驱动能力:基于 Spring Cloud Stream 为微服务应用构建消息驱动能力。
阿里云对象存储:阿里云提供的海量、安全、低成本、高可靠的云存储服务。支持在任何应用、任何时间、任何地点存储和访问任意类型的数据。
分布式任务调度:提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。同时提供分布式的任务执行模型,如网格任务。网格任务支持海量子任务均匀分配到所有 Worker(schedulerx-client)上执行。

去哪下?

https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md

怎么玩

18 SpringCloud Alibaba Nacos服务注册和配置中心

18.1 安装并运行 Nacos

首先在官网下载 Nacos 1.1.4 这里用的1.1.4

https://github.com/alibaba/nacos/releases/tag/1.1.4

18.2 Nacos作为服务注册中心演示

官网文档
https://spring-cloud-alibaba-group.github.io/github-pages/greenwich/spring-cloud-alibaba.html#_spring_cloud_alibaba_nacos_config

18.2.1 基于Nacos的服务提供者

新建模块 cloudalibaba-provider-payment9001 和 9002
其中9002完全参照9001 只是端口不一样

这里因为我们是子工程 所以我们需要在父工程中引入对应的版本管理依赖

			 
                com.alibaba.cloud
                spring-cloud-alibaba-dependencies
                2.1.0.RELEASE
                pom
                import
            


然后是当前pom


        
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-nacos-discovery
        
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-actuator
        
        
        
            org.springframework.boot
            spring-boot-devtools
            runtime
            true
        
        
            org.projectlombok
            lombok
            true
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    

yaml

server:
  port: 9001

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

management:
  endpoints:
    web:
      exposure:
        include: '*' #暴露监控

主启动 不要忘记加上@EnableDiscoveryClient注解

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

简单业务类

@RestController
public class PaymentController
{
    @Value("${server.port}")
    private String serverPort;

    @GetMapping(value = "/payment/nacos/{id}")
    public String getPayment(@PathVariable("id") Integer id)
    {
        return "nacos registry, serverPort: "+ serverPort+"t id"+id;
    }
}

当我们把两个模块都建好 在配置中心就可以看到对应的信息

18.2.2 基于Nacos的服务消费者

Nacos自动集成了负载均衡

新建模块 cloudalibaba-consumer-nacos-order83
pom

 
        
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-nacos-discovery
        
        
        
            com.atguigu.springcloud
            cloud-api-commons
            ${project.version}
        
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-actuator
        
        
        
            org.springframework.boot
            spring-boot-devtools
            runtime
            true
        
        
            org.projectlombok
            lombok
            true
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    

yaml

server:
  port: 83


spring:
  application:
    name: nacos-order-consumer
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #nasos的地址


#消费者将要去访问的微服务名称(注册成功进nacos的微服务提供者)
service-url:
  nacos-user-service: http://nacos-payment-provider  #访问哪个微服务

主启动 不要忘记加上 @EnableDiscoveryClient 注解

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

因为这个是消费者端 要用RestTemplate 实例 所以多一个配置类
因为有负载均衡 不要忘记加上 @LoadBalanced注解

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

controller接口

@RestController
public class OrderNacosController{
    @Resource
    private RestTemplate restTemplate;

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

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

最后调用这个消费者 会发现两个服务端口 轮流提供服务

18.3 Nacos作为服务配置中心演示 18.3.1 读取配置模块建立

新建模块 cloudalibaba-config-nacos-client3377
pom

    
        
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-nacos-config
        
        
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-nacos-discovery
        
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-actuator
        
        
        
            org.springframework.boot
            spring-boot-devtools
            runtime
            true
        
        
            org.projectlombok
            lombok
            true
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    

两个yaml
bootstrap.yaml

# nacos配置
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格式的配置
        
# ${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}

application.yaml

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

主启动

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

controller接口
因为这里用到了nacos当注册中心 所以需要加上 @RefreshScope 注解来进行 自动刷新

@RestController
@RefreshScope //在控制器类加入@RefreshScope注解使当前类下的配置支持Nacos的动态刷新功能。
public class ConfigClientController
{
    @Value("${config.info}")
    private String configInfo;

    @GetMapping("/config/info")
    public String getConfigInfo() {
        return configInfo;
    }
}
 
18.3.2 nacos配置中心文件建立

怎么建立呢
文件的命名也有讲究 如下

如图下图 之前我们在两个文件中 写有配置

问题:

问题1:
实际开发中,通常一个系统会准备
dev开发环境
test测试环境
prod生产环境。
如何保证指定环境启动时服务能正确读取到Nacos上相应环境的配置文件呢?

问题2:
一个大型分布式微服务系统会有很多微服务子项目,
每个微服务项目又都会有相应的开发环境、测试环境、预发环境、正式环境…
那怎么对这些微服务配置进行管理呢?



Namespace+Group+Data ID三者关系?为什么这么设计?

1 是什么
类似Java里面的package名和类名
最外层的namespace是可以用于区分部署环境的,Group和DataID逻辑上区分两个目标对象。
2 三者情况

默认情况:
Namespace=public,Group=DEFAULT_GROUP, 默认Cluster是DEFAULT

Nacos默认的命名空间是public,Namespace主要用来实现隔离。
比方说我们现在有三个环境:开发、测试、生产环境,我们就可以创建三个Namespace,不同的Namespace之间是隔离的。

Group默认是DEFAULT_GROUP,Group可以把不同的微服务划分到同一个分组里面去

Service就是微服务;一个Service可以包含多个Cluster(集群),Nacos默认Cluster是DEFAULT,Cluster是对指定微服务的一个虚拟划分。
比方说为了容灾,将Service微服务分别部署在了杭州机房和广州机房,
这时就可以给杭州机房的Service微服务起一个集群名称(HZ),
给广州机房的Service微服务起一个集群名称(GZ),还可以尽量让同一个机房的微服务互相调用,以提升性能。

最后是Instance,就是微服务的实例。

18.3.2.1 根据id配置


新建一个文件 让他的名字和之前的有所差别
一个-dev 一个-test

怎么使用呢? 只需要修改active即可

18.3.2.2 Group区分文件


新建一个分组

在对应的配置类上加上group属性 然后输入对应的group即可

18.3.2.3 Namespace方案

新建一个命名空间 根据他的 进行配置

在application中配置空间id

18.4 Nacos集群和持久化配置(重要)

目前持久化只支持mysql


在没有配置持久化时 默认使用 derby数据库 怎么切换?

18.4.1 windows的持久化

derby到mysql切换配置步骤

在mysql数据库中 先创建好nacos_config数据库
然后执行脚本




CREATE TABLE `config_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(255) DEFAULT NULL,
  `content` longtext NOT NULL COMMENT 'content',
  `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
  `gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
  `src_user` text COMMENT 'source user',
  `src_ip` varchar(20) DEFAULT NULL COMMENT 'source ip',
  `app_name` varchar(128) DEFAULT NULL,
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
  `c_desc` varchar(256) DEFAULT NULL,
  `c_use` varchar(64) DEFAULT NULL,
  `effect` varchar(64) DEFAULT NULL,
  `type` varchar(64) DEFAULT NULL,
  `c_schema` text,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info';





CREATE TABLE `config_info_aggr` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(255) NOT NULL COMMENT 'group_id',
  `datum_id` varchar(255) NOT NULL COMMENT 'datum_id',
  `content` longtext NOT NULL COMMENT '内容',
  `gmt_modified` datetime NOT NULL COMMENT '修改时间',
  `app_name` varchar(128) DEFAULT NULL,
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfoaggr_datagrouptenantdatum` (`data_id`,`group_id`,`tenant_id`,`datum_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='增加租户字段';






CREATE TABLE `config_info_beta` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(128) NOT NULL COMMENT 'group_id',
  `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
  `content` longtext NOT NULL COMMENT 'content',
  `beta_ips` varchar(1024) DEFAULT NULL COMMENT 'betaIps',
  `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
  `gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
  `src_user` text COMMENT 'source user',
  `src_ip` varchar(20) DEFAULT NULL COMMENT 'source ip',
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_beta';





CREATE TABLE `config_info_tag` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(128) NOT NULL COMMENT 'group_id',
  `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
  `tag_id` varchar(128) NOT NULL COMMENT 'tag_id',
  `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
  `content` longtext NOT NULL COMMENT 'content',
  `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
  `gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
  `src_user` text COMMENT 'source user',
  `src_ip` varchar(20) DEFAULT NULL COMMENT 'source ip',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_tag';





CREATE TABLE `config_tags_relation` (
  `id` bigint(20) NOT NULL COMMENT 'id',
  `tag_name` varchar(128) NOT NULL COMMENT 'tag_name',
  `tag_type` varchar(64) DEFAULT NULL COMMENT 'tag_type',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(128) NOT NULL COMMENT 'group_id',
  `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
  `nid` bigint(20) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`nid`),
  UNIQUE KEY `uk_configtagrelation_configidtag` (`id`,`tag_name`,`tag_type`),
  KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_tag_relation';





CREATE TABLE `group_capacity` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `group_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Group ID,空字符表示整个集群',
  `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
  `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
  `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
  `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数,,0表示使用默认值',
  `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
  `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
  `gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_group_id` (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='集群、各Group容量信息表';





CREATE TABLE `his_config_info` (
  `id` bigint(64) unsigned NOT NULL,
  `nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `data_id` varchar(255) NOT NULL,
  `group_id` varchar(128) NOT NULL,
  `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
  `content` longtext NOT NULL,
  `md5` varchar(32) DEFAULT NULL,
  `gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00',
  `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00',
  `src_user` text,
  `src_ip` varchar(20) DEFAULT NULL,
  `op_type` char(10) DEFAULT NULL,
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
  PRIMARY KEY (`nid`),
  KEY `idx_gmt_create` (`gmt_create`),
  KEY `idx_gmt_modified` (`gmt_modified`),
  KEY `idx_did` (`data_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='多租户改造';






CREATE TABLE `tenant_capacity` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Tenant ID',
  `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
  `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
  `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
  `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数',
  `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
  `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
  `gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='租户容量信息表';


CREATE TABLE `tenant_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `kp` varchar(128) NOT NULL COMMENT 'kp',
  `tenant_id` varchar(128) default '' COMMENT 'tenant_id',
  `tenant_name` varchar(128) default '' COMMENT 'tenant_name',
  `tenant_desc` varchar(256) DEFAULT NULL COMMENT 'tenant_desc',
  `create_source` varchar(32) DEFAULT NULL COMMENT 'create_source',
  `gmt_create` bigint(20) NOT NULL COMMENT '创建时间',
  `gmt_modified` bigint(20) NOT NULL COMMENT '修改时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),
  KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info';

CREATE TABLE users (
	username varchar(50) NOT NULL PRIMARY KEY,
	password varchar(500) NOT NULL,
	enabled boolean NOT NULL
);

CREATE TABLE roles (
	username varchar(50) NOT NULL,
	role varchar(50) NOT NULL
);

INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);

INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');

再nacos-server-1.1.4nacosconf目录下找到application.properties
需要注意的是 有可能 高版本的mysql和低版本的nacos不匹配 需要更改对应版本

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=123456      //数据库密码

然后重启 nacos 命令

startup.cmd -m standalone

最后我们就发现更改的配置文件 就可以存储到mysql中了

18.4.2 Linux版Nacos+MySQL生产环境配置

预计需要,1个Nginx+3个nacos注册中心+1个mysql+jdk8

在官网下载linux版本的nacos

https://github.com/alibaba/nacos/releases/tag/1.1.4

在配置nacos时 需要保证虚拟机上有 mysql5.6.5及以上版本的mysql
mysql安装可以参考如下文章

https://www.cnblogs.com/dingguofeng/p/13814645.html

jdk安装参考如下文章

https://blog.csdn.net/pdsu161530247/article/details/81582980

在linux的根目录创建一个 mynacos 文件夹 将nacos文件解压到这个文件夹
然后打开mysql 运行sql脚本文件
文件目录如下:
sql文件目录
防止sql失败 可以在这个sql文件的最上方 加上下面两句sql

create database `config_info`;
use `config_info`;

编辑 /mynacos/nacos/conf/application.properties 文件
在最底下加上如下语句

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=123456

搭建一个nacos的集群
进入 /mynacos/nacos/conf目录创建一个cluster.conf 文件 然后添加内容
内容为 前面的ip 是在linux上用ip add查看的ens33 这张网卡的ip 端口号固定

完成过后
编辑Nacos的启动脚本startup.sh,使它能够接受不同的启动端口
/mynacos/nacos/bin 目录下有startup.sh 修改内容 如下图

修改完成后启动nacoss集群

./startup.sh -p 3333/4444/5555

如果遇到权限不足执行以下命令

chmod +x /mynacos/nacos/bin/.

然后修改nigex的配置
修改 nigex/config/nigex.config文件
修改如下:

启动nigex

然后我们在本机上测试通过nginx访问nacos

http://192.168.79.131:1111/nacos/#/login

最后将服务注册到集群中
修改yml配置即可

19 SpringCloud Alibabasentinel实现熔断与限流

这个组件 有点类似于Hystrix
下载地址 这里用的是1.7.0版本

https://github.com/alibaba/Sentinel/releases


注意不能把包放在桌面启动 会导致服务运行失败
安装并且运行好过后 我们打开nacos 在nacos的安装目录下的bin目录有cmd直接执行即可

19.1 实现服务监控

创建模块cloudalibaba-sentinel-service8401
pom

    
        
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-nacos-discovery
        
        
        
            com.alibaba.csp
            sentinel-datasource-nacos
        
        
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-sentinel
        
        
        
            org.springframework.cloud
            spring-cloud-starter-openfeign
        
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-actuator
        
        
        
            org.springframework.boot
            spring-boot-devtools
            runtime
            true
        
        
            cn.hutool
            hutool-all
            4.6.3
        
        
            org.projectlombok
            lombok
            true
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        

    


 
 

yaml

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开始依次+1扫描,直至找到未被占用的端口
        port: 8719

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

主启动

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

controller

@RestController
public class FlowLimitController
{

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

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

然后我们启动这个微服务
但是发现sentinel中并没有 因为他是懒加载机制 需要自己访问一遍即可看到

19.2 实现控流

配置的选项图如下

19.2.1控流模式功能配置说明如下



19.2.1 流控效果说明如下



19.3 降级规则

官网

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

Sentinel 熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,
让请求快速失败,避免影响到其它的资源而导致级联错误。

当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出 DegradeException)。

Sentinel的断路器是没有半开状态的
半开的状态系统自动去检测是否请求有异常,
没有异常就关闭断路器恢复使用,
有异常则继续打开断路器不可用。具体可以参考Hystrix

19.3.1 RT降级策略

根据访问量来进行降级 需要注意的是 触发降级的条件就是 线程数>5&&请求时间>200ms 就会触发降级

19.3.2 异常比例降级

参考上面的


19.3.3 异常数降级


19.4 热点key限流

什么是热点
何为热点
热点即经常访问的数据,很多时候我们希望统计或者限制某个热点数据中访问频次最高的TopN数据,并对其访问进行限流或者其它操作
官网说明

https://github.com/alibaba/Sentinel/wiki/%E7%83%AD%E7%82%B9%E5%8F%82%E6%95%B0%E9%99%90%E6%B5%81

会用到一个注解 SentinelResource
在这个注解类似于 HystrixCommand 的注解
主要是用于服务出错后的兜底方法

源码可参考这个类

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

19.4.1 初级用法

怎么进行热点限流呢

需要注意的是 我们不能在接口限流 必须是限制 SentinelResource注解里面设置的value 属性

然后当我们 访问这个点 并且带上p1参数时 如果超过了限流 就会报错 就会触发SentinelResource注解里面设置的blockHandler属性里的方法 这个方法就是兜底方法 但是不要忘记在这个方法参数里加上
BlockException exception这个参数 不然会报错

19.4.1 高级用法

当我们想在p1参数 为某些值时 不对其进行限制怎么办呢?

19.5 系统规则

官网说明

https://github.com/alibaba/Sentinel/wiki/%E7%B3%BB%E7%BB%9F%E8%87%AA%E9%80%82%E5%BA%94%E9%99%90%E6%B5%81

简单一点就是 系统级别的限制

主要有以下配置

19.6 @SentinelResource注解 19.6.1 资源名限流

在8401上面 引入一个自己之前写的包

 
        
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-nacos-discovery
        
        
            com.atguigu.springcloud
            cloud-api-commons
        
        
        
            com.alibaba.csp
            sentinel-datasource-nacos
        
        
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-sentinel
        
        
        
            org.springframework.cloud
            spring-cloud-starter-openfeign
        
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-actuator
        
        
        
            org.springframework.boot
            spring-boot-devtools
            runtime
            true
        
        
            cn.hutool
            hutool-all
            4.6.3
        
        
            org.projectlombok
            lombok
            true
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    

重新写一个controller类

@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 服务不可用");
    }
}

然后启动这个服务

我们根据资源名控流
上面的配置表示 表示1秒钟内查询次数大于1,就跑到我们自定义的处流,限流
对应填写的信息如下

但是这样的用法存在什么问题呢

1 系统默认的,没有体现我们自己的业务要求。
2 依照现有条件,我们自定义的处理方法又和业务代码耦合在一块,不直观。
3 每个业务方法都添加一个兜底的,那代码膨胀加剧。
4 全局统一的处理方法没有体现。

19.6.2 客户自定义限流处理逻辑

创建com.atguigu.springcloud.myhandler.CustomerBlockHandler 类用于自定义限流处理逻辑

public class CustomerBlockHandler{

    //返回參數 需要和被兜底的方法  返回參數一致      並且要有BlockException這個類
    public static CommonResult handleException(BlockException exception){
        return new CommonResult(2020,"自定义的限流处理信息......CustomerBlockHandler1");
    }

    //返回參數 需要和被兜底的方法  返回參數一致      並且要有BlockException這個類
    public static CommonResult handleException1(BlockException exception){
        return new CommonResult(2020,"自定义的限流处理信息......CustomerBlockHandler2");
    }
}

然后在需要兜底的方法上加上注解

    @GetMapping("/rateLimit/customerBlockHandler")
    //value属性表示一个在sentinel上表示的一个id
    // blockHandlerClass表示兜底的类
    // blockHandler表示类里的哪个方法的方法名
    @SentinelResource(value = "customerBlockHandler",
            blockHandlerClass = CustomerBlockHandler.class, blockHandler = "handleException1")
    public CommonResult customerBlockHandler()
    {
        return new CommonResult(200,"按客户自定义限流处理逻辑");
    }

对其进行限流过后 如果触发降级等操作 就会由我们自己设置的方法兜底

进一步对配置的说明给

19.6.3 更多注解属性说明

三张图一样

19.7 服务熔断功能 19.7.1 基于ribbon

sentinel整合ribbon+openFeign+fallback
新建两个服务提供者 cloudalibaba-provider-payment9003/9004两个一样的做法
pom

    
        
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-nacos-discovery
        
        
            com.atguigu.springcloud
            cloud-api-commons
            ${project.version}
        
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-actuator
        
        
        
            org.springframework.boot
            spring-boot-devtools
            runtime
            true
        
        
            org.projectlombok
            lombok
            true
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    

yaml

server:
  port: 9004

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

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

主启动 需要加上 @EnableDiscoveryClient注解

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

简单业务类

@RestController
public class PaymentController{
    @Value("${server.port}")
    private String serverPort;

    public static HashMap 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 paymentSQL(@PathVariable("id") Long id)
    {
        Payment payment = hashMap.get(id);
        CommonResult result = new CommonResult(200,"from mysql,serverPort:  "+serverPort,payment);
        return result;
    }   
}

最后我们启动这个类 测试一下 测试地址 http://localhost:9004/paymentSQL/1

然后创建一个消费者 cloudalibaba-consumer-nacos-order84

pom


        
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-nacos-discovery
        
        
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-sentinel
        
        
        
            com.atguigu.springcloud
            cloud-api-commons
            ${project.version}
        
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-actuator
        
        
        
            org.springframework.boot
            spring-boot-devtools
            runtime
            true
        
        
            org.projectlombok
            lombok
            true
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    

yaml

server:
  port: 84


spring:
  application:
    name: nacos-order-consumer
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        #配置Sentinel dashboard地址
        dashboard: localhost:8080
        #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
        port: 8719


#消费者将要去访问的微服务名称(注册成功进nacos的微服务提供者)
service-url:
  nacos-user-service: http://nacos-payment-provider

主启动

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

业务类

@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",
            fallback = "handlerFallback", //出现runtime异常 的兜底方法
            blockHandler = "blockHandler") //服务被降级或者熔断的方法
    public CommonResult fallback(@PathVariable Long id)    {
        CommonResult result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class,id);
        if (id == 4) {
            throw new IllegalArgumentException ("非法参数异常....");
        }else if (result.getData() == null) {
            throw new NullPointerException ("NullPointerException,该ID没有对应记录");
        }
        return result;
    }

    public CommonResult handlerFallback(@PathVariable  Long id,Throwable e) {
        Payment payment = new Payment(id,"null");
        return new CommonResult<>(444,"fallback,无此流水,exception  "+e.getMessage(),payment);
    }

    public CommonResult blockHandler(@PathVariable  Long id, BlockException blockException) {
        Payment payment = new Payment(id,"null");
        return new CommonResult<>(445,"blockHandler-sentinel限流,无此流水: blockException  "+blockException.getMessage(),payment);
    }
}

这里用的是robbin 所以要用到 RestTemplate 实例

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

熔断的策略主要看主启动类上的 SentinelResource注解

@SentinelResource(value = "fallback",
            fallback = "handlerFallback", //出现runtime异常 的兜底方法
            blockHandler = "blockHandler") //服务被降级或者熔断的方法
19.7.1 基于feign

修改cloudalibaba-consumer-nacos-order84模块
添加feign的文件

        
            org.springframework.cloud
            spring-cloud-starter-openfeign
        

在yaml里面设置暴露监控和打开sentinel对feign的支持

management:
  endpoints:
    web:
      exposure:
        include: '*'
# 激活Sentinel对Feign的支持
feign:
  sentinel:
    enabled: true  

写一个接口 用于feign的调用

@FeignClient(value = "nacos-payment-provider",fallback = PaymentFallbackService.class)//调用中关闭9003服务提供者
public interface PaymentService
{
    @GetMapping(value = "/paymentSQL/{id}")
    public CommonResult paymentSQL(@PathVariable("id") Long id);
}

他的兜底方法:

@Component
public class PaymentFallbackService implements PaymentService
{
    @Override
    public CommonResult paymentSQL(Long id)
    {
        return new CommonResult<>(444,"服务降级返回,没有该流水信息",new Payment(id, "errorSerial......"));
    }
}

在controller上加上一段代码

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

    @GetMapping(value = "/consumer/openfeign/{id}")
    public CommonResult paymentSQL(@PathVariable("id") Long id)
    {
        if(id == 4)
        {
            throw new RuntimeException("没有该id");
        }
        return paymentService.paymentSQL(id);
    }

最后不要忘记在主启动类上加上 @EnableFeignClients注解用于开启支持feign
通过controller调用服务
测试地址: http://localhost:84/consumer/paymentSQL/1
如果我们在调用中故意让feign出错 那么 他就会返回兜底的方法

19.8 规则持久化

我们将规则持久化到nacos
将限流配置规则持久化进Nacos保存,只要刷新8401某个rest地址,sentinel控制台
的流控规则就能看到,只要Nacos里面的配置不删除,针对8401上sentinel上的流控规则持续有效

首先在需要持久化的模块上的pom文件加上支持持久化的依赖



    com.alibaba.csp
    sentinel-datasource-nacos

然后在yaml进行添加配置

spring:
  cloud:
    sentinel:
      datasource:
        ds1:
          nacos:
            server-addr: localhost:8848 #nacos的地址
            dataId: ${spring.application.name} #自身服务名字
            groupId: DEFAULT_GROUP #是属于哪个分组
            data-type: json #保存的格式
            rule-type: flow 

最后需要在nacos加上新建一个配置文件 这样每次sentinel启动的时候就回去读取
需要注意的是 文件的名字 和分组 必须要符合 我们在yaml里配置的规则


那么这个json文件是什么意思呢 参考下面图片

当我们把服务关闭 再重启 这个规则就会依然存在于sentinel里面了

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/462834.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号