-
- 1.1. nacos作为注册中心
- 1.1.1. 使用步骤
- 1.2. nacos作为配置中心
- 1.1. nacos作为注册中心
-
- 2.1. 主要特性
- 2.2. 使用步骤
- 2.3. 流控规则
- 2.4. 熔断降级
- 2.5. 热点限流
- 2.6. 系统规则
- 2.7. @SentinelResource
- 2.7.1. 处理服务降级
- 2.7.2. 处理业务内部的异常
- 2.7.3. fallback和blockHandler属性的区别
- 2.8. sentinel整合open feign
- 2.9. sentinel数据持久化到nacos
- 2.9.1. 步骤
spring cloud alibaba
根pom仍然使用springcloud的
1 | <dependencyManagement> |
1. nacos
Nacos = Eureka + Config + Bus
nacos可以切换 AP 和 CP ,可使用如下命令切换成CP模式:
docker启动nacos,MODE=standalone 为单机模式,还可以调成集群模式
1 | docker run --env MODE=standalone --name nacos -d -p 8848:8848 9c0b55a5ab2c |
1.1. nacos作为注册中心
1.1.1. 使用步骤
- 引入nacos
1 | <!-- springcloud alibaba nacos 依赖 --> |
- 配置yml,注册进nacos并暴露端点
1 | spring: |
主启动类加上@EnableDiscoveryClient
1
2
3
4
5
6
7
8
public class NacosProviderMain9001 {
public static void main(String[] args) {
SpringApplication.run(NacosProviderMain9001.class, args);
}
}消费者若要使用resttemplate,则要加上@LoadBalanced注解,因为nacos自带ribbon,否则报错500
访问8848端口,用户名和密码默认都是nacos
此时和使用eureka一样访问nacos
1.2. nacos作为配置中心
nacos 作为配置中心,不需要像springcloud config 一样做一个Server端模块。
1.2.1. 使用步骤
引入nacos
配置bootstrap.yml文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16# bootstrap.yml
server:
port: 3377
spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
server-addr: 192.168.124.5:8848 # nacos作为服务注册中心
config:
server-addr: 192.168.124.5:8848 # nacos作为服务配置中心
file-extension: yaml # 指定yaml 格式的配置
group: DEFAULT_GROUP # 指定分组,默认为DEFAULT_GROUPe
namespace: public # 默认为public,namespace下有group,group中按dataId划分在获取配置信息的方法上加上注解@RefreshScope,nacos无需post刷新,其会自动进行刷新。当修改配置值,会发现 3377 上也已经修改,Nacos自带自动刷新功能
在nacos上新建配置文件,其配置文件的规则如下图所示
从上面可以看到重要的一点,配置文件的名称第二项,spring.profiles.active
是依据当前环境的profile属性值的,也就是这个值如果是 dev,即开发环境,它就会读取 dev
的配置信息,如果是test,测试环境,它就会读取test的配置信息,就是从 spring.profile.active
值获取当前应该读取哪个环境下的配置信息。
5. 新建application.yml,配置profile属性值
1 | # application.yml |
- nacos和springcloud-config一样,在项目初始化时,要保证先从配置中心进行配置拉取,拉取配置之后,才能保证项目的正常启动
1.2.2. 其他说明
Nacos 的 Group ,默认创建的配置文件,都是在DEFAULT_GROUP中,可以在创建配置文件时,给文件指定分组。
yml 配置如下,当修改开发环境时,只会从同一group中进行切换。
Nacos 的namespace ,默认的命名空间是public ,这个是不允许删除的,可以创建一个新的命名空间,会自动给创建的命名空间一个流水号。
在yml配置中,指定命名空间:
最后,dataid、group、namespace 三者关系如下:(不同的dataid,是相互独立的,不同的group是相互隔离的,不同的namespace也是相互独立的)
2. sentinel
sentinel在 springcloud Alibaba 中的作用是实现熔断和限流
2.1. 主要特性
2.2. 使用步骤
- 引入sentinel和nacos
1 | <dependency> |
- 启动sentinel的jar包,使用java -jar 命令
- 配置sentinel
1 | server: |
- 使用nacos就要加入@EnableDiscoveryClient注解
- 访问localhost:8080,访问界面,用户名和密码都是sentinel
- 创建一个controller类,需要对微服务的资源进行访问,sentinel中才会有资源名称,此时可以对其进行配置。
2.3. 流控规则
可以在sentinel图形界面上对微服务的资源进行流控规则的配置,如此时对微服务8401的/byResource资源配置流控规则
2.3.1. 流控模式–直接
限流表现:当超过阀值,就会被降级。
2.3.2. 流控模式–关联
当关联的资源达到阈值时,就限流自己
例如:当与A关联的资源B达到阈值后,就限流A自己
2.3.3. 流控效果–预热
默认阈值从3开始
2.3.4. 流控效果–排队等待
2.4. 熔断降级
entinel没有半开模式,和hystrix不同
- 慢调用比例 (SLOW_REQUEST_RATIO):选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。
- 异常比例 (ERROR_RATIO):当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
- 异常数 (ERROR_COUNT):当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断
2.4.1. 降级策略–RT
2.4.2. 降级策略–异常比例
2.4.3. 降级策略–异常数
当testE资源的方法中有除数为0的异常时,61s内前5次会将异常展现到界面上,当超过5次后会显示降级页面
2.5. 热点限流
即热点限流可以用来限制指定的资源,针对于某一参数进行限制,下面的配置是使参数p1一秒只能请求一次。
还可以在高级选项中配置参数例外项
2.6. 系统规则
一般配置在网关或者入口应用中,但是这个东西有点危险,不但值不合适,就相当于系统瘫痪。
可以配置全局规则
2.7. @SentinelResource
@SentinelResource 注解,主要是指定资源名(也可以用请求路径作为资源名),和指定降级处理方法的。
该注解类似与hystrix的@HystrixCommand注解,用来处理服务降级和熔断的兜底方法
2.7.1. 处理服务降级
该注解可以用来处理服务降级,自定义处理服务降级方法
默认的服务降级是返回Blocked by Sentinel (flow limiting),如果想使用自己的方法来处理服务降级,需要在注解的blockHandler属性中指明兜底方法
1 |
|
此时降级后不会返回Blocked by Sentinel,而是返回testHotkey__fail
2.7.2. 处理业务内部的异常
要处理java的异常,需要使用其fallback属性指明fallback方法,当业务方法出现异常时,不会将异常错误500发送到页面上,而是显示一个友好的提示
1 | /** |
此时如果业务抛出异常,不会将异常错误直接返回前台,而是返回一个json数据,表示参数异常
忽略异常
可以使用exceptionsToIgnore属性来指定fallback所忽略的异常
exceptionsToIgnore = IllegalArgumentException.class
忽略IllegalArgumentException异常
2.7.3. fallback和blockHandler属性的区别
- fallback用于处理业务异常,不会管sentinel控制台配置的各种规则所产生的服务降级和熔断
- blockHandler只负责sentinel控制台配置违规,如果报java异常不管
- 如果两个属性都配置了兜底方法,假如产生了降级,那么fallback方法就不会生效,而是使用blockHandler的方法来兜底;如果未违规,但是业务方法产生了异常,就会使用fallback的方法兜底
1 |
|
2.8. sentinel整合open feign
使用sentinel整个open feign,需要引入sentinel和feign的pom,并在配置文件中配置sentinel对feign的支持
1 | feign: |
其余和操作hystrix一样,包括配置全局降级类也是一样,只需要实现feign调用方法的接口,并使用FeignClient指明兜底类即可
@FeignClient(value = “nacos-payment-provider”, fallback = PaymentFallbackService.class)
2.9. sentinel数据持久化到nacos
sentinel的数据默认是不持久的,如果微服务关闭后再启动,之前配置的各种规则都会消失
此时可以持久化到nacos的数据库中
2.9.1. 步骤
- 加入持久化所需的pom
1 | <!-- 后续做Sentinel的持久化会用到的依赖 --> |
- yml配置
1 | spring: |
- nacos创建配置,dataId为配置文件中${spring.application.name}的值,加入json配置(此处是流控的配置)
- 重启微服务后,发现sentinel上仍然有关于testA资源的流控配置
总结: 就是在 sentinel 启动的时候,去 nacos 上读取相关规则配置信息,实际上它规则的持久化,就是第三步,粘贴到nacos上保存下来,就算以后在 sentinel 上面修改了,重启应用以后也是无效的。
3. seata
Seate 处理分布式事务。
微服务模块,连接多个数据库,多个数据源,而数据库之间的数据一致性需要被保证。
3.1. seata术语
1+3
3.2. 工作流程
3.3. 配置seata0.9.0版本
下载seata 0.9.0
修改 conf/file.conf 文件的service模块、store模块和db模块
创建名和 file.conf 指定一致的数据库seata,并在里面创建三个表
1 | -- the table to store GlobalSession data |
- 修改 conf/registry.conf 文件内容,改为nacos,并配置好nacos的地址
- 先启动 nacos Server 服务,再在/bin中启动seata Server,此时可以在nacos控制台中看见一个注册的服务,即为seata
3.4. seata实战
3.4.1. 数据库准备
- 在数据库中创建三个表,代表订单,余额和库存
1 | CREATE DATABASE seata_account; |
- 三个数据库都创建一个回滚日志表,seata/conf/ 有相应的sql文件
1 | -- the table to store seata xid data |
订单模块开发
- 新建模块 cloudalibaba-seata-order2001,pom文件如下
1 |
|
- yml配置,配置seata
1 | server: |
- 将 seata/conf/ 下的 file.conf 和 registry.cong 两个文件拷贝到 resource 目录下。
- 配置好seata管理mybatis的数据源,主启动类要配置排除数据源的自动配置
1 | /** |
1 | //这里必须排除数据源自动配置,因为写了配置类,让 seata 管理数据源 |
- 编写业务代码,包结构如下,service包中使用feign远程调用其他两个模块
主要业务代码,mybatis的sql书写略1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53package com.hjznb.springcloud.service.impl;
import com.hjznb.springcloud.dao.OrderDao;
import com.hjznb.springcloud.domain.AccountVo;
import com.hjznb.springcloud.domain.Order;
import com.hjznb.springcloud.service.AccountService;
import com.hjznb.springcloud.service.OrderService;
import com.hjznb.springcloud.service.StorageService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @author hjz
* @version 1.0
* @date 2021/2/5 11:13
*/
public class OrderServiceImpl implements OrderService {
private final OrderDao orderDao;
private final StorageService storageService;
private final AccountService accountService;
public OrderServiceImpl(OrderDao orderDao, StorageService storageService, AccountService accountService) {
this.orderDao = orderDao;
this.storageService = storageService;
this.accountService = accountService;
}
//name为配置文件中的tx-service-group值
public void creat(Order order) {
//1.新建订单
log.info("---->开始新建订单");
orderDao.create(order);
//2.扣减库存
log.info("---->订单微服务开始调用库存,做扣减count");
storageService.decrease(order.getProductId(), order.getCount());
log.info("---->订单微服务开始调用库存,做扣减结束");
//3.扣减账户
log.info("---->订单微服务开始调用账户,做扣减money");
accountService.decrease(new AccountVo(order.getUserId(), order.getMoney()));
log.info("---->订单微服务开始调用账户,做扣减结束");
//4.修改订单的状态status,从0到1,代表完成
log.info("---->修改订单状态");
orderDao.update(order.getUserId(), 0);
log.info("---->修改订单状态结束");
}
}
关键:在业务代码上加上事务注解
@GlobalTransactional(name = “my_test_tx_group”, rollbackFor =
Exception.class)
库存模块开发
创建库存模块seata-storage-service2002,步骤和内容基本一致,唯一大的区别就是这两个不需要导入 open-feign 远程调用其它模块。
包结构如图所示
核心业务代码
1 |
|
余额模块开发
创建模块seata-account-service2003,步骤基本一致,包结构
核心代码
1 |
|
3.4.3. 运行结果
订单表
库存表
余额表
3.4.4. 模拟超时回滚
在余额模块中模拟超时,测试seata的回滚。
1 |
|
此时订单模块的feign调用会超时,seata会对三个数据库进行回滚,结果如下
订单表中出现了一个状态为未完成的表,而其他的表的内容没有变化,说明事务回滚了