Spring CouldAlibaba
Posted 覃会程
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring CouldAlibaba相关的知识,希望对你有一定的参考价值。
Spring Could主要内容结构图:
简介
Spring Cloud Netflix将不再开发新的组件,进入维护模式。
我们都知道Spring Cloud版本迭代算是比较快的,因而出现了很多重大ISSUE都还来不及Fix就又推另一个Release了。进入维护模式意思就是目前一直以后一段时间Spring Cloud Netfli提供的服务和功能就这么多了,不在开发新的组件和功能了。以后将以维护和Merge分支Full Request为主。
Spring Cloud Alibaba的作用:
- 服务限流降级:默认支持Servlet、Feign、RestTemplate、Dubbo和RocketMQ限流降级功能的接入,可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级Metrics 监控。
- 服务注册与发现:适配 Spring Cloud服务注册与发现标准,默认集成了 Ribbon的支持。
- 分布式配置管理:支持分布式系统中的外部化配置,配置更改时自动刷新。
- 消息驱动能力:基于Spring Cloud Stream为微服务应用构建消息驱动能力。
- 阿里云对象存储:阿里云提供的海量、安全、低成本、高可靠的云存储服务。支持在任何应用、任何时间、任何地点存储和访问任意类型的数据。
- 分布式任务调度:提供秒级、精准、高可靠、高可用的定时(基于Cron表达式)任务调度服务。同时提供分布式的任务执行模型,如网格任务。网格任务支持海量子任务均匀分配到所有Worker (schedulerx-client)上执行。
Nacos服务注册和配置中心
名字的由来:前四个字母分别为Naming和Configuration的前两个字母,最后的s为Service。
Nacos是什么:
Nacos就是注册中心+配置中心的组合
相当于:Nacos = Eureka + Config + Bus
各注册中心的比较:
注意:Nacos支持AP和CP模式的切换
在父工程pom文件中引入alibaba 依赖,以下所有案例都基于该父工程
<!-- spring cloud alibaba 2.1.0.RELEASE -->
<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>
Navos服务提供者注册
pom文件:
<dependencies>
<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.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.atguigu.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>$project.version</version>
</dependency>
</dependencies>
yml文件:
server:
port: 9001
spring:
application:
name: nacos-payment-provider
cloud:
nacos:
discovery:
server-addr: localhost:8848
management:
endpoints:
web:
exposure:
include: "*"
启动类:
@SpringBootApplication
@EnableDiscoveryClient
public class NacosProviderMain9001
public static void main(String[] args)
SpringApplication.run(NacosProviderMain9001.class,args);
controller:
@RestController
@RequestMapping("/payment")
public class PaymentController
@Value("$server.port")
public String serverPort;
@RequestMapping("/getPayment/id")
public String getPayment(@PathVariable("id") Integer id)
return "Alibaba Nacos server "+ serverPort+"-----"+id;
Nacos服务消费者的注册
pom文件:
<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.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
yml文件:
server:
port: 83
spring:
application:
name: cloud-nacos-order
cloud:
nacos:
discovery:
server-addr: localhost:8848
#消费者将要去访问的微服务名称
server-url:
nacos-user-service: http://nacos-payment-provider
启动类:
@SpringBootApplication
@EnableDiscoveryClient
public class NacosOrderMain83
public static void main(String[] args)
SpringApplication.run(NacosOrderMain83.class,args);
controller:
@RestController
public class OrderNacosController
@Resource
private RestTemplate restTemplate;
@Value("$server-url.nacos-user-service")
private String url;
@GetMapping("/order/getPayment/id")
public String getPaymentInfo(@PathVariable("id") Long id)
return restTemplate.getForObject(url+"/payment/getPayment/"+id,String.class);
配置类:
@Configuration
public class ApplicationContextConfig
@Bean
@LoadBalanced //负载均衡:轮询
public RestTemplate getRestTemplate()
return new RestTemplate();
注意:Nacos是默认整合了Ribbon的,能够自动实现负载均衡,所以需要添加@LoadBalanced 注解,否则会报错。
Nacos作为服务配置中心
pom文件:
<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>
配置文件:
Nacos同springcloud-config一样,在项目初始化时,要保证先从配置中心进行配置拉取,拉取配置之后,才能保证项目的正常启动。
springboot中配置文件的加载是存在优先级顺序的,bootstrap优先级高于application
bootstrap文件:
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格式的配置
# group: TEST_GROUP
namespace: 7a901d46-e75e-4e6a-b186-5980cca4249b
# $spring.application.name-$spring.profile.active.$spring.cloud.nacos.config.file-extension
#nacos-config-client-dev.yaml
application文件:
spring:
profiles:
active: dev
启动类:
@SpringBootApplication
@EnableDiscoveryClient
public class ConfigNacosMain3377
public static void main(String[] args)
SpringApplication.run(ConfigNacosMain3377.class,args);
controller
@RestController
@RefreshScope //支持nacos的动态刷新功能
public class ConfigClientController
@Value("$config.info")
private String configInfo;
@GetMapping("/config/info")
public String getConfigInfo()
return configInfo;
Nacos界面配置对应:
最后公式:
$spring.application.name$spring.profiles.active.$(spring.cloud.nacos.config.file-extension
启动项目,成功获取配置文件
多环境多项目管理
问题1:
实际开发中,通常一个系统会准备
dev开发环境
test测试环境
prod生产环境。
如何保证指定环境启动时服务能正确读取到Nacos上相应环境的配置文件呢?
问题2:
一个大型分布式微服务系统会有很多微服务子项目,
每个微服务项目又都会有相应的开发环境、测试环境、预发环境、正式环境.
那怎么对这些微服务配置进行管理呢?
Namespace+Group+Data lD三者关系:
最外层的namespace是可以用于区分部署环境的,Group和DataID逻辑上区分两个目标对象。
默认情况:
Namespace=public,Group=DEFAULT_GROUP,默认Cluster是DEFAULT
Nacos默认的命名空间是public,Namespace主要用来实现隔离。
比方说我们现在有三个环境:开发、测试、生产环境,我们就可以创建三个Namespace,不同的Namespace之间是隔离的。
Group默认是DEFAULT_GROUP,Group可以把不同的微服务划分到同一个分组里面去
Service就是微服务;一个Service可以包含多个Cluster(集群),Nacos默认Cluster是DEFAULT,Cluster是对指定微服务的一个虚拟划分。比方说为了容灾,将Seryice微服务分别部署在了杭州机房和广州机房,
这时就可以给杭州机房的Service微服务起一个集群名称(HZ) ,
给广州机房的Service微服务起一个集群名称(GZ),还可以尽量让同一个机房的微服务互相调用,以提升性能。
最后是lnstance,就是微服务的实例。
## Nacos集群
默认Nacos使用嵌入式数据库实现数据的存储。所以,如果启动多个默认配置下的Nacos节点(Nacos集群),数据存储是存在一致性问题的。为了解决这个问题,Nacos采用了集中式存储的方式来支持集群化部署,目前只支持mysql的存储。
参考文章:
集群部署:link
集群配置:link
Sentinel实现熔断和限流
和Hystrix的对比
下载地址:
Sentinel分为两个部分:
- 核心库(Java客户端)不依赖任何框架/库,能够运行于所有Java运行时环境,同时对 Dubbo /Spring Cloud等框架也有较好的支持。
- 控制台(Dashboard)基于Spring Boot开发,打包后可以直接运行,不需要额外的Tomcat等应用容器。
启动本地Sentinel后
搭建服务,并将服务入驻Sentinel控制台(Dashboard)
pom文件:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 后续做持久化用到-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<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>
yml文件:
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinel-service
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务注册中心地址
sentinel:
transport:
dashboard: localhost:8080 #配置Sentinel dashboard地址
port: 8719
datasource:
ds1:
nacos:
server-addr: localhost:8848
dataId: $spring.application.name
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow
management:
endpoints:
web:
exposure:
include: '*'
测试controler:
@RestController
public class FlowLimitController
@RequestMapping("testA")
public String testA()
return "testA-------";
@RequestMapping("testB")
public String testB()
return "testB-------";
启动服务,观察Sentinel控制台
注意:Sentinel是懒加载模式,需要被监控的服务有请求后,才会显示监控信息。
监控规则说明
用于对每一个接口进行配置,规定接口的访问限制,如果不符合条件则调用失败。相当于将Hystrix在代码注解中的配置,在控制界面进行。
解释说明:
控流模式
直接模式流控
如下图的配置表示1秒钟内查询1次就是OK,若超过次数1,就直接-快速失败,报默认错误
关联模式流控
当关联的资源达到阈值时,就限流自己
比如当与A关联的资源B达到阀值后,就限流A自己。
上图的设置效果:
当关联资源/testB的qps阀值超过1时,就限流/testA的Rest访问地址,当关联资源到阈值后限制配置好的资源名
控流效果
快速失败
默认的流控效果,直接返回失败
Warm Up
Warm Up ( RuleConstant.cONTROL_BEHAVIOR_NARA_up)方式,即预热/冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动"”,让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。详细文档可以参考流星控制- Warm Up文档,具体的例子可以参见
公式:阈值除以coldFactor(默认值为3),经过预热时长后才会达到阈值
默认coldFactor为3,即请求QPS从(threshold / 3)开始,经多少预热时长才逐渐升至设定的QPS阈值。
案例:
阀值为10+预热时长设置5秒。系统初始化的阀值为10/3约等于3,即阀值刚开始为3;然后过了5秒后阀值才慢慢升高恢复到10
应用场景:
如:秒杀系统在开启的瞬间,会有很多流量上来,很有可能把系统打死,预热方式就是把为了保护系统,可慢慢的把流量放进来,慢慢的把阀值增长到设置的阀值。
排队等待
匀速排队,让请求以均匀的速度通过,阀值类型必须设成QPS,否则无效。
设置含义:/testA每秒1次请求,超过的话就排队等待,等待的超时时间为20000毫秒
应用场景:
这种方式主要用于处理间隔性突发的流量,例如消息队列。想象一下这样的场景,在某一秒有大量的请求到来,而接下来的几秒则处于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处理这些请求,而不是在第一次直接拒绝多余的请求。
降级规则
和Hystrix相似,只是Sentinel是在监控界面进行配置,不需要在代码中使用注解进行配置。
Sentinel熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联错误。
当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出 DegradeException)。
注意:Sentinel的断路器是没有半开状态的,和Hystrix区别开,只要在窗口时间内没有触发新的熔断,窗口事件过后就会恢复。
半开的状态系统自动去检测是否请求有异常,没有异常就关闭断路器恢复使用,
有异常则继续打开断路器不可用。具体可以参考Hystrix
RT(平均响应时间,秒级)降级策略
平均响应时间超出阈值且在时间窗口内通过的请求>=5,两个条件同时满足后触发降级窗口期过后关闭断路器
RT最大4900(更大的需要通过-Dcsp.sentinel.statistic.max.rt=XXXX才能生效)
案例:
假如一秒钟打进来10个线程(大于5个了)调用testD,我们希望200毫秒处理完本次任务,
如果超过20O0毫秒还没处理完,在未来1秒钟的时间窗口内,断路器打开(保险丝跳闸)微服务不可用,保险丝跳闸断电了
异常比列(秒级)降级策略
QPS >= 5且异常比例(秒级统计)超过阈值时,触发险级;时间窗口结束后,关闭降级
异常比例( DEGRADE_GRADE_EXCEPTION_RATIo):当资源的每秒请求量>=5,并且每秒异常总数占通过量的比值超过阈值( DegradeRule中的count)之后,资源进入降级状态,即在接下的时间窗口(DegradeRule中的timewindow,以s为单位)之内,对这个方法的调用都会自动地返回。异常比率的阈值范围是[0.0,1.0],代表0%到100%。
案例:
当一秒钟内访问量超过5,且调用失败的比例超多百分之20,则触发降级一秒钟,一秒钟后关闭降级。
异常数(分钟级)降级策略
异常数(分钟统计)超过阈值时,触发降级;时间窗口结束后,关闭降级
时间窗口一定要大于等于60秒。
异常数(DEGRADE_GRADE_EXCEPTION_COUNT ):当资源近1分钟的异常数目超过阈值之后会进行熔断。注意由于统计时间窗口是分钟级别的,若timewindow小于60s,则结束熔断状态后可能再进入熔断状态。
案例:
http://localhost:8401/testE,第一次访问绝对报错,因为除数不能为零,我们看到error窗口,但是达到5次报错后,进入熔断后降级。
上述三种规则的测试代码:
@RequestMapping("testC")
public String testC()
try
TimeUnit.SECONDS.sleep(6);
catch (InterruptedException e)
e.printStackTrace();
return "testC 测试RT-------";
@RequestMapping("testD")
public String testD()
System.out.println("testD 异常比例测试");
int age = 10/0;
return "testD-------";
@RequestMapping("testE")
public String testE()
System.out.println("testD 异常s数--测试");
int age = 10/0;
return "testD-------";
热点key限流(热点规则)
何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的Top K数据,并对其访问进行限制。比如:
- 商品ID为参数,统计一段时间内最常购买的商品ID并进行限制
- 用户ID为参数,针对一段时间内频繁访问的用户ID进行限制
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
在1秒钟内,携带第一个参数的请求超过1一次,则进行服务降级,调用指定方法返回,没有指定则会返回错误页面
测试代码:
@RequestMapping(以上是关于Spring CouldAlibaba的主要内容,如果未能解决你的问题,请参考以下文章
Spring框架系列 - Spring和Spring框架组成
你了解Spring从Spring3到Spring5的变迁吗?
Spring全家桶笔记:Spring+Spring Boot+Spring Cloud+Spring MVC
学习笔记——Spring简介;Spring搭建步骤;Spring的特性;Spring中getBean三种方式;Spring中的标签