版本
- springboot : 2.2.7.RELEASE
- spring-cloud-starter-alibaba-sentinel : 2.2.2.RELEASE
- sentinel-transport-simple-http : 1.7.2
- sentinel-datasource-nacos : 1.8.0
- nacos : 1.3.2
dependency
<!-- Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<version>1.8.0</version>
</dependency>
sentinel控制台相关的规则,直接在内存中操作,无法直接持久化保存,项目重新启动后,配置的规则会丢失,所以选择了nacos进行规则的持久化保存。在nacos配置后,项目重启后仍能从nacos获取到配置的规则数据。
application.yml
application:
name: xxxxx
cloud:
sentinel:
eager: true
transport:
dashboard: 172.16.2.2:8083 # 启动的sentinel-dashboard控制台
port: 8721
heartbeat-interval-ms: 1000
datasource:
ds1: # 流控规则
nacos:
server-addr: 172.16.2.2:8848 # nacos配置中心
namespace: xxxxx
username: nacos
password: nacos
dataId: xxxxx
group: DEFAULT_GROUP
data-type: json
rule-type: flow
ds2: # 降级规则
nacos:
server-addr: 172.16.2.2:8848
namespace: xxxxx
username: nacos
password: nacos
dataId: xxxxx
group: DEFAULT_GROUP
data-type: json
rule-type: degrade
log: # sentinel 控制台 日志路径
dir: /home/xxx/csp
一些教程中配置nacos时,没有设置spring.cloud.sentinel.datasource.ds1.nacos.username和spring.cloud.sentinel.datasource.ds1.nacos.password 会在启动时由于npe问题而创建bean出错。高版本需要设置这个两个值才可以。
监听熔断器状态变化事件
@Component
public class SentinelUtil {
public static final Logger logger = LoggerFactory.getLogger(SentinelUtil.class);
private static CircuitBreakerStateChangeObserver getCircuitBreakerStateChangeObserver() {
// OPEN 、HALF-OPEN、CLOSED 状态的切换
return (prevState, newState, rule, snapshotValue) -> {
if (newState == CircuitBreaker.State.OPEN) {
// 变换至 OPEN state 时会携带触发时的值
final String content = String.format("%s -> OPEN at %s, snapshotValue=%.2f, resource=%s",
prevState.name(),
DateTimes.formatTemporal("yyyy-MM-dd HH:mm:ss",
LocalDateTime.now()),
snapshotValue, rule.getResource());
final boolean send = MailUtil.sendNotifyFailedMail("接口状态变化通知", content);
if (!send) {
logger.error("接口状态变化通知 发送失败");
}
} else {
final String content = String.format("%s -> %s at %s, snapshotValue=%.2f,resource=%s",
prevState.name(), newState.name(),
DateTimes.formatTemporal("yyyy-MM-dd HH:mm:ss",
LocalDateTime.now()),
snapshotValue, rule.getResource());
final boolean send = MailUtil.sendNotifyFailedMail("接口状态变化通知", content);
if (!send) {
logger.error("接口状态变化通知 发送失败");
}
}
};
}
@PostConstruct
public void registerStateChangeObserver() {
EventObserverRegistry.getInstance()
.addStateChangeObserver("logging", getCircuitBreakerStateChangeObserver());
}
}
这里做了简单的特定的处理,在状态变化时进行邮件通知。也可以记录到数据库中。
注意点
- @SentinelResource注解 不支持private方法,也需要spring托管的类中的方法才可以。
- 使用fallbackClass时,fallback方法必须是public static方法。
- 多个项目实例连接至sentinel控制台,不需要更改spring.cloud.sentinel.sentinel.port=xxxx(默认8719)端口,sentinel会自动尝试探测使用后面的端口。