7、sentinel集成
7.1、普通spring boot项目使用sentinel
7.1.1、引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- sentinel核心库 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.8.4</version>
</dependency>
<!-- sentinel注解支持 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
<version>1.8.4</version>
</dependency>
<!-- spring aop配合sentinel注解支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
7.1.2、定义规则可使用@PostConstruct注解
private static final String SENTINEL = "sentinel";
private static final String HELLO = "hello";
private static final String QIFENG = "qifeng";
@PostConstruct
private void initFlowRules(){
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule();
//流控的资源
rule.setResource(SENTINEL);
//流控规则为QPS
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
// 设置QPS
rule.setCount(1);
rules.add(rule);
rule = new FlowRule();
//流控的资源
rule.setResource(HELLO);
//流控规则为QPS
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
// 设置QPS
rule.setCount(1);
rules.add(rule);
FlowRuleManager.loadRules(rules);
initDegradeRule();
}
private void initDegradeRule() {
List<DegradeRule> rules = new ArrayList<>();
DegradeRule rule = new DegradeRule();
rule.setResource(HELLO);
//设置规则,熔断策略,支持慢调用比例/异常比例/异常数策略
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
// 熔断时长,单位为 s, 10 ms
rule.setTimeWindow(10);
//熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断
rule.setMinRequestAmount(2);
//统计时长(单位为 ms),如 60*1000 代表分钟级
rule.setStatIntervalMs(60*1000);
//慢调用比例模式下为慢调用临界 RT(超出该值计为慢调用);异常比例/异常数模式下为对应的阈值
rule.setCount(2);
rules.add(rule);
DegradeRuleManager.loadRules(rules);
}
7.1.3、定义资源
7.1.3.1、抛出异常的方式定义资源
//抛出异常的方式定义资源
@GetMapping("sentinel")
@ResponseBody
public String helloSentinel(){
try (Entry entry = SphU.entry(SENTINEL)) {
// 被保护的逻辑
return "hello sentinel";
} catch (BlockException ex) {
// 处理被流控的逻辑
return "请求被流控啦!!!!";
}
}
7.1.3.2、注解方式定义资源
//注解方式定义资源
// 原函数
@GetMapping("qifeng/{age}")
@ResponseBody
@SentinelResource(value = QIFENG, blockHandler = "exceptionHandler", fallback = "helloFallback")
public QiFeng qifeng(@PathVariable("age") int age) {
return new QiFeng("齐丰",age);
}
// Fallback 函数,异常处理,函数签名与原函数一致或加一个 Throwable 类型的参数.
public QiFeng helloFallback(int age,Throwable throwable) {
throwable.printStackTrace();
return new QiFeng("异常啦!!!!", age);
}
// Block 异常处理函数,参数最后多一个 BlockException,其余与原函数一致.
public QiFeng exceptionHandler(int age, BlockException ex) {
// Do some log here.
ex.printStackTrace();
return new QiFeng("请求被流控啦!!!",age);
}
//注解方式定义资源
@GetMapping("hello")
@ResponseBody
@SentinelResource(value = HELLO,blockHandler = "hellBlockHandler")
public String hell(String name){
int x = 1/0;
return "hello DegradeRule!!!";
}
// Block 异常处理函数,参数最后多一个 BlockException,其余与原函数一致.
public String hellBlockHandler(String name, BlockException ex) {
// Do some log here.
ex.printStackTrace();
return "熔断降级啦!!!!";
}
7.1.3.3、注解需要将SentinelResourceAspect注册一个为Spring Bean
@Bean
public SentinelResourceAspect sentinelResourceAspect() {
return new SentinelResourceAspect();
}
7.2、Spring Cloud整合控制台sentinel、nacos、openfeign
7.2.1、下载控制台jar包并启动
java -Dserver.port=8080 -jar sentinel-dashboard.jar
7.2.2、引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 解决 java.net.UnknownHostException -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
7.2.3、yaml配置
server:
port: 7779
spring:
main:
allow-circular-references: true
cloud:
sentinel:
transport:
# sentinel控制台地址
dashboard: 172.16.156.139:9999
port: 8720
web-context-unify: false # 关闭默认调用链路收敛
# sentinel持久化配置
datasource:
flowrule: #可以自定义
nacos:
serverAddr: 172.16.156.139:8847
username: nacos
password: nacos
groupId: SENTINEL_GROUP
# nacos上配置文件的dataId
dataId: order-feign-sentinel-win-flowrule
# 规则分类
RuleType: flow
nacos:
server-addr: 172.16.156.139:8847
discovery:
ephemeral: true #是否临时实例,false表示永久实例,掉线也不会消失
username: nacos
password: nacos
application:
name: order-feign-sentinel
---
feign:
client:
config:
# 全局使用default,指定feign默认使用feignName,如果配置了contextId必须使用contextId
stock:
# 连接超时时间,默认2s
connectTimeout: 5000
# 请求处理超时时间,默认5秒
readTimeout: 3000
# 指定feign拦截器
# requestInterceptors[0]: com.wanqi.interceptor.FeignInterceptor
loggerLevel: Full
sentinel:
# 打开 Sentinel 对 Feign 的支持
enabled: true
---
logging:
level:
com.wanqi.feign: debug
---
7.2.4、示例代码
7.2.4.1、feign接口配置与回调
public class FeignConfig {
@Bean
public StockFeignServiceFallback stockFeignServiceImpl(){
return new StockFeignServiceFallback();
}
}
/**
* name 指定调用rest接口所对应的服务名
* path 指定调用接口所在StockController类上指定的@RequestMapping("/stock")
* contextId 多个feign接口使用@FeignClient注解调用同一个名称的微服务时增加contextId属性,
* 确保每个feignclient的contextId唯一
* configuration 引入配置类
*/
@FeignClient(name = "stock-service", path = "/stock"
, contextId = "stock"
, fallback = StockFeignServiceFallback.class
, configuration = {FeignConfig.class}
)
public interface StockFeignService {
@RequestMapping("/test1")
String test1();
@RequestMapping("/test2")
String test2();
@RequestMapping("/get/{id}")
public String getById(@PathVariable("id") int id);
}
public class StockFeignServiceFallback implements StockFeignService{
@Override
public String test1() {
return "test1熔断降级啦!!!!";
}
@Override
public String test2() {
return "test2熔断降级啦!!!!";
}
@Override
public String getById(int id) {
return "接口异常熔断降级啦!!!!";
}
}
7.2.4.2、controller层
@RestController
public class OrderController {
@Autowired
private StockFeignService stockFeignService;
@GetMapping("/test1")
public String test1(){
return stockFeignService.test1();
}
@GetMapping("/test2")
public String test2(){
return stockFeignService.test2();
}
/**
* 热点参数流控须要使用Sentinel
* @param id
* @return
*/
@RequestMapping("/get/{id}")
@SentinelResource(value = "getById",blockHandler = "getByIdBlockHandler")
public String getById(@PathVariable("id") int id){
return stockFeignService.getById(id);
}
public String getByIdBlockHandler(int id, BlockException e){
return "getByIdBlockHandler--热点异常处理" + id;
}
}
7.2.4.3、启动类
@SpringBootApplication
// 开启nacos
@EnableDiscoveryClient
// 开启feign
@EnableFeignClients
public class OrderFeignSentinelApplication {
public static void main(String[] args) {
SpringApplication.run(OrderFeignSentinelApplication.class,args);
}
}
7.2.4.4、nacos实现动态规则配置
7.2.4.4.1、yaml配置增加
spring:
cloud:
sentinel:
datasource:
flowrule: #可以自定义
nacos:
serverAddr: 172.16.156.139:8847
username: nacos
password: nacos
groupId: SENTINEL_GROUP
dataId: order-feign-sentinel-win-flowrule
RuleType: flow
@GetMapping("/sentinel/nacos")
@SentinelResource(value = "sentinelNacos",blockHandler = "sentinelNacosBlockHandler"
, fallback ="sentinelNacosFallback")
public String sentinelNacos(){
return "sentinelNacos正常返回!!!";
}
// Fallback 函数,异常处理,函数签名与原函数一致或加一个 Throwable 类型的参数.
public String sentinelNacosFallback(Throwable throwable) {
return "Fallback: "+ throwable.getMessage();
}
// Block 异常处理函数,参数最后多一个 BlockException,其余与原函数一致.
public String sentinelNacosBlockHandler(BlockException ex) {
// Do some log here.
return "BlockHandler: "+ ex.getMessage();
}
8、Spring Cloud Gateway
- 可以使用nginx实现负载均衡
8.1、引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--spring cloud gateway-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- spring cloud gateway整合sentinel的依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<!-- sentinel的依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 解决 java.net.UnknownHostException -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
8.2、yaml配置
server:
port: 9527
spring:
application:
name: api-gateway
cloud:
## 整合sentinel,配置sentinel控制台的地址
sentinel:
transport:
## 指定控制台的地址,默认端口8080
dashboard: 172.16.156.139:9999
port: 8722
nacos:
## 注册中心配置
discovery:
# nacos的服务地址,nacos-server中IP地址:端口号
server-addr: 172.16.156.139:8847
username: nacos
password: nacos
gateway:
## 路由
routes:
## id只要唯一即可,名称任意
- id: gateway-provider
# 需要转发的地址
#lb://service-name
#lb:uri 的协议,表示开启 Spring Cloud Gateway 的负载均衡功能。
#service-name:服务名,Spring Cloud Gateway 会根据它获取到具体的微服务地址。
uri: lb://stock-service
## 配置断言
predicates:
# Path Route Predicate Factory断言,满足/stock-service/**这个请求路径的都会被路由到stock-service这个服务中
# 自定义前缀避免接口重复
- Path=/stock-service/**
# 过滤器,转发之前过滤掉第一层路径即stock-service/
# http://localhost:9527/stock-service/stock/get/1 转发到stock-service服务上,http://stock-service/stock/get/1
filters:
- StripPrefix=1
8.3、访问http://localhost:9527/stock-service/stock/get/1会自动路由到stock-service服务上
8.4、自定义全局流控异常
@Configuration
public class GatewayConfig {
@PostConstruct
public void init(){
BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
Map<String,Object> map = new HashMap<>();
map.put("code", HttpStatus.TOO_MANY_REQUESTS.value());
map.put("msg", "请求太多,限流了");
return ServerResponse.status(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(map);
}
};
GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}
}
springcloudalibaba入门(一)
springcloudalibaba入门(二)
springcloudalibaba入门(四)