• SpringCloud 断路器之Hystrix


    Hystrix-断路器

    在分布式环境中,许多服务依赖项中的一些必然会失败。Hystrix是一个库,通过添加延迟容忍和容错逻辑,帮助你控制这些分布式服务之间的交互。Hystrix通过隔离服务之间的访问点、停止级联失败和提供回退选项来实现这一点,所有这些都可以提高系统的整体弹性

    两个比较重要的类

      

    HystrixCommand
    HystrixObservableCommand

    注解@HystrixCommand(fallbackMethods="methods")methods中可以添加降级策略

    除了提供服务降级

    还提供了请求缓存

    @CacheResult

    @CacheRemve

    不过添加CacheResult的时候,说

    HystrixRequestContext未初始化。
    2020-01-13 16:12:10.273 ERROR 15348 --- [nio-8083-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.reflect.UndeclaredThrowableException] with root cause
    
    java.lang.IllegalStateException: Request caching is not available. Maybe you need to initialize the HystrixRequestContext?
        at com.netflix.hystrix.HystrixRequestCache.get(HystrixRequestCache.java:104) ~[hystrix-core-1.5.18.jar:1.5.18]
        at com.netflix.hystrix.AbstractCommand$7.call(AbstractCommand.java:478) ~[hystrix-core-1.5.18.jar:1.5.18]
        at com.netflix.hystrix.AbstractCommand$7.call(AbstractCommand.java:454) ~[hystrix-core-1.5.18.jar:1.5.18]
        at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:46) ~[rxjava-1.3.8.jar:1.3.8]
        at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35) ~[rxjava-1.3.8.jar:1.3.8]

    查看官方文档https://github.com/Netflix/Hystrix/wiki/How-To-Use

    Typically this context will be initialized and shut down via a ServletFilter that wraps a user request or some other lifecycle hook.

     

    在同一用户请求的上下文中,相同依赖服务的返回数据始终保持一致。在当次请求内对同一个依赖进行重复调用,只会真实调用一次。在当次请求内数据可以保证一致性

    初始化是在filter中进行(官方建议),但是每一次请求都会进行初始化 。所以说和一般的缓存还是有去别的,可以解决高并发,保证的资源的线程安全。在某些场景很有用。

    请求合并

        /**
         * 建议: 服务提供方有较高的延迟。可以考虑使用请求合并
         * HystrixCollapser 合并请求的时候会创建一个请求处理器。如果每次合并的请求量不大,只有很少的请求还要合并,会造成合并时间窗
         * 并发量增大,时间窗的创建和消耗增大。所以只有在时间窗内有很大的并发量,推荐请求合并。
         *
         * batchMethod 请求合并后的替换方法com.gitee.munan56.cloud.hystrixconsumer.AService#findALl(java.util.List)  注意客户端要有这个方法
         *HystrixProperty 一个属性合并时间窗100s 这个时间结束后会发起请求,也就是指这个时间是合并处理的时间
         * @param id
         * @return
         */
        @HystrixCollapser(batchMethod = "findALl",collapserProperties = @HystrixProperty(name = "timerDelayInMilliseconds",value = "100"))
        public String doBFindOne(String id){
    
            System.out.println("begin do provider service");
            return restTemplate.getForEntity("http://service-provider:8081/api/v1/provider/do",String.class).getBody();
        }

    全部代码

    package com.gitee.munan56.cloud.hystrixconsumer;
    
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser;
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
    import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheResult;
    import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;
    import com.netflix.ribbon.proxy.annotation.Hystrix;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.web.client.RestTemplate;
    
    import java.util.List;
    
    /**
     * @author munan
     * @version 1.0
     * @date 2020/1/13 10:41
     */
    @Service
    public class AService {
    
        @Autowired
        private RestTemplate restTemplate;
    
        public String doAService(){
            return "A Service is run";
        }
    
    //    @Hystrix(fallbackHandler = )
        @HystrixCommand(fallbackMethod = "error")
        public String doBServiceOne(){
            System.out.println("begin do provider service");
            return restTemplate.getForEntity("http://service-provider:8081/api/v1/provider/do",String.class).getBody();
        }
    
        /**
         * CacheResult  请求缓存(针对request的缓存),官方建议在serverlet filter 中初始化HystrixRequestContext
         * 在同一用户请求的上下文中缓存在统一请求的上下文环境中有效。
         * @param id
         * @return
         */
        @CacheResult(cacheKeyMethod = "getKey")
        @HystrixCommand(fallbackMethod = "error")
        public String doBServiceTwo(String id){
    
            System.out.println("begin do provider service");
            return restTemplate.getForEntity("http://service-provider:8081/api/v1/provider/do",String.class).getBody();
        }
    
        /**
         * 建议: 服务提供方有较高的延迟。可以考虑使用请求合并
         * HystrixCollapser 合并请求的时候会创建一个请求处理器。如果每次合并的请求量不大,只有很少的请求还要合并,会造成合并时间窗
         * 并发量增大,时间窗的创建和消耗增大。所以只有在时间窗内有很大的并发量,推荐请求合并。
         *
         * batchMethod 请求合并后的替换方法com.gitee.munan56.cloud.hystrixconsumer.AService#findALl(java.util.List)  注意客户端要有这个方法
         *HystrixProperty 一个属性合并时间窗100s 这个时间结束后会发起请求,也就是指这个时间是合并处理的时间
         * @param id
         * @return
         */
        @HystrixCollapser(batchMethod = "findALl",collapserProperties = @HystrixProperty(name = "timerDelayInMilliseconds",value = "100"))
        public String doBFindOne(String id){
    
            System.out.println("begin do provider service");
            return restTemplate.getForEntity("http://service-provider:8081/api/v1/provider/do",String.class).getBody();
        }
    
        @HystrixCommand()
        public String findALl(List<String> ids){
            System.out.println("begin do provider service");
            return restTemplate.getForEntity("http://service-provider:8081/api/v1/provider/do",String.class).getBody();
        }
    
        /**
         * 服务降级
         *  指定调用服务出错的回调方法
         * @return
         */
        public String error(Throwable e){
            return "do provider error this is default result" + "the error is " + e.getMessage();
        }
        /**
         *   服务降级
         *  指定调用服务出错的回调方法
         * @return
         */
        public String error(String id ,Throwable e){
            return "do provider error this is default result" + "the error is " + e.getMessage();
        }
    
    
        public String getKey(String id){
            return id;
        }
    }
  • 相关阅读:
    javascript页面刷新的几种方法
    Expo大作战(三十九)--expo sdk api之 DocumentPicker,Contacts(获取手机联系人信息),Branch
    Expo大作战(三十八)--expo sdk api之 FileSystem(文件操作系统)
    Expo大作战(三十七)--expo sdk api之 GLView,GestureHandler,Font,Fingerprint,DeviceMotion,Brightness
    Expo大作战(三十六)--expo sdk api之 ImagePicker,ImageManipulator,Camera
    Expo大作战(三十五)--expo sdk api之Location!
    一条SQL语句中算日销售额和月销售额
    绑定sql server数据库的用户与登录名
    牛腩代码生成器
    ASP.NET MVC做的微信WEBAPP中调用微信JSSDK扫一扫
  • 原文地址:https://www.cnblogs.com/munan56/p/12188935.html
Copyright © 2020-2023  润新知