栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

sentinel 服务熔断和限流

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

sentinel 服务熔断和限流

目录

sentinel 下载安装:​

初始化监控:

流量控制:

服务降级:

热点规则:

sentinel系统规则(系统自适应限流):

@SentinelResource的配置:

Sentinel服务熔断:

exceptionsToIgnore:

Sentinel服务熔断OpenFeign:

sentinel持久化规则:


sentinel 下载安装: 访问管理页面 localhost:8080

初始化监控:
    建module导入POM
    
            
                org.springframework.cloud
                spring-cloud-starter-config
            
            
                com.alibaba.csp
                sentinel-datasource-nacos
            
            
                org.springframework.cloud
                spring-cloud-starter-stream-rabbit
            
            
                com.alibaba.cloud
                spring-cloud-starter-alibaba-sentinel
            
            
                org.springframework.cloud
                spring-cloud-starter-openfeign
            
    
            
                com.ljw.springcloudstudy
                cloud-api-commons
                ${project.version}
            
            
                org.springframework.boot
                spring-boot-starter-web
            
            
                org.springframework.boot
                spring-boot-starter-actuator
            
    
            
            
                org.springframework.cloud
                spring-cloud-starter-alibaba-nacos-discovery
                0.2.1.RELEASE
            
    
        
    

    YML

    server:
      port: 8401
    
    spring:
      application:
        name: cloudalibaba-sentinel-service
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848
        sentinel:
          transport:
            dashboard: localhost:8080
    #        默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
            port: 8719
    
    management:
      endpoints:
        web:
          exposure:
            include: "*"

    主启动

    @SpringBootApplication
    @EnableDiscoveryClient
    public class MainApp8401 {
        public static void main(String[] args) {
            SpringApplication.run(MainApp8401.class,args);
        }
    }
    

    controller

    @RestController
    public class FlowLimitController {
    
        @GetMapping("/testA")
        public String testA() {
            return "-------testA";
        }
    
        @GetMapping("/testB")
        public String testB() {
            return "-------testB";
        }
    
    }
    

    执行一次访问后访问控制台(懒加载),可以看到该服务

流量控制:
    流控模式为直接,流控效果为快速失败时:流控模式为关联时,当关联资源达到阈值时,限流自己;当testB访问达到阈值后,testA:流控效果为warm up(预热)时:一开始阈值为设定阈值/cold Factor,经过预热时长后,变为设定的阈值流控效果为排队等待时:使得请求匀速通过

服务降级: 首先是慢调用比例:
        @GetMapping("/testD")
        public String testD() {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "-------testD";
        }
    
    }
    

    配置:

    测试后发现熔断

异常比例:

        @GetMapping("/testE")
        public String testE() {
    //异常
            int age=10/0;
            return "-------testE";
        }
    

异常数:

        
        @GetMapping("/testF")
        public String testF() {
            int age=10/0;
            return "-------testF";
        }

     

热点规则:

    针对热点参数进行限流;

        
        @GetMapping("/testHotKey")
    //    作为唯一标识,一般和url统一,也就是资源名称
        @SentinelResource(value = "testHotKey", blockHandler = "dealTestHotKey")
        public String testHotKey(@RequestParam(value = "p1", required = false) String p1,
                                 @RequestParam(value = "p2", required = false) String p2) {
            return "-----testHotKey";
    
        }
    //兜底方法,如果发现了热点参数,就会走这里
        public String dealTestHotKey(String p1, String p2, BlockException exception) {
    
            return "------dealTestHotKey";
    
        }
    }
    
    制定热点规则:第一个参数在一秒钟内QPS超过了阈值,则立刻进行降级处理,携带p1也会按照这个规则进行;参数例外项:当热点参数为特殊值的时候,会有不同于其他的限流阈值;如果是运行异常,那么@SentinelResource不负责,不走该兜底方法,@SentinelResource只负责违背控制台配置的异常。
        
        @GetMapping("/testHotKey")
    //    作为唯一标识,一般和url统一,也就是资源名称
        @SentinelResource(value = "testHotKey", blockHandler = "dealTestHotKey")
        public String testHotKey(@RequestParam(value = "p1", required = false) String p1,
                                 @RequestParam(value = "p2", required = false) String p2) {
    //        模拟运行时异常
            int age =10/0;
            return "-----testHotKey";
    
        }
    //兜底方法,如果发现了热点参数,就会走这里
        public String dealTestHotKey(String p1, String p2, BlockException exception) {
    
            return "------dealTestHotKey/(ㄒoㄒ)/~~";
    
        }

sentinel系统规则(系统自适应限流):
    从整体维度对应用入口流量进行控制;以入口QPS举例:、

