五、SpringCloud Alibaba
上一级页面:index-la
五、SpringCloud Alibaba
5.1 SpringCloud Alibaba 简介
5.1.1、简介
Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。
依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将 Spring Cloud 应用接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。
5.1.2、为什么要使用 ?
SpringClouid的几大痛点:
SpringCloud部分组件停止维护和更新,给开发带来不便;
SpringCloud部分环境搭建复杂,没有完善的可视化界面,我们需要大量的二次开发和定制
SpringCloud配置复杂,难以上手,部分配置差别难以区分和合理应用
SpringCloud Alibaba的优势:
阿里使用过的组件经历了考验,性能强悍,设计合理,现在开源出来大家用
成套的产品搭配完善的可视化界面给开发运维带来极大的便利
搭建简单,学习曲线低。
结合SpringCloud Alibaba我们最终的技术搭配方案:
SpringCloud Alibaba - Nacos : 注册中心 (服务发现/注册)
SpringCloud AlibabaNacos: 配置中心 (动态配置管理)
SpringCloud - Ribbon: 负载均衡
SpringCloud - Feign: 声明式HTTP客户端(调用远程服务)
SpringCloud Alibaba - Sentinel: 服务容错(限流、降级、熔断)
SpringCloud - Gateway: API 网关 (webflux 编程模式)
SpringCloud - Sleuth:调用链监控
SpringCloud Alibaba - Seata: 原Fescar, 即分布式事务解决方案
5.2 SpringCloud Alibaba - Nacos [作为注册中心]
Nacos 是阿里巴巴开源的一个更易于构建云原生应用的动态服务发现,配置管理和服务管理平台,他是使用 java 编写的,需要依赖 java 环境
Nacos 文档地址: https://nacos.io/zh-cn/docs/quick-start.html
5.2.1、下载 nacos-server
https://github.com/alibaba/nacos/releases
5.2.2、启动 nacos-server
- cmd 运行startup.cmd 文件
- 访问localhost:8848/nacos/
- 使用默认的 nacos/nacos 登录
5.2.3、注册进入 nacos 中
1、首先,修改 pom.xml 文件,引入 Nacos Discovery Starter
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
2、在应用的 /resource /application.properties 中配置 Nacos Server地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
3、使用@EnableDiscoveryClient 开启服务注册发现功能
@SpringBootApplication
@EnableDiscoveryClient
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
4、启动应用、观察 nacos 服务列表是否已经注册上服务
注意每一个应用都应该有名字,这样才能往册上去。修改pplicaion.propertes文件
spring.application.name= service provider
server.port=8000
5、注册更多的服务上去,测试使用 feign 远程
Nacos 使用三步
1、导包
2、写配置,指定 nacos 地址,指定应用的名字
3、开启服务注册发现功能 @EnableDiscoveryClient
Feign 使用三步
1、导包 openfeign
2、开启 @EnableFeignClients 功能
3、编写接口,进行远程调用
5.3 SpringCloud Alibaba - Nacos 作为配置中心
5.3.1、pom.xml 引入 Nacos Config Starter
<!--配置中心来做配置管理-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
5.3.2、在应用的 resource 下 bootstrap.properties
spring.application.name=gulimall-coupon
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
5.3.3、在 nacos 中添加配置
选择右上角添加配置
Data ID 改成 gulimall-coupon.properties 默认规则 用户名.应用名.properties
5.3.4、在应用中使用@Value 和 @RefreshScope
@RefreshScope // 刷新对应controller
@RestController
@RequestMapping("coupon/coupon")
public class CouponController {
@Autowired
private CouponService couponService;
@Value("${coupon.user.name}")
private String name;
@Value("${coupon.user.age}")
private Integer age;
@RequestMapping("/test")
public R test() {
return R.ok().put("name",name).put("age",age);
}
5.3.5、进阶
1、核心概念
命名空间:
用于进行租户粒度的配置隔离。不同的命名空间下,可以存在相同的 Group 或 DatalD 的配置。Namespace 的常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。
配置集
一组相关或者不相关的配置项的集合称为配置集。在系统中,一个配置文件通常就是一个配置集,包含了系统各个方面的配置。例如,一个配置集可能包含了数据源、线程池、日志级别等配置项。
配置集ID:
Nacos 中的某个配置集的 ID,配置集 ID 是组织划分配置的维度之一,Data ID 通常用于组织划分系统的配置集,一个系统或者应用可以包含多个配置集,一个系统应用可以包含多个配置集,每个配置集都可以被一个有意义的名称标识,Data ID 通常采用类 Java 包 如 ( com.taobao.tc.refund.log.level ) 的命名规则保证全局唯一性,此命名规则非强制
配置分组:
Nacos 中的一组配置集,是组织配置的维度之一,通过一个有意义的字符串,(如 Buy 或 Trade ) 对配置集进行分组,从而区分 Data ID 相同的配置集,当您在 Nacos 上创建一个配置时,如果未填写配置分组的名称,则配置分组的名称默认采用,DEFAULT_GROUP 配置分组的常见场景,不同的应用或组件采用了相同的配置类型,如 database_url 配置和 MQ_topic 配置
bootstrap.properties 配置
spring.application.name=gulimall-coupon # 服务的名称
spring.cloud.nacos.config.server-addr=127.0.0.1:8848 # 服务注册地址
spring.cloud.nacos.config.namespace=ae34901c-9215-4409-ae61-c6b8d6c8f9b0 # 命名空间地址
#spring.cloud.nacos.config.group=111 # 对应分组
spring.cloud.nacos.config.ext-config[0].data-id=datasource.yml # 配置集指定data_id
spring.cloud.nacos.config.ext-config[0].group=dev # 配置集指定 group 分组
spring.cloud.nacos.config.ext-config[0].refresh=true # 是否动态刷新 在配置中心修改后 微服务自动刷新
相关解释
/**
* 1、如何使用 Nacos作为配置中心统一管理配置
* 1.1 引入依赖
* <dependency>
* <groupId>com.alibaba.cloud</groupId>
* <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
* </dependency>
* 1.2 创建一个bootstrap.properties
* spring.application.name=gulimall-coupon
* spring.cloud.nacos.config.server-addr=127.0.0.1:8848
* 1.3 需要给配置中心默认添加一个叫 数据集 (Data Id) gulimall-coupon.properties 默认规则 用户名.应用名.properties
* 1.4 给 应用名.properties 添加任何配置
* 1.5 动态获取配置
* @RefreshScope: 动态获取并刷新配置
* @Value$("${配置项的名字}")
* 如果配置中心和当前应用的配置文件中都配置了相同的配置文件,优先使用配置中心的文件
*
* 2、细节
* 1、命名空间:配置隔离:
* 默认:public(保留空间);默认新增的所有配置都在 public 空间
* 1、开发 测试 生产 利用命名空间来做环境隔离
* 注意: 在bootstrap.properties配置上 需要使用哪个命名空间下的配置
* spring.cloud.nacos.config.namespace=b1e89ce0-784f-4a80-9de0-e9b080eeaca5
* 2、每一个微服务之间互相隔离配置,每一个微服务都创建自己的命名空间,只加载自己命名空间下的所有配置
*
*
* 2、配置集:所有配置的集合
*
* 3、配置集ID:类似文件名
* Data ID:类型文件名
*
* 4、配置分组:
* 默认所有的配置都属于 DEFAULT_GROUP
*
* 每个微服务创建自己的命名空间,使用配置分组区分环境,dev、test、prod
*
* 3、同时加载多个配置集
* 1、微服务任何配置信息,任何配置文件多可以放在配置中心中
* 2、只要在 bootstrap.properties 说明加载配置中心中哪些配置文件即可
* 3、@Value,@ConfigurationProperties...
* 以前SpringBoot的任何方式从配置文件中获取值,都能使用
* 配置中心有的优先使用配置中心的
* @author gcq
* @Create 2020-10-16
*/
5.4 SpringCloud Alibaba-Sentinel
这里是后面的内容,直接补充到这
1、简介
1、服务降级限流
什么是熔断:
A 服务调用 B 服务的某个功能,由于网络不稳定问题,或者 B 服务卡机,导致功能时间超长,如果这样子的次数太多,我们可以直接将 B 断路了,(A 不在请求 B 接口)凡是调用 B 服务的直接返回降级数据,不必等待 B 的 超时执行,这样 B 的故障问题,就不会级联影响到 A。
什么是降级:
整个网站处于流量高峰期服务器压力剧增,根据当前自身业务情况以及流量,对一些服务和页面进行有策略的降级/停止服务,所有的调用直接返回降级数据以此缓解服务器资源的压力,以保证核心业务的正常运行,同时也保持了客户和大部分客户等到正确的响应
异同:
相同点
1、为了保证集群大部分服务的可用性和可靠性,防止崩溃,牺牲小我
2、用户最终都是体验到某个功能不可用
不同点:
1、熔断是被调用方的故障,触发系统的主动规则
2、降级是基于全局的考虑停止一些正常服务,释放资源
什么是限流
对打入的服务的请求流量进行控制,使服务能够承担不超过自己能力的流量压力
2、Sentinel 简介
官方文档:https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D
项目文档:https://github.com/alibaba/Sentinel
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
Sentinel 具有以下特征:
- 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
- 完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
- 广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。
- 完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。
Sentinel 的主要特性:
Sentinel 分为两个部分:
- 核心库(Java 客户端)不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
- 控制台(Dashboard)基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器。
Sentinel 基本概念:
- 资源
- 资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。在接下来的文档中,我们都会用资源来描述代码块。
- 只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。
- 规则
- 围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。
2、Hystrix 与 Sentinel 比较
3、整合 Feign 和 Sentinel 测试熔断降级
熔断降级官网解释:https://github.com/alibaba/Sentinel/wiki/%E7%86%94%E6%96%AD%E9%99%8D%E7%BA%A7
SpringCloud整合Sentinel和Feign:https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel
pom.xml
<!-- 导入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>
application.properties
## sentinel与项目间的通信端口
spring.cloud.sentinel.transport.port=8719
## sentinel端口设置
spring.cloud.sentinel.transport.dashboard=localhost:8333
## 暴露信息
management.endpoints.web.exposure.exclude=*
## 配置文件打开 Sentinel 对 Feign 的支持
feign.sentinel.enabled=true
开启后,在微服务中调用远程服务,Sentinel 就会记录微服务之间的调用,从而对远程调用进行设置熔断降级等。
请求设置
设置流控规则
Feign设置
结果
4、整合 Sentinel 测试限流
官网Spring-Cloud 整合:https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel
Pom.xml
参考 3、整合 Feign 和 Sentinel 测试熔断降级
控制台:
超过单继阈值,返回自定义请求结果
实现方式:
/**
1、代码
* try (Entry entry = SphU.entry("resourceName")) {
* }(BlockedException e){}
* 2、基于注解
* @SentinelResource(value = "getCurrentSeckillSkusSource",blockHandler = "BlockHandler")
* 无论1/2方式一定要配置限流以后的默认返回
* url可以设置统一返回
**/
具体实现方式参考官网给出文档:https://github.com/alibaba/Sentinel/wiki/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8
5、Sentinel网关限流
官网文档:https://github.com/alibaba/Sentinel/wiki/%E7%BD%91%E5%85%B3%E9%99%90%E6%B5%81
pom.xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
启动Sentinle1.7.1 后比原先的1.6.1多个一个功能
您可以在 GatewayCallbackManager
注册回调进行定制:
setBlockHandler
:注册函数用于实现自定义的逻辑处理被限流的请求,对应接口为BlockRequestHandler
。默认实现为DefaultBlockRequestHandler
,当被限流时会返回类似于下面的错误信息:Blocked by Sentinel: FlowException
。
@Configuration
public class SentinelGatewayConfig {
public SentinelGatewayConfig() {
GatewayCallbackManager.setBlockHandler(new BlockRequestHandler() {
// 网关限流了 就会回调
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
R error = R.error(BizCodeEnume.TO_MANY_REQUEST.getCode(), BizCodeEnume.TO_MANY_REQUEST.getMsg());
String errorJson = JSON.toJSONString(error);
Mono<ServerResponse> body = ServerResponse.ok().body(Mono.just(errorJson), String.class);
return body;
}
});
}
}
5.5 SpringCloud Alibaba-Seata
1、简介
Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。
https://seata.io/zh-cn/index.html
2、核心概念
TC (Transaction Coordinator) - 事务协调者
维护全局和分支事务的状态,驱动全局事务提交或回滚。
TM (Transaction Manager) - 事务管理器
定义全局事务的范围:开始全局事务、提交或回滚全局事务。
RM (Resource Manager) - 资源管理器
管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
5.6 SpringCloud Alibaba-OSS
5.6.1、简介
对象存储服务 阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。
5.6.2、使用步骤
使用 Java 上传文件
https://help.aliyun.com/document_detail/32011.html?spm=a2c4g.11186623.6.915.56196d39rr96Ll
来自官网实例 - 上传文件流
@Test
public void testUpload() throws FileNotFoundException {
// Endpoint以杭州为例,其它Region请按实际情况填写。
String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
// 云账号AccessKey有所有API访问权限,建议遵循阿里云安全最佳实践,创建并使用RAM子账号进行API访问或日常运维,请登录 //https://ram.console.aliyun.com 创建。
String accessKeyId = "<yourAccessKeyId>";
String accessKeySecret = "<yourAccessKeySecret>";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// 上传文件流。
InputStream inputStream = new FileInputStream("<yourlocalFile>");
ossClient.putObject("<yourBucketName>", "<yourObjectName>", inputStream);
// 关闭OSSClient。
ossClient.shutdown();
System.out.println("上传成功");
}
需要填写 AccesskeyId 以及 Secret 同时也要指定文件位置 以及文件名字
最终上传结果
5.6.3、 抽取成一个单独的第三方服务?OSS
官网文档
https://github.com/alibaba/aliyun-spring-boot/blob/master/aliyun-spring-boot-samples/aliyun-oss-spring-boot-sample/README-zh.md
新建项目 gulimall-third-party
pom 配置
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-oss</artifactId>
</dependency>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- springCloudAlibaba -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
application.yml 配置 accessKey、secretKey、endpoint
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
alicloud:
access-key: LTAI4GE22ckocpNBfd36zkxJ
secret-key: qDFrQ6cxZqc4DwxoWx5K2aosXXj0Go
oss:
endpoint: oss-cn-shenzhen.aliyuncs.com ## 地域节点
bucket: gulimall-oss01 # 桶列表
application:
name: gulimall-third-party
server:
port: 30000
5.6.4、Web端上传介绍
阿里云对象存储-普通上传方式:
用户提交文件到服务器,服务器将文件提交到 OSS 对象存储
和数据直传到OSS相比,以上方法有三个缺点:
- 上传慢:用户数据需先上传到应用服务器,之后再上传到OSS。网络传输时间比直传到OSS多一倍。如果用户数据不通过应用服务器中转,而是直传到OSS,速度将大大提升。而且OSS采用BGP带宽,能保证各地各运营商之间的传输速度。
- 扩展性差:如果后续用户多了,应用服务器会成为瓶颈。
- 费用高:需要准备多台应用服务器。由于OSS上传流量是免费的,如果数据直传到OSS,不通过应用服务器,那么将能省下几台应用服务器。
阿里云对象存储-服务端签名后直传:
流程介绍
背景
采用JavaScript客户端直接签名(参见JavaScript客户端签名直传)时,AccessKey ID和AcessKey Secret会暴露在前端页面,因此存在严重的安全隐患。因此,OSS提供了服务端签名后直传的方案。
Web端向服务端请求签名,然后直接上传,不会对服务端产生压力,而且安全可靠。服务端签后直传