zoukankan      html  css  js  c++  java
  • Hystrix-request cache(请求缓存)

    开启请求缓存

      请求缓存在run()和construce()执行之前生效,所以可以有效减少不必要的线程开销。你可以通过实现getCachekey()方法来开启请求缓存。

    package org.hope.hystrix.example.request.cache;
    
    import com.netflix.hystrix.HystrixCommand;
    import com.netflix.hystrix.HystrixCommandGroupKey;
    
    public class CommandUsingRequestCache extends HystrixCommand<Boolean> {
        private final int value;
    
        public CommandUsingRequestCache(int value) {
            super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
            this.value = value;
        }
    
        @Override
        protected Boolean run() throws Exception {
            return value == 0 || value % 2 == 0;
        }
    
        @Override
        protected String getCacheKey() {
            return String.valueOf(value);
        }
    }

    单元测试

    package org.hope.hystrix.example.request.cache;
    
    import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;
    import org.hope.hystrix.example.request.cache.CommandUsingRequestCache;
    import org.junit.Test;
    
    import static org.junit.Assert.assertEquals;
    import static org.junit.Assert.assertFalse;
    import static org.junit.Assert.assertTrue;
    
    public class CommandUsingRequestCacheTest {
    
        @Test
        public void testWithoutCacheHits() {
            HystrixRequestContext cxt = HystrixRequestContext.initializeContext();
            try {
                assertTrue(new CommandUsingRequestCache(2).execute());
                assertTrue(new CommandUsingRequestCache(1).execute());
            } finally {
                cxt.shutdown();
            }
        }
    
        @Test
        public void testWithCacheHits() {
            HystrixRequestContext cxt = HystrixRequestContext.initializeContext();
            try {
                CommandUsingRequestCache command2a = new CommandUsingRequestCache(2);
                CommandUsingRequestCache command2b = new CommandUsingRequestCache(2);
    
                assertTrue(command2a.execute());
                // this is the first time we've executed this command with the value of "2" so it should not be from cache
    //            assertFalse(command2a.isResponseFromCache());
                System.out.println(command2a.isResponseFromCache());
    
                assertTrue(command2b.execute());
                // this is the second time we've executed this command with the same value so it should return from cache
    //            assertTrue(command2b.isResponseFromCache());
                System.out.println(command2b.isResponseFromCache());
            } finally {
                cxt.shutdown();
            }
    
            // start a new request context
            cxt = HystrixRequestContext.initializeContext();
            try {
                CommandUsingRequestCache command3b = new CommandUsingRequestCache(2);
                assertTrue(command3b.execute());
                // this is a new request context so this should not come from cache
    //            assertFalse(command3b.isResponseFromCache());
                System.out.println(command3b.isResponseFromCache());
            } finally {
                cxt.shutdown();
            }
        }
    }

    清理失效缓存

    package org.hope.hystrix.example.request.cache;
    
    
    import com.netflix.hystrix.HystrixCommand;
    import com.netflix.hystrix.HystrixCommandGroupKey;
    import com.netflix.hystrix.HystrixCommandKey;
    import com.netflix.hystrix.HystrixRequestCache;
    import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategyDefault;
    
    /**
     * 清理缓存
     */
    public class CommandUsingRequestCacheInvalidation{
    
        private static volatile String prefixStoredOnRemoteDataStore = "ValueBeforeSet_";
    
        public static class GetterCommand extends HystrixCommand<String> {
            private static final HystrixCommandKey GETTER_KEY = HystrixCommandKey.Factory.asKey("GetterCommand");
            private final int id;
            public GetterCommand(int id) {
                super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("GetSetGet")).andCommandKey(GETTER_KEY));
                this.id = id;
            }
    
            @Override
            protected String run() throws Exception {
                return prefixStoredOnRemoteDataStore + id;
            }
    
            @Override
            protected String getCacheKey() {
                return String.valueOf(id);
            }
    
            //Allow the cache to be flushed for this object.
            public static void flushCache(int id) {
                HystrixRequestCache.getInstance(GETTER_KEY, HystrixConcurrencyStrategyDefault.getInstance()).clear(String.valueOf(id));
            }
    
        }
    
        public static class SetterCommand extends HystrixCommand<Void> {
            private final int id;
            private final String prefix;
    
            public SetterCommand(int id, String prefix) {
                super(HystrixCommandGroupKey.Factory.asKey("GetSetGet"));
                this.id = id;
                this.prefix = prefix;
            }
    
    
            @Override
            protected Void run() throws Exception {
                // persist the value against the datastore
                prefixStoredOnRemoteDataStore = prefix;
                // flush the cache
                GetterCommand.flushCache(id);
                return null;
            }
        }
    
    }

    单元测试:

    package org.hope.hystrix.example.request.cache;
    
    import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;
    import org.junit.Test;
    
    /**
     * Created by lisen on 2017/12/27.
     */
    public class CommandUsingRequestCacheInvalidationTest {
    
        @Test
        public void flushCacheTest() {
            HystrixRequestContext context = HystrixRequestContext.initializeContext();
            System.out.println(new CommandUsingRequestCacheInvalidation.GetterCommand(1).execute());
    
            CommandUsingRequestCacheInvalidation.GetterCommand commandAgainstCache = new CommandUsingRequestCacheInvalidation.GetterCommand(1);
    
            System.out.println(commandAgainstCache.isResponseFromCache()); //false
            System.out.println(commandAgainstCache.execute());
            System.out.println(commandAgainstCache.isResponseFromCache()); //false
            // set the new value
            new CommandUsingRequestCacheInvalidation.SetterCommand(1, "ValueAfterSet_").execute();
            // fetch it again
            CommandUsingRequestCacheInvalidation.GetterCommand commandAfterSet = new CommandUsingRequestCacheInvalidation.GetterCommand(1);
            //the getter should return with the new prefix, not the value from cache
            System.out.println(commandAfterSet.isResponseFromCache());
            System.out.println(commandAfterSet.execute());
        }
    }

    注解的实现请求缓存

    注解 描述 属性
    @CacheResult 改注解用来标记请求命令返回的结果应该被缓存,它必须与@HystrixCommand注解结合使用 cacheKeyMethod
    @CacheRemove 该注解用来让请求命令的缓存失效,失效的缓存根据定义的key决定 commandKey,cacheKeyMethod
    @CacheKey

    改注解用来在请求命令的参数上标记,使其作为缓存的Key值,如果没有标注则会使用所有参数。如果同时还使用了@CacheResult和

    @CacheRemove注解的cacheKeyMethod方法指定缓存Key的生成,那么该注解将不会起作用

    value

    设置缓存

    package org.hope.hystrix.example.request.cache;
    
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheKey;
    import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheResult;
    import org.hope.hystrix.example.model.User;
    import org.springframework.stereotype.Service;
    @Service public class RequestCacheAnnotation { /** * 返回的结果会置入请求缓存中,缓存的key值会使用所有的方法入参, * 也就是这里Long类型的id */ @CacheResult @HystrixCommand public String getUserById(Long id) { return "你好" + id; } /** * cacheKeyMethod可以为缓存指定具体的缓存key */ @CacheResult(cacheKeyMethod = "getUserByIdCacheKey") @HystrixCommand public String getUserById2(Long id) { return "你好:" + id; } public String getUserByIdCacheKey(Long id) { return String.valueOf(id); } /** * 通过@CacheKey来定义具体的缓存Key。 * 但是注意,@CacheKey的优先级比@CacheResult(cacheKeyMethod = "")的优先级低。 * 如果已经使用了cacheKeyMethod指定缓存Key的生成函数,那么@CacheKey注解不会生效 */ @CacheResult @HystrixCommand public String getUserById3(@CacheKey("id") Long id) { return "你好:" + id; } /** * @CacheKey还可以通过访问参数对象内部属性作为缓存key * 这里指定了User对象id属性作为缓存key */ @CacheResult @HystrixCommand public String getUserById4(@CacheKey("id") User user) { return "你好" + user.getId(); } }

    清理缓存

    package org.hope.hystrix.example.request.cache;
    
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheKey;
    import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheRemove;
    import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheResult;
    import org.hope.hystrix.example.model.User;
    
    public class RequestClearCacheAnnotation {
    
        @CacheResult
        @HystrixCommand
        public User getUserById(@CacheKey("id") Long id) {
            User u = new User();
            u.setId(id);
            return u;
        }
    
        /**
         * 用@CacheRemove来清理失效缓存,其中commandKey是必须指定的
         */
        @CacheRemove(commandKey = "getUserById")
        @HystrixCommand
        public void update(@CacheKey("id") User user) {
            User u = new User();
            u.setId(20L);
        }
    
        public String getUserById(User user) {
            return String.valueOf(user.getId());
        }
    }

    https://gitee.com/huayicompany/Hystrix-learn/tree/master/hystrix-example

    参考:

    [1]Github,https://github.com/Netflix/Hystrix/wiki/How-it-Works

    [2] 《SpringCloud微服务实战》,电子工业出版社,翟永超

  • 相关阅读:
    Azure PowerShell (2) 修改Azure订阅名称
    Windows Azure Platform Introduction (11) 了解Org ID、Windows Azure订阅、账户
    Azure PowerShell (3) 上传证书
    Azure PowerShell (1) PowerShell入门
    Windows Azure Service Bus (2) 队列(Queue)入门
    Windows Azure Service Bus (1) 基础
    Windows Azure Cloud Service (10) Role的生命周期
    Windows Azure Cloud Service (36) 在Azure Cloud Service配置SSL证书
    Android studio 使用心得(一)—android studio快速掌握快捷键
    android 签名、混淆打包
  • 原文地址:https://www.cnblogs.com/happyflyingpig/p/8119754.html
Copyright © 2011-2022 走看看