@SentinelResource的配置:
    按资源名称进行限流+后续处理;首先在8401中引入自定义jar包:
            
                com.ljw.springcloudstudy
                cloud-api-commons
                ${project.version}
            

    新加一个业务类:

    @RestController
    public class ReTeLimitController {
    
        @GetMapping("/byResource")
        @SentinelResource(value = "byResource",blockHandler = "handleException")
        public CommonResult byResource(){
            return new CommonResult(200,"按资源名称进行限流测试",new Payment(2020L,"serial001"));
        }
    
        public CommonResult handleException(BlockException exception){
            return new CommonResult(444,exception.getClass().getCanonicalName()+"t","服务不可用");
        }
    }
    

    添加限流条件:

    测试:

    关闭服务后,流控规则会消失(非持久化);

    如果没有自定义blockHandler方法,则会用系统自带的。


    按资源url进行限流+后续处理;

        @GetMapping("/byUrl")
    //    没有自定义blockHandler方法,将会使用默认的
        @SentinelResource(value = "byUrl")
        public CommonResult byUrl(){
            return new CommonResult(200,"按资源url进行限流测试",new Payment(2020L,"serial002"));
        }
    }

    测试: 


    自定义限流处理+解耦:创建自定义限流处理类:
    public class CustomerBlockHandler {
    
        public static CommonResult handlerException(BlockException exception){
            return new CommonResult(444,"自定义限流处理,global",new Payment(2020L,"serial003"));
        }
    
        public static CommonResult handlerException2(BlockException exception){
            return new CommonResult(444,"自定义限流处理,global",new Payment(2020L,"serial003"));
        }
    }
    
        @GetMapping("/customerBlockHandler")
    //调用限流处理的方法2
        @SentinelResource(value = "customerBlockHandler",
                blockHandlerClass = CustomerBlockHandler.class,
                blockHandler = "handlerException2")
        public CommonResult customerBlockHandler() {
            return new CommonResult(200, "自定义限流处理", new Payment(2020L, "serial003"));
        }
    }
    需要使用资源名进行限流;测试:

Sentinel服务熔断:
    新建payment服务9003,9004,消费者84服务端YML:
    server:
      port: 9003
    
    spring:
      application:
        name: nacos-payment-provider
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848
    
    management:
      endpoints:
        web:
          exposure:
            include: "*"
    服务端controller:
    @RestController
    public class PaymentController {
        @Value("${server.port}")
        public String serverPort;
    
        public static HashMap hashMap=new HashMap<>();
        static {
            hashMap.put(1L,new Payment(1L, UUID.randomUUID().toString()));
            hashMap.put(2L,new Payment(2L, UUID.randomUUID().toString()));
            hashMap.put(3L,new Payment(3L, UUID.randomUUID().toString()));
        }
    
        @GetMapping("/paymentSQL/{id}")
        public CommonResult paymentSQL(@PathVariable("id") Long id){
            Payment payment = hashMap.get(id);
            CommonResult result = new CommonResult<>(200, "from sql,serverPort" + serverPort, payment);
            return result;
        }
    
    }
    

    消费端主启动:

    @SpringBootApplication
    @EnableFeignClients
    @EnableDiscoveryClient
    public class OrderMain84 {
        public static void main(String[] args) {
            SpringApplication.run(OrderMain84.class,args);
        }
    }
    

    消费端service:

    @FeignClient(value ="nacos-payment-provider")
    public interface PaymentFeignService {
    
        @GetMapping("/paymentSQL/{id}")
        public CommonResult paymentSQL(@PathVariable("id") Integer id);
    }
    

    消费端controller

    @RestController
    public class OrderController {
        private static final String SERVICE_NAME="nacos-payment-provider";
    
        @Resource
        private PaymentFeignService paymentFeignService;
    
        @GetMapping("/consumer/fallback/{id}")
        @SentinelResource(value = "fallback")
        public CommonResult paymentSQL(@PathVariable("id") Long id){
            CommonResult result = paymentFeignService.paymentSQL(id);
            if (id == 4){
                throw new IllegalArgumentException("IllegalArgumentException,非法参数异常");
            }else if (result.getData()==null){
                throw new NullPointerException("NullPointerException,该ID没有对应记录,空指针异常");
            }
            return result;
        }
    
    }
    

    fallback负责处理运行时异常,blockhandler负责配置违规;

如果没有配fallback,那么将直接报错;

 

只配置fallback时:

    @GetMapping("/consumer/fallback/{id}")
//    配置fallback方法
    @SentinelResource(value = "fallback",fallback = "handlerFallBack")
    public CommonResult paymentSQL(@PathVariable("id") Long id){
        CommonResult result = paymentFeignService.paymentSQL(id);
        if (id == 4){
            throw new IllegalArgumentException("IllegalArgumentException,非法参数异常");
        }else if (result.getData()==null){
            throw new NullPointerException("NullPointerException,该ID没有对应记录,空指针异常");
        }
        return result;
    }

    public CommonResult handlerFallBack(@PathVariable("id") Long id,Throwable e){
        Payment payment = new Payment(id, "null");
        return new CommonResult(444,"兜底异常handlerFallBack,exception内容"+e.getMessage(),payment);
    }

 只配置blockhandler,不处理运行时异常,只处理配置违规,但是可以在配置中设置异常比例和异常数来处理运行时异常;

