學(xué)習(xí)筆記-dubbo介紹和使用

  • 內(nèi)容簡(jiǎn)介

    此篇文章是介紹Dubbo以及它的簡(jiǎn)單使用,會(huì)列舉運(yùn)用spring boot + dubbo搭建項(xiàng)目運(yùn)用dubbo的步驟,主要是介紹一下dubbo的作用以及簡(jiǎn)單的配置,若有興趣的朋友可以繼續(xù)關(guān)注后續(xù)的dubbo系列文章,也可以參考官方文檔進(jìn)行學(xué)習(xí).個(gè)人的一點(diǎn)心得和想法,有錯(cuò)誤還請(qǐng)指正。


  • Dubbo介紹

    1.什么是Dubbo

    一個(gè)分布式服務(wù)治理框架


    2.為什么用Dubbo

    • 官方介紹

    當(dāng)垂直應(yīng)用越來越多,應(yīng)用之間交互不可避免,將核心業(yè)務(wù)抽取出來,作為獨(dú)立的服務(wù),逐漸形成穩(wěn)定的服務(wù)中心,使前端應(yīng)用能更快速的響應(yīng)多變的市場(chǎng)需求。 此時(shí),用于提高業(yè)務(wù)復(fù)用及整合的分布式服務(wù)框架(RPC)是關(guān)鍵。

    • 自我心得

    小項(xiàng)目中dubbo作用不明顯,因?yàn)轫?xiàng)目中的Api都是通過直接依賴調(diào)用,當(dāng)項(xiàng)目龐大比并且服務(wù)需要多次重復(fù)性的調(diào)用時(shí),就需要一個(gè)框架來治理,dubbo可以做到的效果就是通多xml文件配置,達(dá)到一次提供,到處調(diào)用的效果,并且和可以對(duì)服務(wù)的提供者和消費(fèi)者進(jìn)行管理;就是將提供服務(wù)的Api打包到服務(wù)器,同時(shí)注冊(cè)到注冊(cè)中心(zookeeper),需要調(diào)用此服務(wù)的只需依賴服務(wù)器上的jar包,配置消費(fèi)者服務(wù)即可調(diào)用Api。


    3.基本概念

    • 節(jié)點(diǎn)角色說明
    dubbo-node
    dubbo-node
     > 
     - provider 服務(wù)的提供方
     - consumer 服用的消費(fèi)方
     - registry 注冊(cè)中心(可以對(duì)提供方和消費(fèi)方統(tǒng)一管理)
     - monitor 統(tǒng)計(jì)中心
     - container 運(yùn)行容器
    
    • 調(diào)用關(guān)系說明:

      • 服務(wù)容器負(fù)責(zé)啟動(dòng),加載,運(yùn)行服務(wù)提供者。
      • 服務(wù)提供者在啟動(dòng)時(shí),向注冊(cè)中心注冊(cè)自己提供的服務(wù)。
      • 服務(wù)消費(fèi)者在啟動(dòng)時(shí),向注冊(cè)中心訂閱自己所需的服務(wù)。
      • 注冊(cè)中心返回服務(wù)提供者地址列表給消費(fèi)者,如果有變更,注冊(cè)中心將基于長(zhǎng)連接推送變更數(shù)據(jù)給消費(fèi)者。
      • 服務(wù)消費(fèi)者,從提供者地址列表中,基于軟負(fù)載均衡算法,選一臺(tái)提供者進(jìn)行調(diào)用,如果調(diào)用失敗,再選另一臺(tái)調(diào)用。
      • 服務(wù)消費(fèi)者和提供者,在內(nèi)存中累計(jì)調(diào)用次數(shù)和調(diào)用時(shí)間,定時(shí)每分鐘發(fā)送一次統(tǒng)計(jì)數(shù)據(jù)到監(jiān)控中心。

  • dubbo-provider搭建(Simple)

    1.準(zhǔn)備工作

    為了更加直觀的體現(xiàn)dubbo的作用,在此我會(huì)搭建一個(gè)簡(jiǎn)單的maven項(xiàng)目,通過項(xiàng)目的搭建流程和dubbo的相關(guān)簡(jiǎn)單配置,介紹dubbo的使用,所以,需要做好以下最基本的準(zhǔn)備工作:

    • JDK(1.8)
    • 開發(fā)工具(IDEA)
    • maven(3.3.9)
    • zookepper(注冊(cè)中心)

    2.項(xiàng)目結(jié)構(gòu)

    為了后續(xù)代碼更好的演示,將兩個(gè)項(xiàng)目建立在一個(gè)工作空間下(IDEA),創(chuàng)建簡(jiǎn)單的接口和實(shí)現(xiàn)類,簡(jiǎn)單的測(cè)試方法,基本結(jié)構(gòu)為:

    dubbo-project
    dubbo-project
    • 接口基本實(shí)現(xiàn)為:
    public interface ISimpleService {
        public String sayHello(String name);
    }
    
    @Service
    public class SimpleServiceImpl implements ISimpleService {
        public String sayHello(String name) {
            return "Hello" + name;
        }
    }
    
    

    3.spring boot配置

    • 配置項(xiàng)目的pom文件,搭建spring boot運(yùn)行環(huán)境,這里給出一個(gè)基本的模板,其中包含mysql的依賴,以及使用基本dubbo的依賴,還有注冊(cè)中心zookeeper的相關(guān)依賴,可以根據(jù)實(shí)際情況修改:
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.2.8.RELEASE</version>
    </parent>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>logback-classic</artifactId>
                    <groupId>ch.qos.logback</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>log4j-over-slf4j</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--dubbo-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.8.4</version>
        </dependency>
        <!--zookeeper 相關(guān)-->
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.8</version>
        </dependency>
        <dependency>
            <groupId>com.github.sgroschupf</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.1</version>
        </dependency>
    </dependencies>
    
    <dependencyManagement>
        <dependencies>
            <dependency>
                <!-- Import dependency management from Spring Boot -->
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>1.2.8.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    
    <repositories>
        <repository>
            <id>public</id>
            <name>nexus-repository</name>
            <url>http://192.168.1.169:8080/nexus/content/groups/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>release</id>
            <name>nexus-repository</name>
            <url>http://192.168.1.169:8080/nexus/content/repositories/releases</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>nexus</id>
            <name>nexus-repository</name>
            <url>http://192.168.1.169:8080/nexus/content/groups/public/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    
    
    • 配置完pom文件后還需要配置application.xml(spring默認(rèn)加載的配置文件,根目錄下即可,也可以自己修改配置文件制定),由于spring boot默認(rèn)會(huì)配置jdbcTemplate,所以需要指定一個(gè)dataSourcec(也可通過配置修改,不多說):
    # 制定spring boot運(yùn)行的端口
    server.port=8899
    
    #db properties 需要指定一個(gè)datasource
    spring.datasource.url=xxx
    spring.datasource.username=xxx
    spring.datasource.password=xxx
    spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    
    

    4.dubbo配置

    • 隨后配置simple-dubbo-provider.xml,此處我們做最簡(jiǎn)單的配置:
    <?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:context="http://www.springframework.org/schema/context"
           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">
    
        <!--提供的服務(wù)名稱 自己指定即可 代表你提供的這個(gè)服務(wù)-->
        <dubbo:application name="simpleprovider"></dubbo:application>
        <!--注冊(cè)中心 本地啟動(dòng)zookeeper后默認(rèn)的ip+port-->
        <dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry>
        <!--協(xié)議 port自己指定-->
        <dubbo:protocol name="dubbo" port="8899"></dubbo:protocol>
        <!--提供的接口服務(wù)-->
        <dubbo:service ref="simpleServiceImpl" interface="cn.littledragon.dubbo.service.ISimpleService"></dubbo:service>
    
    

    5.運(yùn)行函數(shù)

    • 最后可以配置日志文件進(jìn)行,進(jìn)行日志記錄,隨后編寫main函數(shù)運(yùn)行項(xiàng)目,運(yùn)用spring boot中寫好的main方法,加以修改:
    @SpringBootApplication
    @ComponentScan("cn.littledragon")
    // @MapperScan(basePackages = "com.tdh.swaptrailer.comm.dal.mapper")
    @ImportResource("simple-dubbo-spring.xml")
    public class Application {
    
       public static final String CONTAINER_KEY = "dubbo.container";
    
       public static final String SHUTDOWN_HOOK_KEY = "dubbo.shutdown.hook";
    
       private static final Logger LOGGER = LoggerFactory.getLogger(Application.class);
    
       private static final ExtensionLoader<Container> LOADER = ExtensionLoader.getExtensionLoader(Container.class);
    
       private static volatile boolean running = true;
    
       protected static void keepRunning(String[] args) {
          try {
             if (args == null || args.length == 0) {
                String config = ConfigUtils.getProperty(CONTAINER_KEY, LOADER.getDefaultExtensionName());
                args = Constants.COMMA_SPLIT_PATTERN.split(config);
             }
    
             final List<Container> containers = new ArrayList<Container>();
             for (int i = 0; i < args.length; i++) {
                containers.add(LOADER.getExtension(args[i]));
             }
             LOGGER.info("Use container type(" + Arrays.toString(args) + ") to run dubbo serivce.");
    
             if ("true".equals(System.getProperty(SHUTDOWN_HOOK_KEY))) {
                Runtime.getRuntime().addShutdownHook(new Thread() {
                   public void run() {
                      for (Container container : containers) {
                         try {
                            container.stop();
                            LOGGER.info("Dubbo " + container.getClass().getSimpleName() + " stopped!");
                         } catch (Exception t) {
                            LOGGER.error(t.getMessage(), t);
                         }
                         synchronized (Application.class) {
                            running = false;
                            Application.class.notify();
                         }
                      }
                   }
                });
             }
    
             for (Container container : containers) {
                container.start();
                LOGGER.info("Dubbo " + container.getClass().getSimpleName() + " started!");
             }
             LOGGER.info(new SimpleDateFormat("[yyyy-MM-dd HH:mm:ss]").format(new Date())
                   + " Dubbo service server started!");
          } catch (RuntimeException e) {
             LOGGER.error(e.getMessage(), e);
          }
          synchronized (Application.class) {
             while (running) {
                try {
                   Application.class.wait();
                } catch (Exception e) {
                   LOGGER.error(e.getMessage(), e);
                }
             }
          }
       }
    
       public static void main(String[] args) throws Exception {
          // SpringApplication.run(Application.class, args);
    
          SpringApplication app = new SpringApplication(Application.class);
    
          app.setWebEnvironment(false);
    
          app.run(args);
    
          keepRunning(args);
       }
    }
    
    

  • dubbo-consumer搭建

    • 準(zhǔn)備工作

    在dubbo-provider相同目錄下創(chuàng)建dubbo-consumer項(xiàng)目,二者處于同一目錄下同一等級(jí)


    • spring boot配置

    步驟與dubbo-provider相同,此處多一個(gè)步驟就是需要將別人提供的服務(wù)(也就是需要使用、消費(fèi)的服務(wù))引入進(jìn)來:
    <dependency> <groupId>cn.littledragon</groupId> <artifactId>dubbo.provider</artifactId> <version>1.0-SNAPSHOT</version> </dependency>


    • dubbo配置

    隨后配置simple-dubbo-provider.xml,此處我們做最簡(jiǎn)單的配置:
    <dubbo:application name="simpleprovider"></dubbo:application> <dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry> <dubbo:reference interface="cn.littledragon.dubbo.service.ISimpleService" id="simpleService"/>


    • 運(yùn)行函數(shù)

    Application.java也與dubbo-provider相同即可


    • 測(cè)試函數(shù)

    編寫測(cè)試類,測(cè)試服務(wù)使用情況

       public class ConsumerTest {
    
         public static void main(String[] args){
    
             ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"simple-dubbo-spring.xml"});
    
             context.start();
    
             ISimpleService simpleService = (ISimpleService)context.getBean("simpleService");
    
             System.out.println(simpleService.sayHello(" littledragon ..."));
    
         }}
    

  • 運(yùn)行效果

    • 首先本地運(yùn)行zookepper
    • 運(yùn)行dubbo-provider項(xiàng)目的Application.main(),打印dubbo started即可
    • 運(yùn)行dubbo-consumer項(xiàng)目的Application.main(),打印dubbo started即可
    • 運(yùn)行測(cè)試函數(shù).main(),可以看到輸出結(jié)果:
    hello  littledragon ...
    

  • 結(jié)語

通過這個(gè)例子可以看出,我們?cè)谕ㄟ^提供方提供服務(wù)到注冊(cè)中心,消費(fèi)方通過配置到注冊(cè)中心上取到該服務(wù),再進(jìn)行消費(fèi)(調(diào)用),即可達(dá)到不同項(xiàng)目之間的相互調(diào)用,也驗(yàn)證了分布式管理的意義,此處只是一個(gè)簡(jiǎn)單的小例子,在實(shí)際項(xiàng)目運(yùn)用中,這種模式加上這個(gè)框架的好處會(huì)更加明顯,后續(xù)也會(huì)給出關(guān)于dubbo其他更深入的運(yùn)用。


本文作者: little-dragon
個(gè)人博客: http://littledragon.cn
版權(quán)聲明: 原創(chuàng)文章,有問題請(qǐng)?jiān)u論中留言。非商業(yè)轉(zhuǎn)載請(qǐng)注明作者及出處。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容