使用dubbo時你須要注意的

採用註解方式注入消費者接口實力空指針

註解的方式在如今的項目中因爲他的簡潔性愈來愈被大衆所喜歡,在咱們集成dubbox的時候,發現dubbox支持了註解方式,可是在咱們在用註解式集成的時候,發現消費者的對象在沒有注入進去,一直都是報空指針異常.java

代碼以下:spring

/**
 * <p>
 * bug反饋業務接口
 * </p>
 *
 * @author wangguangdong
 * @version 1.0
 * @Date 2016年10月12日16:18:30
 */@AuthAnnotation@Controllerpublic class BugReportResource {    private static final Logger LOG = Logger.getLogger(BugReportResource.class);    @Reference(version = "1.0.0",interfaceClass = BugReportService.class)
    BugReportService bugReportService;
}

通過博主辛苦的查找緣由,後來終於找到問題所在:
在spirng進行實例掃描的時候根本沒法識別dubbo中的註解@Reference ,同時,在dubbo掃描的時候也沒法識別Spring @Controller ,因此兩個框架的掃描順序要排列好,若是先掃了controller,這時候把控制器都實例化好了,再掃dubbo的服務,就會出現空指針,由於在實例化的時候是沒有對應的消費者的實例的,因此就會形成沒法注入,這也就是爲何在咱們調用消費者服務的時候會形成空指針.數據庫

下面是博主編排成功的代碼.express

    <mvc:annotation-driven />
    
    <!-- 查找xxx路徑下全部@Controller 註釋類,添加與項目相關的controller -->
    
    <dubbo:annotation package="XXX.XXX.XXX.controller" />
    
    <context:component-scan base-package="XXX.XXX.XXX.controller"/>

而後在查閱資料以後,博主又發現了另外一種解決辦法:
在一個spring對象中注入dubbo消費者實例,而後在controller中注入這個服務實例便可,這種方法不受dubbo和spirng掃描順序的影響.其實在項目中咱們可能也會有這樣的設計(有些的架構改進會進行這樣的設計,好比我吧全部的服務細粒度化拆分,並做爲提供者註冊給dubbo的server,而後我在消費者端多架構一個組合服務層(業務編排service層),進行dubbo子服務的組合,再講組合後的服務注入到controller中供業務側使用)apache

    @Component
    public class DubboSupport
    {        @Reference(version = "1.0.0",interfaceClass = BugReportService.class)
         BugReportService bugReportService;     
        public BugReportService getBugReportService(){            return bugReportService;
        }
    }

Dubbo超時和重連

dubbo啓動時默認有重試機制和超時機制,某些業務場景下,若是不注意配置超時和重試,可能會引發一些異常。架構

超時機制的規則是若是在必定的時間內,provider沒有返回,則認爲本次調用失敗mvc

重試機制在出現調用失敗時,會再次調用。若是在配置的調用次數內都失敗,則認爲這次請求異常,拋出異常。(dubbo默認重試2次)框架

若是出現超時,一般是業務處理太慢或者發送io阻塞,可在服務提供方執行:jstack PID > jstack.log 分析線程都卡在哪一個方法調用上,這裏就是慢的緣由。若是這個服務接口不能調優性能,請將timeout設大。ide

超時設置

DUBBO消費端設置超時時間須要根據業務實際狀況來設定,若是設置的時間過短,一些複雜業務須要很長時間完成,致使在設定的超時時間內沒法完成正常的業務處理。這樣消費端達到超時時間,那麼dubbo會進行重試機制,不合理的重試在一些特殊的業務場景下可能會引起不少問題,須要合理設置接口超時時間。性能

好比發送郵件,可能就會發出多份重複郵件,執行註冊請求時,就會插入多條重複的註冊數據。

(1)合理配置超時和重連的思路

  1. 對於核心的服務中心,去除dubbo超時重試機制,並從新評估設置超時時間。

  2. 業務處理代碼必須放在服務端,客戶端只作參數驗證和服務調用,不涉及業務流程處理

(2)Dubbo超時和重連配置示例

    <!-- 服務調用超時設置爲6秒,超時不重試--> 
    <dubbo:service interface="com.provider.service.DemoService" ref="demoService"  retries="0" timeout="5000"/>

(3)Dubbo消費者端統一的超時和重連配置

    <!--統一的消費者配置-->
    <dubbo:consumer timeout="30000" retries="0" version="1.0.0"/>

重連機制

dubbo在調用服務不成功時,默認會重試2次。Dubbo的路由機制,會把超時的請求路由到其餘機器上,而不是本機嘗試,因此 dubbo的重試機器也能必定程度的保證服務的質量。可是若是不合理的配置重試次數,當失敗時會進行重試屢次,這樣在某個時間點出現性能問題,調用方再連續重複調用,系統請求變爲正常值的retries倍,系統壓力會大增,容易引發服務雪崩,須要根據業務狀況規劃好如何進行異常處理,什麼時候進行重試。

在重試發送的時候也可能會出現這樣的問題:    
好比有一個bug反饋,可是由於數據庫io瓶頸,這時候這個服務阻塞了,而後過了一會查看數據庫裏有3條除了id外剩下都同樣的數據(id是在服務提供者裏生成的,這裏只作異常例子舉例).

這就是重試機制下,業務不合理的設計所形成的坑,這時候咱們處理的方式有兩種:

  1. 合理規劃業務(例如id放在服務上游生成,數據庫主鍵惟一的機制)

  2. 吧服務增長冪等性設置(例如接口中增長消息id)

附帶上使用dubbo你所須要的mavne依賴

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>4.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.8.4</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.101tec</groupId>
                    <artifactId>zkclient</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.6</version>
        </dependency>
        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.7</version>
        </dependency>
相關文章
相關標籤/搜索