package org.java.boy.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowItem;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.java.boy.driver.model.Driver;
import org.java.boy.service.DriverService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping(value = "/driver")
@Slf4j
@RefreshScope
public class DriverController {
@Autowired
private DriverService driverService;
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
/****
* 司机信息
*/
@GetMapping(value = "/info/{id}")
// @SentinelResource(value = "info",blockHandler = "blockHandler")
@SentinelResource(value = "info",fallback = "follBackHandler")
public Driver info(@PathVariable(value = "id")String id){
log.info("当前服务占用的端口为:{}",port);
Driver driver = driverService.findById(id);
if (driver == null) {
throw new RuntimeException("司机id=" + id + ",不存在"); //这个异常Sentinel识别不了
// throw new SystemBlockException("info","司机id=" + id + ",不存在",null);
}
return driver;
}
public Driver blockHandler(String id, BlockException e) {
Driver driver = new Driver();
driver.setId(id);
driver.setName("系统繁忙,请稍候重试-blockHandler");
return driver;
}
public Driver follBackHandler(String id, Throwable e) {
Driver driver = new Driver();
driver.setId(id);
driver.setName("系统繁忙,请稍候重试-follBackHandler");
return driver;
}
// public Driver info(@PathVariable(value = "id")String id, HttpServletRequest request){
// Enumeration<String> headerNames = request.getHeaderNames();
// while (headerNames.hasMoreElements()){
// String name = headerNames.nextElement();
// String value = request.getHeader(name);
// System.out.println(name+":"+value);
// System.out.println("--------------------------");
// }
// return driverService.findById(id);
// }
@Value("${server.port}")
private int port;
/****
* 更新司机信息
*/
@PutMapping(value = "/status/{id}/{status}")
public Driver status(@PathVariable(value = "id")String id,@PathVariable(value = "status")Integer status){
log.info("当前服务占用的端口为:{}",port);
//修改状态
driverService.update(id,status);
//修改状态后的司机信息
return driverService.findById(id);
}
@GetMapping("/get/yml")
public String testDynamicPropertity() {
return "userName: " + username + " password: " + password;
}
/***
* 搜素指定城市的司机
*/
@SentinelResource(value = "search",fallback =
"searchFallbackHandler")
@GetMapping(value = "/search/{city}")
public Driver search(@PathVariable(value = "city")String
city){
System.out.println("查询的司机所在城市:"+city);
//假设查询到了一个司机信息
Driver driver = new Driver();
driver.setName("唐僧老师");
driver.setId("No.1");
return driver;
}
public Driver searchFallbackHandler(String city) {
//假设查询到了一个司机信息
Driver driver = new Driver();
driver.setName("searchFallbackHandler");
driver.setId("No.1");
return driver;
}
/***
* 热点参数初始化
*/
@PostConstruct
private static void initParamFlowRules() {
ParamFlowRule rule = new ParamFlowRule("search")
//参数下标为0
.setParamIdx(0)
//限流模式为QPS
.setGrade(RuleConstant.FLOW_GRADE_QPS)
//统计窗口时间长度(单位为秒)
.setDurationInSec(10)
//流控效果(支持快速失败和匀速排队模式)
//CONTROL_BEHAVIOR_DEFAULT:限流行为,直接拒绝
//CONTROL_BEHAVIOR_WARM_UP:限流行为,匀速排队
//CONTROL_BEHAVIOR_RATE_LIMITER:限流行为,匀速排队
.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT)
//最大排队等待时长(仅在匀速排队模式生效 CONTROL_BEHAVIOR_RATE_LIMITER)
//.setMaxQueueingTimeMs(600)
//最大阈值为5
.setCount(5);
/** 为特定参数单独设置规则 2、我们访问 http://localhost:18081/driver/search/天津/ 的时候,连续
执行5次,才会限流,
我们访问 http://localhost:18081/driver/search/恩施/ 的时候,连续执行
2次,就会限流,
2.3 OpenFeign支持
参看:
https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel#feign-%
E6%94%AF%E6%8C%81
Sentinel 适配了 Feign 组件。如果想使用,除了外还需要 2 个步骤:
如下配置:当参数值为恩施的时候,阈值到达2的时候则执行限流
**/
ParamFlowItem item = new ParamFlowItem()
//参数类型为String类型
.setClassType(String.class.getName())
//设置阈值为2
.setCount(2)
//需要统计的值
.setObject("恩施");
rule.setParamFlowItemList(Collections.singletonList(item));
//返回的是不可变的集合,但是这个长度的集合只有1,可以减少内存空间
//加载热点数据
ParamFlowRuleManager.loadRules(Collections.singletonList(rule));
}
}