一.Nacos配置管理
1.Nacos配置中心
1.1.概述
Nacos作为Spring Cloud Alibaba的一个重要组件,它不仅可以用作服务注册与发现,也可以用来替代Spring Cloud Config作为统一配置文件管理。
1.2 优点
- 配置放在nacos,之后需要更改配置不需要重启项目
- 可以有一个公共的配置:
1.3.Nacos添加配置
第一步:点击+号进行添加配置
第二步:填写Data ID,选择YAML,编辑配置文件内容(注意:DataID一定要加后缀.yml或者yaml)
Data ID
: 非常重要,可以看做是配置的文件的名字,在程序中拉取配置文件的时候需要指定Data ID。Group
: 分组,默认是 DEFAULT_GROUP , 可以针对不同的项目指定不同的配置组。
2.客户端接入配置中心(重要)
2.1.导入依赖
<dependencies>
<!-- 配置中心客户端-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- 服务注册与发现-->
<dependency>
<groupId>com.alibaba.cloud </groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.example</groupId>
<artifactId>springcloudalibaba-user-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
2.3.修改yml配置
将原来的配置文件修改成bootstrap.yml
,然后增加如下内容:
server:
port: 1010
spring:
profiles:
active: dev
application:
name: user-server
cloud:
nacos:
discovery:
server-addr: localhost:8848 #注册中心
config:
server-addr: localhost:8848 #配置中心
file-extension: yaml #配置文件格式
prefix: application-user #配置前缀 ,默认使用sring.application.name
group: DEFAULT_GROUP #默认分组
#如何查找配置文件:application-user + dev + yaml=application-user-dev.yaml 正好和Nacos配置的DataId一致
提示:客户端是如何从Nacos中找到配置文件的呢?
spring.cloud.nacos.config.server-addr
:配置了Nacos的地址spring.cloud.nacos.config.file-extension
:指定了配置文件的格式为YAML,默认是properties,spring.cloud.nacos.config.prefix
:配置前缀,如果不配置前缀默认会把 服务名即spring.application.name
的值作为前缀spring.cloud.nacos.config.group
:分组名,默认是DEFAULT_GROUP对应了Nacos配置中的Groupspring.profiles.active
:配置了环境为dev .该配置可以实现多配置多环境管理
根据如上配置,那么config客户端会将:前缀+环境+后缀 拼接成的文件名“application-user-dev.yaml
” 去Nacos上查找是否有对应Data ID的配置文件。
3.命名空间
命名空间可以用来隔离不同项目的配置文件,在Nacos中配置了命名空间后,那么Java客户端需要指定命名空间后才能拉取到该命名空间下的配置文件。
3.1.创建命名空间
修改Nacos,添加命名空间如下:
这里建立了一个名字为“test”的命名空间,点击确定,然后你需要关注一下命名空间的ID,这个是需要在Java客户端进行配置的。如下:
3.2.在命名空间创建配置
进入配置列表 ,切换到新建立的命名空间“test”,然后创建配置,如下:
需要注意:这里的配置文件名也叫 application-user-dev.yaml,但是他是属于 “test”这个命名空间的 , 我们之前在 默认的“public”命名空间中也有一个同名的配置。
3.3.客户端配置
这里需要指定一下从哪个命名空间拉取配置:
server:
port: 1010
spring:
profiles:
active: dev
application:
name: user-server
cloud:
nacos:
discovery:
server-addr: localhost:8848 #注册中心
config:
server-addr: localhost:8848 #配置中心
file-extension: yaml #配置文件格式
prefix: application-user #配置前缀 ,默认使用sring.application.name
group: DEFAULT_GROUP #默认分组
namespace: 8ef8c1e5-6d20-4efc-80c8-2b2c05541fa3 #命名空间的ID
注意:这里的namespace对应了 Nacos中“test”这个命名空间的ID,意思是从“test”这个命名空间去找 application-user-dev.yaml的配置文件。
4.扩展需求
4.1.如何自定义Data ID
支持自定义扩展的 Data Id 配置 :https://github.com/alibaba/spring-cloud-alibaba/wiki/Nacos-config
4.2.开启Nacos认证
开启Nacos认证,需要通知账号和密码进行注册,以及拉取配置。
https://nacos.io/zh-cn/docs/auth.html
二.Sentienl限流
1.Sentinel和Hystrix
1.1.限流和熔断
限流 , 限制流量,这里的流量我们可以理解成请求数量,其实就是限制服务器的请求并发数量,为什么要这么做?如果不做限流,那么在大量并发请求下我们的服务器会慢慢的变慢然后顶不住压力而挂掉(类似堵车)。并不是说并发越大越好,有的时候我们的项目规模和业务决定了我们不需要那么大的并发性,当大量的并发请求访问到服务器时我们需要把部分请求拒绝在外,这个是流量限制 - 限流。
熔断机制在在《Spring Cloud 极简入门》中有详细的解释,熔断机制是对服务调用链路的保护机制,如果链路上的某个服务不可访问,调用超时,发生异常等,服务会进行发熔断,触发降级返回托底数据。简单理解就是当服务器不可访问,可以返回一些预先准备好的兜底数据给用户,比如友好的提示信息,不至于直接向客户抛出异常。
1.2.Hystrix的熔断和资源隔离
其实在《Spring Cloud 极简入门》中我们已经学习过Hystrix的熔断和资源隔离机制,它的资源隔离可以通过线程池隔离和信号量隔离两种方式来实现对流量的控制。Hystrix相比Sentinel来说它的线程池隔离(限流)会造成线程上下切换对资源的消耗比较大;Hystrix使用的信号量进行资源的隔离效果不错,但是无法对慢调用进行自动降级。
1.3.Sentinel介绍
Sentinel诞生于阿里巴巴,其主要目标是流量控制和服务熔断
,2018年,Sentinel演变为一个开源项目现如今成为了Spring Cloud Alibaba的一个子项目。Sentinel是通过限制并发线程的数量来减少不稳定资源的影响
,而不是使用线程池,省去了线程切换的性能开销。
当资源的响应时间变长时,线程将开始被占用。当线程数累积到一定数量时,新的传入请求将被拒绝
。反之亦然,当资源恢复并变得稳定时,占用的线程也将被释放,新请求将被接受。
除了限制并发性外,Sentinel可以根据响应时间降级
不稳定资源也是保证可靠性的有效方法。当资源的响应时间太大时,将在指定的时间窗口中拒绝所有对该资源的访问
。-- 熔断机制
此外,Sentinel支持的熔断降级维度更多,可对多种指标进行流控、熔断,且提供了实时监控和控制面板,功能更为强大。
2.Sentinel限流实战(重要)
2.1.Sentinel Server服务端
Sentinel 提供了现成的服务端供我们使用(https://github.com/alibaba/Sentinel/releases/download/1.6.0/sentinel-dashboard-1.6.0.jar),下载之后通过命令行启动
java -jar -Dserver.port=1111 sentinel-dashboard-1.6.0.jar
访问:http://127.0.0.1:1111
进入控制台,使用 sentinel/sentinel登录。
2.Sentinel限流实战(重要)
2.1.Sentinel Server服务端
默认用户名和密码都是sentinel
。对于用户登录的相关配置可以在启动命令中增加下面的参数来进行配置:
-
-Dsentinel.dashboard.auth.username=sentinel
: 用于指定控制台的登录用户名为 sentinel; -
-Dsentinel.dashboard.auth.password=123456
: 用于指定控制台的登录密码为 123456;如果省略这两个参数,默认用户和密码均为 sentinel -
-Dserver.servlet.session.timeout=7200
: 用于指定 Spring Boot 服务端 session 的过期时间,如 7200 表示 7200 秒;60m 表示 60 分钟,默认为 30 分钟; -
-Dserver.port=1111
:配置端口
2.2.Sentinel 客户端接入
1.导入依赖
修改用户服务 springcloudalibaba-user-server-1010 ,加入sentinel依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
2.配置Sentinel
修改yml配置,添加senticel服务控制台地址
spring:
cloud:
sentinel:
transport:
dashboard: localhost:1111
3.资源限流
Sentinel为我们提供了 @SentinelResource
注解标记需要限流的资源。 修改UserController,代码如下:
@GetMapping("/user/{id}")
//限流降级
@SentinelResource(value="user",blockHandler="exceptionHandler")
public User getById(@PathVariable Long id){
System.out.println(notify);
return new User(id,"zs:"+id, "我是zs");
}
// 限流与阻塞处理 : 参数要和 被降级的方法参数一样
public User exceptionHandler(@PathVariable Long id, BlockException ex) {
ex.printStackTrace();
System.out.println("限流了...");
return new User(-1L,"限流了","限流了");
}
提示:这里通过@SentinelResource
的value属性为资源取名为 “user” ,后续我们可以根据该资源名来进行限流。
同时这里通过 blockHandler
属性我配置了一个限流降级方法,即当“user”资源触发限流了会调用blockHandler
指向的降级方法返回拖地数据,不至于抛出默认的限流异常信息给客户端(一串英文用户也看不懂) ,需要注意的是:降级方法要和被限流的方法参数一致,然后加上 BlockException异常对象。
当然,也可以通过 blockHandlerClass 属性把降级方法写在一个专门的类中,如:
@SentinelResource(value="user",blockHandler="exceptionHandler"
,blockHandlerClass=ExceptionUtil.Class)
降级类
public final class ExceptionUtil {
public static User exceptionHandler(Long id ,lockException ex) {
//...
}
}
2.3.Sentinel设置限流策略
启动应用 springcloudalibaba-user-server-1010 ,然后通过浏览器访问 http://localhost:1010/user/11
,然后登录Sentinel控制台,在“实时监控”列表中可以看到资源的相关监控信息的
在 “族点链路” 列表中可以看到资源的调用链 ,并且可以通过“流控”按钮设置流控规则
也可以在“流量控制”菜单中我们可以针对资源进行限流规则的设置。如下:
这里添加了一个流控规则,资源名对应客户端 @SentinelResource(value="user"..
注解的资源,通过QPS限流(每秒请求数量),阈值是 1 ,意思是“user”这个资源每秒只能有1个请求进来,多余的请求会触发限流,返回降级数据。
2.4.限流测试
通过浏览器频发访问 “user”资源,当QPS大于1就会触发限流,效果如下:
5.Gateway使用Sentinel限流(重要)
Spring Cloud Gateway 作为微服务的网关,它是微服务的访问入口,当请求的流量洪峰到来我们可以在Gateway网关层通过Sentinel对请求进行流控,把好第一道关。
5.1.导入依赖
这里我们需要导入sentinel基础依赖和 sentinel-gateway 整合依赖
<!-- 限流和gataway使用-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
5.2.配置Sentinel地址
修改yml配置,增加Sentinel服务地址
spring:
cloud:
sentinel:
transport:
dashboard: localhost:1111
5.3.配置限流规则
启动Gateway,登录sentinel控制台,对url资源进行流控限制,配置方式和前面的配置方式一样,童鞋们可以自己测试一下。
5.4.限流降级
@Configuration
public class SentinelConfig {
public SentinelConfig(){
GatewayCallbackManager.setBlockHandler(new BlockRequestHandler() {
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
return ServerResponse.ok().body(Mono.just("限流啦,请求太频繁"),String.class);
}
});
}
}
6.Nacos存储限流规则
在前两章节我们学习了通过Sentinel的限流和熔断机制来保护微服务,提高系统的可用性,但是有一个问题,我们在Sentinel配置了限流,熔断策略,默认情况下Sentinel的数据是基于内存存储,当客户端断开,或者Sentinel重启数据就会丢失,这不是我们愿意看到的。所有我们需要的Sentinel做数据持久。 Sentinel 中支持5种持久化的方式:file、redis、nacos、zk和apollo,本片文章针对于Nacos进行持久化配置。
6.1.整合Nacos持久化限流规则
第一步:导入基础依赖,springcloudalibaba-user-server-1010为例子,修改pom增加Sentinel和Nacos持久化配置依赖 sentinel-datasource-nacos ,如下:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--Sentinel和Nacos做持久的-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<version>1.5.2</version>
</dependency>
</dependencies>
第二步:配置持久化nacos地址
spring:
application:
name: user-server
cloud:
nacos:
config: #配置中心
server-addr: localhost:8848
file-extension: yaml
prefix: application-user
sentinel: #限流服务器sentinel配置
transport:
dashboard: localhost:1111
#====================持久化配置=================================
datasource:
flow:
nacos: #限流持久配置
server-addr: localhost:8848 #使用nacos的持久
dataId: application-user-dev #获取限流的数据源的dataId
groupId: DEFAULT_GROUP
rule-type: flow #类型:限流
#=====================================================
profiles:
active: dev
这里其实是在之前的配置基础上增加了 spring.cloud.sentinel.datasource持久化数据源的配置,对应了NacosDataSourceProperties 配置类具体含义如下:
- spring.cloud.sentinel.datasource.ds.nacos.server-addr:nacos的访问地址
- spring.cloud.sentinel.datasource.ds.nacos.groupId:nacos中存储规则的groupId
- spring.cloud.sentinel.datasource.ds.nacos.dataId:nacos中存储规则的dataId
- spring.cloud.sentinel.datasource.ds.nacos.rule-type:该参数是用来定义存储的规则类型。所有的规则类型可查看枚举类:…datasource.RuleType,每种规则的定义格式可以通过各枚举值中定义的规则对象来查看,比如限流规则可查看:…flow.FlowRule
简而言之,这里是配置了Sentinel持久化针对于Nacos的相关信息,程序会去地址为localhost:8848的Nacos中查找DataId为 application-user-sentinel-dev,GourpId为 DEFAULT_GROUP的文件作为限流策略(rule-type: flow代表限流)。
第三步:编写测试用的Controller这个controller我们待会用来做限流测试,
@RestController
public class TempController {
@GetMapping("/hello")
public String hello() {
return "测试数据";
}
}
6.2.Nacos持久化Sentinel限流规则
第一步:在配置列表增加配置如下:
[
{
"resource": "/hello",
"limitApp": "default",
"grade": 1,
"count": 10,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
这里做一个解释
- resource:对那个资源进行限流
- limitApp:这个是流控的调用者,default 代表不区分调用者
- grade:限流方式0是根据并发数量限流,1是表根据QPS来限流
- count:限流阈值,达到这个阈值就被限流,触发降级。
- strategy:基于调用链的流控制策略。0 直接,1 关联 2 链路
- controlBehavior:流控效果,0 直接拒绝,1是Warm Up,2是匀速排队
- clusterMode:是否为集群
上面的配置项目对应了 com.alibaba.csp.sentinel.slots.block.flow.FlowRule 限流规则类。程序启动,Sentinel通过 NacosDataSource 从Nacos中查找配置。具体效果如:
这里随便用的一个限流配置(ruoyi)
三.Sentinel熔断
1.概述
1.1.什么是熔断
在上一章节我们探讨了Sentinel的流控(限流)功能,Sentinel除了流控还提供了服务熔断和降级机制,服务之间的调用关系错综复杂,微服务的调用链上的某些服务资源不稳定(宕机,异常,超时)可能会导致可能请求的失败和请求的堆积,调用链产生连锁反应可能会导致整个微服务架构瘫痪
。服务熔断降级机制是保障高可用的重要措施之一。
1.2.Sentinel熔断
Sentinel的服务熔断机制会对调用链上的某个不稳定(宕机,异常,超时)的资源,做出请求限制,快速失败,避免影响到其它的服务而导致级联错误
。资源熔断后,在后续的一定时间(时间窗口)之内,对该服务的请求都自动熔断,抛出 DegradeException异常。
Sentinel拥有比Hystrix更强大和丰富的功能,能满足我们的各种应用场景,并且经历过淘宝双十一的考验,是微服务架构中熔断机制的不二选择。
2.Sentnel熔断实战(重要)
2.Sentnel熔断实战(重要)
2.1.资源熔断降级
4.Feign整合Sentinel熔断(重要)
Spring Cloud Alibaba是Spring Cloud的一个子项目,OpenFeign是Spring Cloud的客户端负载均衡器,使用Spring Cloud Alibaba依然可以很方便的集成OpenFeign,如果要使用OpenFeign作为服务客户端负载均衡,那么我们需要考虑OpenFeign开启Sentinel进行服务熔断降级。
4.1.开启Sentinel
OpenFeign与Sentinel组件集成除了引入sentinel-starter
依赖关系之外,还需要在属性文件中启用Sentinel支持:feign.sentinel.enabled=true
feign:
sentinel:
enabled: true #熔断
4.2.给Feign接口降级
这里跟Feign开启[Hystrix]降级一样,还是可以使用fallback属性
@FeignClient(value = "user-server",fallback = UserClientFallback.class)
public interface UserClient {
@GetMapping("/user/{id}")
User getById(@PathVariable Long id);
}
4.3.编写降级类
@Component
public class UserClientFallback implements UserClient {
@Override
public User getById(Long id) {
return new User(-1L,"无此用户","无此用户");
}
}