Dubbo之旅--结果缓存

来源:互联网 发布:javascript call是什么 编辑:程序博客网 时间:2024/05/19 02:40
在上篇文章中我们队Dubbo的扩展进行了一些基本了解.这些扩展能够很好的帮助我们在实际的项目中发挥作用,接下来对于dubbo的一些高级特征,针对特殊情况而进行的处理进行进一步的介绍,这里我们要说的是结果缓存.

 

         为什么要用到结果缓存,主要是用于加速热门数据的访问速度,Dubbo提供声明式缓存,以减少用户加缓存的工作量。

    

          下面我们将通过一个例子来对结果缓存进行一个接触.

 

1、客户端和服务提供端共用接口类

 

packagecom.alibaba.dubbo.demo;

 

public interfaceCacheService {

    String findCache(String id);

}

 

 

2、服务提供端接口实现类

 

packagecom.alibaba.dubbo.demo.provider;

 

importjava.util.concurrent.atomic.AtomicInteger;

 

importcom.alibaba.dubbo.demo.CacheService;

 

public classCacheServiceImpl implements CacheService {

 

//AtomicInteger通过一种线程安全的加减操作接口

    private final AtomicInteger i = newAtomicInteger();

 

    @Override

    public String findCache(String id) {

        String result = "request: " +id + ", response: " + i.getAndIncrement();

        System.out.println(result);

        return result;

    }

 

}

 

 

3、服务提供端配置文件

 

<?xmlversion="1.0" encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

   xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"

   xsi:schemaLocation="http://www.springframework.org/schema/beans

    http://www.springframework.org/schema/beans/spring-beans.xsd

    http://code.alibabatech.com/schema/dubbo

    http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

 

    <!-- 提供方应用信息,用于计算依赖关系 -->

    <dubbo:applicationname="hello-world"  />

 

    <!-- 使用zookeeper注册中心暴露发现服务地址 -->

    <dubbo:registryaddress="zookeeper://127.0.0.1:2181" />

 

    <!-- 用dubbo协议在20880端口暴露服务 -->

    <dubbo:protocol name="dubbo"port="20880" />

 

    <!-- 声明需要暴露的服务接口 -->

    <dubbo:serviceinterface="com.alibaba.dubbo.demo.DemoService"ref="demoService" />

 

    <!-- 和本地bean一样实现服务 -->

    <bean id="demoService"class="com.alibaba.dubbo.demo.provider.DemoServiceImpl" />

 

    <!-- 声明需要暴露的服务接口 -->

    <dubbo:serviceinterface="com.alibaba.dubbo.demo.ValidationService"ref="validationService" />

 

    <!-- 和本地bean一样实现服务 -->

    <bean id="validationService"class="com.alibaba.dubbo.demo.provider.ValidationServiceImpl" />

    

    <bean id="cacheService"class="com.alibaba.dubbo.demo.provider.CacheServiceImpl" />

    

    <dubbo:serviceinterface="com.alibaba.dubbo.demo.CacheService"ref="cacheService" />

 

</beans>

 

 

4、客户端配置文件

 

<?xmlversion="1.0" encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

   xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"

   xsi:schemaLocation="http://www.springframework.org/schema/beans       

    http://www.springframework.org/schema/beans/spring-beans.xsd       

    http://code.alibabatech.com/schema/dubbo       

    http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

 

    <!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样-->

    <dubbo:applicationname="consumer-of-helloworld-app" />

 

    <!-- 使用zookeeper注册中心暴露发现服务地址 -->

    <dubbo:registryaddress="zookeeper://127.0.0.1:2181" />

 

    <!-- 生成远程服务代理 -->

    <dubbo:referenceid="demoService"interface="com.alibaba.dubbo.demo.DemoService"

         retries="2"

          />

 

    <!-- 生成远程服务代理 -->

    <dubbo:referenceid="validationService"interface="com.alibaba.dubbo.demo.ValidationService"

         retries="2"validation="true"

          />

    

    <!-- 生成远程服务代理 -->

    <dubbo:referenceid="cacheService"interface="com.alibaba.dubbo.demo.CacheService"cache="true" />

 

</beans>

 

 

5、客户端主类

 

importorg.springframework.context.support.ClassPathXmlApplicationContext;

 

importcom.alibaba.dubbo.demo.CacheService;

 

public class Consumer {

 

    /**

     * @param args

     * @throws Exception

     */

    public static void main(String[] args)throws Exception {

        ClassPathXmlApplicationContext context= new ClassPathXmlApplicationContext(

                new String[] {"classpath:consumer.xml" });

        context.start();

 

        CacheService cacheService =(CacheService) context.getBean("cacheService");

 

        // 测试缓存生效,多次调用返回同样的结果。(服务器端自增长返回值)

        String fix = null;

        for (int i = 0; i < 5; i++) {

            String result =cacheService.findCache("0");

            if (fix == null ||fix.equals(result)) {

               System.out.println("i=" + i + " OK: " + result);

            } else {

               System.err.println("i=" + i + " ERROR: " + result);

            }

            fix = result;

            Thread.sleep(500);

        }

 

        // LRU的缺省cache.size为1000,执行1001次,应有溢出

        for (int n = 0; n < 1001; n++) {

            String pre = null;

            for (int i = 0; i < 10; i++) {

                String result =cacheService.findCache(String.valueOf(n));

                if (pre != null &&!pre.equals(result)) {

                   System.err.println("n=" + n + " ERROR: " + result);

                }

                pre = result;

            }

        }

 

        // 测试LRU有移除最开始的一个缓存项

        String result =cacheService.findCache("0");

        if (fix != null &&!fix.equals(result)) {

            System.out.println("OK: "+ result);

        } else {

            System.err.println("ERROR:" + result);

        }

    }

}

 

 

6、客户端控制台,返回值

 

i=0 OK: request: 0,response: 0

i=1 OK: request: 0,response: 0

i=2 OK: request: 0,response: 0

i=3 OK: request: 0,response: 0

i=4 OK: request: 0,response: 0

OK: request: 0, response:1001

 

 

          使用结果缓存的服务方法必须是幂等的,也就是说,相同的输入参数返回相同的结果,参数第一次计算缓存结果,下一次相同参数传入时直接返回结果。

 


缓存策略有三种:

        1、LruCache,lru基于最近最少使用原则删除多余缓存,保持最热的数据被缓存。

        2、ThreadLocalCache,threadlocal当前线程缓存,比如一个页面渲染,用到很多portal,每个portal都要去查用户信息,通过线程缓存,可以减少这种多余访问。

        3、JCache,jcache与JSR107集成,可以桥接各种缓存实现。

除此之外,我们还可以自定义扩展缓存。

0 0
原创粉丝点击