• 微服务组件Sentinel (Hystrix)详细分析


    1 微服务组件Sentinel (Hystrix)

    1、分布式系统遇到的问题

     

     

     

     

     

    什么是缓存雪崩、击穿、穿透?

    如何解决它们

    redis
    ​
    缓存雪崩 
    指缓存中数据大批量到过期时间,而查询数据量巨大,请求都直接访问数据库,引起数据库压力过大甚至down机。
    ​
    于大量数据同时过期造成的,对于这个原因,可通过均匀设置过期时间解决,即让过期时间相对离散一点。如采用一个较大固定值+一个较小的随机值,5小时+0到1800秒酱紫。
    ​
    Redis 故障宕机也可能引起缓存雪奔。这就需要构造Redis高可用集群啦。
    ​
    ​
    ​
    缓存穿透 
    :指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,进而给数据库带来压力。
    ​
    如果是非法请求,我们在API入口,对参数进行校验,过滤非法值。
    ​
    如果查询数据库为空,我们可以给缓存设置个空值,或者默认值。但是如有有写请求进来的话,需要更新缓存哈,以保证缓存一致性,同时,最后给缓存设置适当的过期时间。(业务上比较常用,简单有效)
    ​
    使用布隆过滤器快速判断数据是否存在。即一个查询请求过来时,先通过布隆过滤器判断值是否存在,存在才继续往下查。
    ​
    布隆过滤器原理:它由初始值为0的位图数组和N个哈希函数组成。一个对一个key进行N个hash算法获取N个值,在比特数组中将这N个值散列后设定为1,然后查的时候如果特定的这几个位置都为1,那么布隆过滤器判断该key存在。
    ​
    ​
    缓存击穿
    指热点key在某个时间点过期的时候,而恰好在这个时间点对这个Key有大量的并发请求过来,从而大量的请求打到db。
    ​
    缓存击穿看着有点像,其实它两区别是,缓存雪奔是指数据库压力过大甚至down机,缓存击穿只是大量并发请求到了DB数据库层面。可以认为击穿是缓存雪奔的一个子集吧。有些文章认为它俩区别,是区别在于击穿针对某一热点key缓存,雪奔则是很多key。
    ​
    1.使用互斥锁方案。缓存失效时,不是立即去加载db数据,而是先使用某些带成功返回的原子操作命令,如(Redis的setnx)去操作,成功的时候,再去加载db数据库数据和设置缓存。否则就去重试获取缓存。
    ​
    2. “永不过期”,是指没有设置过期时间,但是热点数据快要过期时,异步线程去更新和设置过期时间。
    ​
    ​
    ​

     

    解决方案 常见的容错机制:

    超时机制

    在不做任何处理的情况下,服务提供者不可用会导致消费者请求线程强制等待,而造成系统资源耗尽。加入超时机制,  一旦超时,就释放资源。由于释放资源速度较快,一定程度上可以抑制资源耗尽的问题。

    服务限流

     

    隔离

    原理:用户的请求将不再直接访问服务,而是通过线程池中的空闲线程来访问服务,如果线程池已满,则会进行降级  处理,用户的请求不会被阻塞,至少可以看到一个执行结果(例如返回友好的提示信息),而不是无休止的等待或者看  到系统崩溃。

    信号隔离:
    信号隔离也可以用于限制并发访问,防止阻塞扩散, 与线程隔离最大不同在于执行依赖代码的线程依然是请求线程(该线程需要通过信号申请, 如果客户端是可信的且可以快速返回,可以使用信号隔离替换线程隔离,降低开销。信号量的大小可以动态调整, 线程池大小不可以。 

    服务熔断

    远程服务不稳定或网络抖动时暂时关闭,就叫服务熔断。
    现实世界的断路器大家肯定都很了解,断路器实时监控电路的情况,如果发现电路电流异常,就会跳闸,从而防止电路  被烧毁。
    软件世界的断路器可以这样理解:实时监测应用,如果发现在一定时间内失败次数/失败率达到一定阈值,就“跳闸”,断路  器打开——此时,请求直接返回,而不去调用原本调用的逻辑。跳闸一段时间后(例如10秒),断路器会进入半开状
    态,这是一个瞬间态,此时允许一次请求调用该调的逻辑,如果成功,则断路器关闭,应用正常调用;如果调用依然不  成功,断路器继续回到打开状态,过段时间再进入半开状态尝试——通过”跳闸“,应用可以保护自己,而且避免浪费资  源;而通过半开的设计,可实现应用的“自我修复“。
    所以,同样的道理,当依赖的服务有大量超时时,在让新的请求去访问根本没有意义,只会无畏的消耗现有资源。比如   我们设置了超时时间为1s,如果短时间内有大量请求在1s内都得不到响应,就意味着这个服务出现了异常,此时就没有必  要再让其他的请求去访问这个依赖了,这个时候就应该使用断路器避免资源浪费。
    

     

    服务降级

    有服务熔断,必然要有服务降级。
    所谓降级,就是当某个服务熔断之后,服务将不再被调用,此时客户端可以自己准备一个本地的fallback(回退)回调,  返回一个缺省值。 例如:(备用接口/缓存/mock数据)  。这样做,虽然服务水平下降,但好歹可用,比直接挂掉要强,当然这也要看适合的业务场景。

    2 阿里巴巴sentinel

     

    Sentinel**快速开始**

    第一步导入pom依赖

            <dependency>
                <groupId>com.alibaba.csp</groupId>
                <artifactId>sentinel-core</artifactId>
                <version>1.8.1</version>
            </dependency>

    第二步配置yml

    server:
      port: 12004
    spring:
      application:
        name: nacossentinel

    第三步配置controller

    @RestController
    @RequestMapping("/sent-serv")
    public class InitCtrl {
        private static final String RESOURCE_NAME_FIND="find";
    ​
        @RequestMapping("/find")
        public String find(){
    ​
            try {
                //在这里设置一个资源(流量)管理的监听器(名字随便)
                //人话:就是加个监听器
                Entry entry = SphU.entry(RESOURCE_NAME_FIND);
                return "hello , world";
            } catch (BlockException e) {
                return "我被限流了。。。。";
            }catch (Exception e){
                return "我的服务要降级了。。。。";
            }
        }
        //在控制器对象创建时 先创建资源管理监听器的触发规则
        //人话: 触发监听器
        @PostConstruct
        private static void init(){
            ArrayList<FlowRule> rules = new ArrayList<>();
            FlowRule rule = new FlowRule();
            //填放被管理的资源
            rule.setResource(RESOURCE_NAME_FIND);
            //设置流量规则
            rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
            //限制每秒访问次数
            rule.setCount(1);
            rules.add(rule);
            //讲规则集合存放到规则管理器中
            FlowRuleManager.loadRules(rules);
        }
    }

    第四步启动 测试

    http://localhost:12004/sent-serv/find

    bean的生命周期
    实例化  初始化 服务 销毁
    ​
    导入pom 
    spring-core spring-context spring-beans
    ​
    写一个服务类
    public class MyService{
        priavate String name;
    }
    ​
    配置spring.xml
    <beans>
        <bean id="ms" class="com.kgc.MyService" init-method="init"></bean>
    </beans>

    sentinel 实现二(配置切面 异常低侵入式)

    第一步导入pom依赖

            <dependency>
                <groupId>com.alibaba.csp</groupId>
                <artifactId>sentinel-annotation-aspectj</artifactId>
                <version>1.8.1</version>
            </dependency>

    第二步配置config类 配置切面支持

    @Configuration
    public class SentinelConfiguration {
        @Bean
        public SentinelResourceAspect sentinelResourceAspect(){
            return  new SentinelResourceAspect();
        }
    }

    第三步配置controller

    @RestController
    @RequestMapping("/sent-serv")
    public class InitCtrl {
        private static final String RESOURCE_NAME_FIND="find";
    ​
    //    @RequestMapping("/find")
    //    public String find(){
    //
    //        try {
    //            //在这里设置一个资源(流量)管理的监听器(名字随便)
    //            //人话:就是加个监听器
    //            Entry entry = SphU.entry(RESOURCE_NAME_FIND);
    //            return "hello , world";
    //        } catch (BlockException e) {
    //            return "我被限流了。。。。";
    //        }catch (Exception e){
    //            return "我的服务要降级了。。。。";
    //        }
    //    }
        @RequestMapping("/find")
        @SentinelResource(value = "find",blockHandler = "bkHandler")
        public String find(){
            return "Hello World!";
        }
    ​
        //异常处理的方法
        public  String bkHandler(BlockException e){
            return "我又被限流了o(╥﹏╥)o";
        }
    ​
        //在控制器对象创建时 先创建资源管理监听器的触发规则
        //人话: 触发监听器
        @PostConstruct
        private static void init(){
            ArrayList<FlowRule> rules = new ArrayList<>();
            FlowRule rule = new FlowRule();
            //填放被管理的资源
            rule.setResource(RESOURCE_NAME_FIND);
            //设置流量规则
            rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
            //限制每秒访问次数
            rule.setCount(2);
            rules.add(rule);
            //讲规则集合存放到规则管理器中
            FlowRuleManager.loadRules(rules);
        }
    }

    第四步测试

    项目

     

     

     

  • 相关阅读:
    【unity与android的交互(一)】安卓打包相关的常见参数详解
    ETest系列产品1 | 便捷式嵌入式系统半实物仿真测试平台ETest_PT
    “趣说“Sybase ASE中有关字段大小计算
    QT使用MSVC编译时报错C2001: 常量中有换行符
    List接口与实现类
    如何基于原名称批量重命名(格式化)文件(夹)名
    JVM-GC
    HTML5与CSS3学习笔记【第十五章 列表】
    如何使用远程控制软件并将用途最大化?4款国内外优质应用测评解析
    严格反馈非线性系统基于事件触发的自抗扰预设有限时间跟踪控制
  • 原文地址:https://blog.csdn.net/just_learing/article/details/125568919