springcloudalibaba入门(三)

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实现动态规则配置

image.png

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服务上

image.png
image.pngimage.png

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入门(四)

  • 18
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值