官网:官网地址
GitHub中文文档:点击访问
一个更易于构建云原生应用的动态服务发现、配置管理和 服务管理平台。
Liunx版:nacos-server-1.4.1.tar.gz
Windows版:nacos-server-1.4.1.zip
下载完成后进入文件夹的bin目录下启动nacos:
登陆成功显示的界面:
(1)创建子模块cloudalibaba-provider-paymnet9001
(2)编写pom
父pom:
<dependencyManagement>
<dependencies>
<!-- 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>
</dependencies>
</dependencyManagement>
本pom:
<dependencies>
<!-- 引入自定义的api的通用包 -->
<dependency>
<groupId>com.atguigu.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- SpringCloud alibaba 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)编写application.yml
server:
port: 9001
spring:
application:
name: nacos-payment-provider
cloud:
nacos:
discovery:
server-addr: localhost:8848 #配置nacos地址
#打开全部监控端点
maagement:
endpoints:
web:
exposure:
include: '*'
(4)创建主启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class PaymentMain9001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain9001.class,args);
}
}
(5)编写业务方法
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(value = "/payment/nacos/{id}")
public String getPayment(@PathVariable("id") Integer id){
return "nacos registry,serverPort:" + serverPort + "\t id" + id;
}
}
(6)启动nacos和9001模块进行测试
进入Nacos的web管理界面的服务列表,可以查看到注册到Nacos服务注册中心中的服务:
(1)创建子模块 cloudalibaba-provider-paymnet9002
几乎跟9001完全一样,作为演示Nacos的负载均衡功能使用。
启动之后查看一下Nacos服务注册中心,确定服务实例数量:
(1)创建子模块 cloudalibaba-consumer-nacos-order83
(2)编写pom
<dependencies>
<!-- SpringCloud alibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 引入自定义的api的通用包 -->
<dependency>
<groupId>com.atguigu.springcloud</groupId>
<artifactId>cloud-api-commons</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>
(3)编写application.yml
server:
port: 83
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
application:
name: nacos-order-consumer
#消费者将要去访问的微服务名称(注册成功进nacos的微服务提供者)
server-url:
nacos-user-service: http://nacos-payment-provider
(4)创建启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class OrderNacosMain83 {
public static void main(String[] args) {
SpringApplication.run(OrderNacosMain83.class,args);
}
}
(5)编写业务类
需要添加一个RestTemplate的配置类:
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 AppliationContextConfig {
@Bean
@LoadBalanced //赋予RestTemplate负载均衡的能力
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
import lombok.extern.slf4j.Slf4j;
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;
import javax.annotation.Resource;
@RestController
@Slf4j
public class OrderNacosController {
@Resource
private RestTemplate restTemplate;
@Value("${server-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);
}
}
(6)启动nacos、payment9001、payment9222和order83测试
查看nacos界面
通过访问:http://localhost:83/consumer/payment/nacos/1133,可以看出nacos默认自带负载均衡(轮询):
Nacos与其他注册中心特性对比
Nacos支持AP和CP的切换
(1)创建子模块cloudalibaba-config-nacos-client3377
(2)编写pom
<dependencies>
<!-- nacos-config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- SpringCloud alibaba nacos discovery-->
<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)编写application.yml
Nacos同springcloud-config一样,在项目初始化时,要保证先从配置中心进行配置拉取,拉取之后,才能保证项目的正常启动。
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格式的配置
application.yml:
spring:
profiles:
active: dev
(4)创建主启动类
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)编写业务类
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中添加配置信息
填写好之后发布:
再次通过请求获取内容
至此,Nacos Config中心配置成功!
(1)是什么
类似Java里面的package名和类名
最外层的namespace是可以用于区分部署环境的,Group和DataID逻辑上区分两个目标对象。
(2)三者情况
默认情况:Namespac=public,Group=DEFAULT_GROUP,默认Cluster是DEFAULT
(3)DataID配置
指定spring.profile.active和配置文件的DataI来使不同环境下读取不同的配置。
新建dev和test两个DataID:
通过spring.profile.active属性就能进行多环境下配置文件的读取:
(4)Group分组方案
通过Group实现环境区分,
通过bootstrap+application实现group区分开发环境,在config下增加一条group的配置即可。可配置为DEV_GROUP或TEST_GROUP:
(5)Namespace空间方案
在此新建dev和test两个Namespace:
回到服务列表,可以发现在public的基础上多了两个:
进入配置列表dev命名空间下创建三个配置文件:
通过bootstrap+application实现命名空间区分开发环境,在config下增加一条namespace的配置即可。其值即为命名空间的ID:
文档说明地址:点击访问
默认Nacos使用嵌入式数据库实现数据的存储。所以,如果启动多个默认配置下的Nacos节点,数据存储是存在一致性的问题的。为了解决这个问题,Nacos采用了集中式存储的方式来支持集群化部署,目前只支持MySQL的存储。
Nacos默认自带的是嵌入式数据库derby
(1)实现Nacos的derby切换到mysql
打开这个sql脚本复制里面的sql语句前往Mysql数据库图形化工具中执行一下:
找到 nacos/conf 目录下的的application.properties配置文件,修改conf/application.properties文件,增加支持mysql数据源配置(目前只支持mysql),添加mysql数据源的url、用户名和密码":
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://11.162.196.16:3306/nacos_devtest?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=nacos_devtest
db.password=youdontknow
高兴的太早啦O(∩_∩)O,重启的时候遇到了一点问题,因为版本的原因
此处遇到了一些问题需要修改,因为数据库要5.6.5+,我索性下载了mysql8.0.20,所以连接数据时在Nacos官网所给的db.url.0=jdbc:mysql://11.162.196.16:3306/nacos_devtest?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true的基础上添加时区参数:serverTimezone=UTC;另外我删除了之前nacos1.1.4,因为其版本过低无法与mysql8.0连接,下载了nacos1.4.1,启动报错,需要修改一下startup.cmd/startup.sh:
这两处都修改之后,终于启动成功!
这也意味我们切换默认数据库derby到mysql是成功的!
解压命令:tar -zxvf nacos-server-1.4.1.tar.gz
至此已经下载成功!
然后在进入到application.properties中添加配置:
Gihub地址:点击访问
中文文档:点击访问
Sentinel: 分布式系统的流量防卫兵
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
(1)下载地址:前往下载
(2)安装Sentinel控制台
sentinel组建由两部分构成
– 核心库(Java客户端)不依赖任何框架/库,能够运行于所有Java运行时环境,同时对Dubbo/Spring Cloud等框架也有较好的支持。
– 控制台(Dashboard)基于SpringBoot开发,打包后可以直接运行,不需要额外的Tomcat等应用容器。
运行步骤
–下载到本地jar包
– 需要有java8环境且8080端口不能被占用
– 命令:java -jar sentinel-dashboard-xxx.jar
– 访问sentinel管理界面:http://localhost:8080,账号密码均为sentinel
(1)启动Nacos8848
(2)创建子模块cloudalibaba-sentinel-service8401
<!-- SpringCloud alibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud alibaba sentinel-datasource-nacos:用于持久化 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<!-- SpringCloud alibaba 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组件 -->
<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>
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: '*'
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);
}
}
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)启动子模块8401微服务查看sentinel
因为Sentinel采用的是懒加载机制,需要执行一次访问才能够在http://localhost:8080/#/dashboard监控界面出现:
(4)sentinel的流控规则
A、QPS直接失败:当调用该api的QPS达到阀值的时候,进行限流
新增一个流控规则:表示1s访问/testA的数量为1,超过1次会出错
1s内超过1次就会被阻塞限流:
B、线程数直接失败:当调用该api的线程数达到阀值的时候 ,进行限流
新增一个流控规则:表示访问/testB的线程最大处理数量为1,超过1次会出错
C、关联:当关联的资源达到阀值时,就限流自己(别人惹事自己承担)
比如:支付功能方法达到处理阀值,就得限流下下订单的功能方法。
正常情况下我们访问/testA并不会出现阻塞限流,现在用postman模拟并发密集的访问/testB的同时我们在访问/testA进行测试:
点击 run “collectionsName”
密集访问/testB的同时访问/testA,发现被限流了,这就是流控-关联的作用:
D、链路:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阀值,就进行限流)【api级别的针对来源】
E、预热Warm up
比如:系统初始化的阀值为10/3约等于3,即阀值刚开始为3;然后过了5s后阀值才慢慢恢复到10
配置好规则之后,访问/testB 5s之前快速点击会出现阻塞限流情况,但是5s之后阀值达到了10便不会轻易出现了阻塞情况了。
F、排队等待:匀速排队,让请求以匀速通过,阀值类型必须设置为QPS否则无效
在/testA方法中添加打印方法:
使用postman向/testA发送10次请求,请求间隔为0.1s:
可以看到控制台打印结果显示每隔一秒处理了一次请求而不是0.1s,排队等候生效,如果请求数量实在过多,可能会出现一个请求在排队20s都没有排上就会出现超时报错处理。
(5)sentinel降级规则
A、慢调用比例
testD()方法:
@GetMapping("/testD")
public String testD(){
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("testD 测试RT");
return "-----------------testD";
}
快速点击访问/testD导致1s内响应数>=5,又因为我们的线程作了1s睡眠,处理时间大于0.2响应,所以全部响应都为慢响应,满足两个条件
又因为我们的熔断时长为1s,所以当下1s请求数<5时,则结束熔断,请求成功:
B、异常比例
当1s内错误率大于20%且请求数大于5才会触发降级。
C、异常数
(6)sentinel热点规则
A、兜底方法:分为系统默认和客户自定义两种
在8401模块中添加如下方法
@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){
return "--------------testHotKey";
}
public String deal_testHotKey(String p1, String p2, BlockException exception){
return "---------------deal_testHotKey";
}
在Sentinel控制台添加如下热点规则:
再次访问http://localhost:8401/testHotKey?p1=a频率为1s1次的时候不会出现问题,当频率超过1s1次,则就会执行我们在==@SentinelResource==注解中指定的兜底方法:
注:如果不指定@SentinelResource的blockHandler属性的兜底方法的话,当违反了热点规则时,会报错误界面:
B、参数例外项
上述A中参数p1的QPS超过1次/s就会马上被限流。当存在特殊情况,例如:当p1的值是我们所期望的值时,希望它即便超过1次/s也不会被限流。
此处配置热点规则:当p1=5时,阈值为200;其他情况阈值为1
先访问 http://localhost:8401/testHotKey?p1=a,当QPS<=1时正常访问,当QPS>1则限流执行兜底方法:
再访问 http://localhost:8401/testHotKey?p1=5,当我们快速点击发现不会出现兜底方法执行了,由此可见:我们的手速没法达到200
次/s 且 配置例外项成功了:
C、@SentinelResource只处理的是违背Sentinel控制台热点规则的访问情况,而对于处理方法中出现的异常不涉及
(7)系统自适应限流
A、配置一个入口QPS系统规则
现在无论是/testA还是/testB当访问频率超过1次/s都会触发限流。
将整个系统比作一个小区,将controller中的rest地址比作住户。之前的得规则设置都是住户门口的设置,只针对某个住户生效;而系统规则则是对小区大门生效。
(8)@SentinelResource配置
A、目前兜底方法存在的问题
B、客户自定义限流处理逻辑
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.atguigu.springcloud.utils.CommonResult;
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");
}
}
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.atguigu.springcloud.alibaba.myhandler.CustomerBlockHandler;
import com.atguigu.springcloud.entity.Payment;
import com.atguigu.springcloud.utils.CommonResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@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服务不可用");
}
@GetMapping("/rateLimit/byUrl")
@SentinelResource(value = "byUrl")
public CommonResult byUrl(){
return new CommonResult(200,"按url限流测试ok",new Payment(2020L,"serial002"));
}
@GetMapping("/rateLimit/customerBlockHandler")
@SentinelResource(value = "customerBlockHandler",blockHandlerClass = CustomerBlockHandler.class,
blockHandler = "handlerException2")
public CommonResult customerBlockHandler(){
return new CommonResult(200,"按url限流测试ok",new Payment(2020L,"serial002"));
}
}
通过这样基本可以解决兜底方法跟业务方法耦合。
根据资源名添加流控规则就可以实现我们自定义兜底的方法执行:
C、@SentinelResource注解其他属性
注意:注解方式埋点不支持private方法
A、fallback、blockHandler属性值设置
@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")
public CommonResult<Payment> fallback(@PathVariable("id")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处理方法(用于处理java程序运行中出现的异常)
public CommonResult<Payment> handlerFallback(@PathVariable("id")Long id,Throwable e){
Payment payment = new Payment(id,"null");
return new CommonResult<>(444,"java运行异常,handlerFallback,exception内容:"+e.getMessage(),payment);
}
//blockHandler处理方法(用于处理外部访问违背sentinel控制台规则的异常)
public CommonResult blockHandler(@PathVariable("id")Long id, BlockException exception){
Payment payment = new Payment(id,"null");
return new CommonResult<>(445,"sentinel控制台限流异常,blockException:"+exception.getMessage(),payment);
}
若fallback、blockHandler都进行了配置,当出现两种情况的异常时只会进入blockHandler处理逻辑。
(9)Sentinel持久化规则
A、启动8401子模块,访问http://localhost:8401/rateLimit/byUrl,在sentinel控制台中添加流控规则:
B、重启8401子模块,再次访问http://localhost:8401/rateLimit/byUrl发现流控规则已经不起作用
C、修改8401子模块实现sentinel流控规则持久化
<!-- SpringCloud alibaba sentinel-datasource-nacos:用于持久化 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
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
datasource:
dsl:
nacos:
server-addr: localhost:8848
dataId: cloudalibaba-sentinel-service
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow
management:
endpoints:
web:
exposure:
include: '*'
D、添加Nacos业务规则配置
[
{
"resource": 资源名称
"limitApp": 来源应用
"greate": 阈值类型:0->线程数,1->QPS
"count": 单机阈值
"strategy": 流控模式:0->直接,1->关联,2->链路
"controlBehavior": 流控效果:0->快速失败,1->Warm Up,2->排队等候
"clusterMode": 是否集群
}
]
nacos发布之后重启8401然后访问以下流控规则的rest地址:
单体应用被拆分成微服务应用,原来的三个模块被拆分成三个独立的应用,分别使用三个独立的数据源。
业务操作需要调用三个服务来完成。此时每个服务内部的数据一致性由本地事务来保证,但是全局的数据一致性问题没法保证。
例如:
用户购买商品的业务逻辑。整个业务逻辑由三个微服务提供支持
Seata是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。
中文官网:点击访问
中文文档:点击访问
(1)一个典型的分布式事务过程
分布式事务处理过程的一ID+三组件模型:
Transaction ID XID
-全局唯一的事务ID
三组件概念
–TC (Transaction Coordinator) - 事务协调者:维护全局和分支事务的状态,驱动全局事务提交或回滚。
–TM (Transaction Manager) - 事务管理器:定义全局事务的范围:开始全局事务、提交或回滚全局事务。
–RM (Resource Manager) - 资源管理器:管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
(2)Seata下载
下载地址:点击访问
(1)之前下载windows版Seata压缩包后解压到本地目录下,进入seate文件夹下的conf,修改file.conf(修改之前先备份)
主要修改:自定义事务组名称+事务日志存储模式为db+数据库连接信息
在conf目录下找到db_store.sql数据库脚本文件并运行:
运行之后会在seata数据库下生成三个表(分支表、全局表、锁表):
(3)在conf目录下找到registry.conf配置文件并修改
(4)先启动nacos端口号8848,在启动seata
先等Nacos启动并访问成功后,在启动Seate:
启动遇到了一些问题即解决方法:
我笔记本电脑上装的MySQL版本为8.0+,启动时一直报数据库创建连接失败,后来经过网上查询知道是jdbc的jar版本过低导致的,因为Seata1.0 lib目录下的jdbc jar包版本为5.0+,需要换成8.0+才能访问到数据库8.0+版本的,可以下载Seata1.4+进入lib目录下手动将jdbc jar包替换进Seata中就可以了!
进入Nacos服务列表可以查看到注册进Nacos中的Seata:
(1)AT模式
前提
整体机制
两个阶段提交协议的演变
A、一阶段加载
在一阶段,Seata会拦截“业务SQL”
B、二阶段提交
如果提交顺利的话,因为“业务SQL”在一阶段已经提交至数据库,所以Seata框架只需要将一阶段保存的快照数据和行锁删掉,完成数据清理即可。
C、二阶段回滚