Dubbo學習:服務降級

 

Dubbo學習(十三):服務降級

2016-04-26 16:45 4345人閱讀 評論(1) 收藏 舉報spring

 分類:網絡

Dubbo(13) 併發

版權聲明:本文爲博主原創文章,未經博主容許不得轉載。app

1、dubbo降級服務    ide

    dubbo開發中,可能因爲服務沒有啓動或者網絡不通,調用中會出現RpcException,也就是遠程調用失敗。若是是服務啓動順序的問題,可能加工check="false"的配置能夠獲得很好的解決。可是,若是是服務宕掉或者併發數過高致使的RpcException該如何處理?學習

    通過過12306搶票的人應該常常會遇到這個問題:在搶票高峯的時候,明明票還有,可是查詢出來的列表倒是爲空的(若是沒票列表也應該會呈現);等高峯事後再查詢,列表又恢復正常。我的猜想應該是查詢過程當中出現了問題,要麼超時,要麼網絡問題致使查詢失敗採用的服務降級處理。因此,最終呈現給用戶的並非內部系統出錯之類的提示,而是一個空的列表。好了,言歸正傳,在dubbo中想實現服務降級,須要怎麼樣作能夠實現?測試

    查看dubbo的官方文檔,能夠發現有個mock的配置,mock只在出現非業務異常(好比超時,網絡異常等)時執行。mock的配置支持兩種,一種爲boolean值,默認的爲false。若是配置爲true,則缺省使用mock類名,即類名+Mock後綴;另一種則是配置"return null",能夠很簡單的忽略掉異常。spa

2、結合dubbo的例子.net

說明下面將經過一個例子進行說明:代理

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

/**接口定義*/

public interface IUser {

  

    public void addUser(User u);

      

    public User getUserById(int id);

      

}

  

/**實現類*/

public class UserImpl implements IUser {

      

    private static List<User> USER_LIST = new ArrayList<User>();

      

    static{

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

            User u = new User();

            u.setAddress("address"+i);

            u.setId(i);

            u.setName("name"+i);

              

            USER_LIST.add(u);

        }

    }

      

    public void addUser(User u) {

        USER_LIST.add(u);

        System.out.println("total:"+USER_LIST.size());

    }

  

    public User getUserById(int id) {

        for(int i=0;i<USER_LIST.size();i++){

            if(USER_LIST.get(i).getId() == id){

                return USER_LIST.get(i);

            }

        }

        return null;

    }

}

 

dubbo-provider.xml配置:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="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:application name="hello-world-app" />

 

    <!-- 使用multicast廣播註冊中心暴露服務地址 -->

    <dubbo:registry address="zookeeper://127.0.0.1:2181" />

 

    <!-- 用dubbo協議在20880端口暴露服務 -->

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

 

    <!-- 聲明須要暴露的服務接口 -->

    <dubbo:service interface="com.zzq.test.iface.IUser" ref="userImpl" timeout="10000" />

 

    <!-- 和本地bean同樣實現服務 -->

    <bean id="userImpl" class="com.zzq.test.ifaceimpl.UserImpl" />

 

</beans>

調用方的配置:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="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:application name="dubbo-consumer"  />

  

    <dubbo:registry address="zookeeper://127.0.0.1:2181" />

  

    <!-- 生成遠程服務代理,能夠和本地bean同樣使用demoService -->

    <dubbo:reference id="iUser" interface="com.zzq.test.iface.IUser"  timeout="10000" check="false" mock="return null">

    </dubbo:reference>

  

</beans>

調用的測試代碼:

?

1

2

3

4

5

6

7

8

9

10

11

12

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

        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"classpath:dubbo-consumer.xml"});

        context.start();

         

        IUser iUser = (IUser)context.getBean("iUser");

        User u = new User();

        u.setAddress("aaa");

        u.setId(311);

        u.setName("n3");

        iUser.addUser(u);

        System.out.println(iUser.getUserById(1));

    }

經過測試,若是服務啓動,則程序按照預期的運行正常;若是服務沒啓動,則此時運行程序,程序並未報錯,打印出null。

3、思考

    經過以上的例子能夠知道,經過mock的配置,能夠很好的實現dubbo服務降級。可是,仔細查看上面的例子會發現,IUser自己定義了兩個接口,一個是新增用戶,一個是根據id查詢用戶信息。對於根據id查詢用戶信息,在調用失敗的時候返回null很好理解,多是因爲驗證失敗或者記錄刪除了,可是對於新增用戶,可能就須要拋出具體的業務信息,不然程序沒法處理後續的業務,包括頁面彈出」添加成功「或者列表刷新的時候沒法查看到最新的記錄,這樣體驗將會很是很差。因此,若是要有較好的區分,能夠經過如下的方式,能夠更好的實現降級:

(1)將接口進行歸類,查詢類和變動操做類:對於查詢的分爲一個接口類,變動的歸類爲其餘的接口類,這樣對於查詢的可使用mock="return null"進行降級操做;對於變動類的,能夠仍舊使用try……catch進行異常捕獲處理;

(2)配置mock="true",同時mock實現接口,接口名要注意命名規範:接口名+Mock後綴。此時若是調用失敗會調用Mock實現。mock實現須要保證有無參的構造方法。

配置mock="true"的狀況,對於上面的例子即在IUser的同個路徑下,添加類IUserMock,實現以下:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

public class IUserMock implements IUser {

 

    @Override

    public void addUser(User u) {

        throw new RuntimeException("add user fail!");

    }

 

    @Override

    public User getUserById(int id) {

        return null;

    }

 

}

相關文章
相關標籤/搜索