1. 程式人生 > >Dubbo之旅--結果快取

Dubbo之旅--結果快取

     在上篇文章中我們隊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

    <!-- 提供方應用資訊,用於計算依賴關係 -->

    <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       

    <!-- 消費方應用名,用於計算依賴關係,不是匹配條件,不要與提供方一樣-->

    <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整合,可以橋接各種快取實現。

除此之外,我們還可以自定義擴充套件快取。