同时配置fallback和blockHandler:

    @GetMapping("/consumer/fallback/{id}")
//    配置fallback方法
    @SentinelResource(value = "fallback",fallback = "handlerFallBack",blockHandler = "blockHandler")
    public CommonResult paymentSQL(@PathVariable("id") Long id){
        CommonResult result = paymentFeignService.paymentSQL(id);
        if (id == 4){
            throw new IllegalArgumentException("IllegalArgumentException,非法参数异常");
        }else if (result.getData()==null){
            throw new NullPointerException("NullPointerException,该ID没有对应记录,空指针异常");
        }
        return result;
    }

    public CommonResult handlerFallBack(@PathVariable("id") Long id,Throwable e){
        Payment payment = new Payment(id, "null");
        return new CommonResult(444,"兜底异常handlerFallBack,exception内容"+e.getMessage(),payment);
    }

    public CommonResult blockHandler(@PathVariable("id") Long id, BlockException blockException){
        Payment payment = new Payment(id, null);
        return new CommonResult<>(445,"blockHandler限流,blockException"+blockException.getMessage(),payment);
    }

}

 

同时违反配置和运行报错:

 走blockHandler;


exceptionsToIgnore: 也就是发生该异常的时候,不再走fallback方法,没有降级效果;
    @GetMapping("/consumer/fallback/{id}")
//    配置fallback方法
    @SentinelResource(value = "fallback",
            fallback = "handlerFallBack",
            blockHandler = "blockHandler",
//            也就是发生该异常的时候,不再走fallback方法,没有降级效果 
            exceptionsToIgnore = {IllegalArgumentException.class})
    public CommonResult paymentSQL(@PathVariable("id") Long id){
        CommonResult result = paymentFeignService.paymentSQL(id);
        if (id == 4){
            throw new IllegalArgumentException("IllegalArgumentException,非法参数异常");
        }else if (result.getData()==null){
            throw new NullPointerException("NullPointerException,该ID没有对应记录,空指针异常");
        }
        return result;
    }

    public CommonResult handlerFallBack(@PathVariable("id") Long id,Throwable e){
        Payment payment = new Payment(id, "null");
        return new CommonResult(444,"兜底异常handlerFallBack,exception内容"+e.getMessage(),payment);
    }

    public CommonResult blockHandler(@PathVariable("id") Long id, BlockException blockException){
        Payment payment = new Payment(id, null);
        return new CommonResult<>(445,"blockHandler限流,blockException"+blockException.getMessage(),payment);
    }

 


Sentinel服务熔断OpenFeign: 消费者端YML
server:
  port: 84

spring:
  application:
    name: nacos-payment-order
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        dashboard: localhost:8080
        #        默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
        port: 8719

management:
  endpoints:
    web:
      exposure:
        include: "*"
        
#开启sentinel对feign的支持
feign:
  sentinel:
    enabled: true

主启动:

@SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
public class OrderMain84 {
    public static void main(String[] args) {
        SpringApplication.run(OrderMain84.class,args);
    }
}

service:

@FeignClient(value ="nacos-payment-provider",fallback = PaymentFeignServiceImpl.class)
public interface PaymentFeignService {

    @GetMapping("/paymentSQL/{id}")
    public CommonResult paymentSQL(@PathVariable("id") Long id);
}

通配服务降级,处理服务端宕机,服务调用失败的情况;

@Component
public class PaymentFeignServiceImpl implements PaymentFeignService {
    @Override
    public CommonResult paymentSQL(Long id) {
        return new CommonResult(444, "服务降级访问,------PaymentFeignServiceImpl",
                new Payment(id, "errorSerial"));
    }
}

sentinel持久化规则:
    需要导入POM
            
                com.alibaba.csp
                sentinel-datasource-nacos
            

    YML

    server:
      port: 8401
    
    spring:
      application:
        name: cloudalibaba-sentinel-service
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848
        sentinel:
          transport:
            dashboard: localhost:8080
            #        默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
            port: 8719
              #          持久化sentinel规则的配置
          datasource:
            ds1:
              nacos:
                server-addr: localhost:8848
                dataId: cloudalibaba-sentinel-service
                groupId: DEFAULT_GROUP
                data-type: json
                rule-type: flow
    
    management:
      endpoints:
        web:
          exposure:
            include: "*"

    在nacos中新建配置:

    其中,resource:资源名称;limitApp:来源应用; grade:阀值类型,0表示线程数,1表示QPS,count:单机阈值,strategy:流控模式,0表示直接,1表示关联,2表示链路;controlBehavior:流控效果,0表示快速失败,1表示Warm Up,2表示排队等待;clusterMode:是否集群;

    创建成功,测试:

     

    服务重启后,该规则依旧存在。 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/782535.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号