Spring-boot:5分鐘整合Dubbo構建分佈式服務

概述:

  Dubbo是Alibaba開源的分佈式服務框架,它最大的特點是按照分層的方式來架構,使用這種方式可以使各個層之間解耦合(或者最大限度地鬆耦合)。從服務模型的角度來看,Dubbo採用的是一種非常簡單的模型,要麼是提供方提供服務,要麼是消費方消費服務,所以基於這一點可以抽象出服務提供方(Provider)和服務消費方(Consumer)兩個角色。

 我們來看一下Dubbo 的RPC 調用流程,這裏主要涉及到4個模塊:

  • Registry:服務註冊,我們一般會採取Zookeeper 作爲我們的註冊中心
  • Provider:服務提供者(生產者),提供具體的服務實現
  • Consumer:消費者,從註冊中心中訂閱服務
  • Monitor:監控中心,RPC調用次數和調用時間監控

      從上圖中我們可以瞭解到整個RPC 服務調用的過程主要爲:

  1. 生產者發佈服務到服務註冊中心中
  2. 消費者在服務註冊中心中訂閱服務
  3. 消費者調用已經註冊的服務

 

一、項目構建

 開發環境主要涉及以下幾個方面:

  • Spring-boot
  • JDK 8
  • Dubbo
  • Zookeeper

 項目構建通過: http://start.spring.io/ 快速構建web 項目,具體操作可以參考《Spring-Boot:6分鐘掌握SpringBoot開發》

 由於Dubbo 中需要使用到服務註冊中心,我們這裏將使用Zookeeper 作爲服務註冊中心,具體安裝配置,可以參考《Zookeeper-5分鐘快速掌握分佈式應用程序協調服》

 在基礎環境確定好了之後,我們項目的目錄結構如下:

上圖所示,我們項目主要分爲了兩個模塊,一部分是生產者:spring-boot-dubbo ,一部分是:spring-boot-consumer。

    整個項目的結構非常簡單,這很符合Spring-Boot 的特性,簡單便捷,下面我們開始一步步的剖析整個項目的結構

二、Productor

 2.1、Pom.xml

   項目依賴這一塊主要使用到了基本的Spring-Boot-Web 依賴,然後我們需要額外引入Dubbo 與Zookeeper的依賴(詳細依賴可參考源碼,博文底部會有項目Github 地址):

<dependency>
            <groupId>io.dubbo.springboot</groupId>
            <artifactId>spring-boot-starter-dubbo</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.6</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>log4j</groupId>
                    <artifactId>log4j</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

 2.2、配置文件

   由於我們底層使用的是Spring-Boot 進行開發,那麼我們就應該善於利用Spring-Boot 給我們帶來的優勢,因此我們可以直接在Application.properties 文件中配置Dubbo 服務:

## Dubbo 服務提供者配置
spring.dubbo.application.name=provider    --服務名稱
spring.dubbo.registry.address=zookeeper://127.0.0.1:2181   -- 註冊中心地址
spring.dubbo.protocol.name=dubbo     -- dubbo 協議
spring.dubbo.protocol.port=20880
spring.dubbo.scan=com.jaycekon.dubbo.service     --聲明需要暴露的服務接口

如果不採用Spring-Boot 進行自動配置,大家可以參考一下的配置xml 配置:

<?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="provider"  />
    <!-- 註冊中心服務地址 -->
    <dubbo:registry  protocol="zookeeper" address="127.0.0.1"  check="false" />
    <!-- 用dubbo協議-->
    <dubbo:protocol name="dubbo" port="-1" dispather="all" check="false" />
    <dubbo:provider timeout="10000"  threads="10" threadpool="fixed"   loadbalance="roundrobin"/>
    <!-- 聲明需要暴露的服務接口 -->
    <dubbo:service interface="com.jaycekon.dubbo.service" ref="userService"/> </beans>

2.3、服務提供

  在服務提供主要包括兩部分,一個是暴露服務,一個是服務實現

  暴露服務:即我們平常開發中所使用的的接口,這裏我們創建一個 UserService 的接口,主要包括一個保存用戶的方法。

import com.jaycekon.dubbo.domain.User;

/**
 * Created by Jaycekon on 2017/9/19.
 */
public interface UserService {

    User saveUser(User user);
}

服務實現:服務實現,與我們平常的服務一樣,對接口進行實現,比較特別的是,我們這裏需要使用到Dubbo 的 @Service 註解

import com.alibaba.dubbo.config.annotation.Service;
import com.jaycekon.dubbo.domain.User;
import com.jaycekon.dubbo.service.UserService;

/**
 * Created by Jaycekon on 2017/9/19.
 */
@Service
public class UserServiceImpl implements UserService {

    @Override
    public User saveUser(User user) {
        user.setId(1);
        System.out.println(user.toString());
        return user;
    }
}

2.4、總體結構

  Dubbo 的服務提供端,已經總體開發完成,非常簡單,總體的目錄結構如下:

三、Consumer

3.1、pom.xml

  消費者的相關依賴,與生產者的依賴一致。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jaycekon</groupId>
    <artifactId>spring-boot-consumer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>spring-boot-consumer</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- Spring Boot Dubbo 依賴 -->
        <dependency>
            <groupId>io.dubbo.springboot</groupId>
            <artifactId>spring-boot-starter-dubbo</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.6</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>log4j</groupId>
                    <artifactId>log4j</artifactId>
                </exclusion>
            </exclusions>
        </dependency>


        <!-- mvn spring-boot:run 熱部署啓動 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>springloaded</artifactId>
            <version>1.2.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.18</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

3.2、配置文件

  配置文件與生產者稍有區別:

## 避免和 server 工程端口衝突
server.port=8081

## Dubbo 服務消費者配置
spring.dubbo.application.name=consumer
spring.dubbo.registry.address=zookeeper://127.0.0.1:2181
spring.dubbo.scan=com.jaycekon.dubbo.service

基於Xml 的配置:

<?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="provider"  />
    <!-- 註冊中心服務地址 -->
    <dubbo:registry  protocol="zookeeper" address="${dubbo.registry.address}"  check="false" />
    <!-- 用dubbo協議-->
    <dubbo:protocol name="dubbo" port="-1" dispather="all" check="false" />
    <dubbo:provider timeout="10000"  threads="10" threadpool="fixed"   loadbalance="roundrobin"/>
    <!-- 聲明需要暴露的服務接口 -->
    <dubbo:service interface="com.jaycekon.dubbo.service" ref="userService"/>
</beans>

3.3、服務實現

  在這裏,如果我們需要調用註冊服務中的相關服務,則需要實現相關的接口。

import com.jaycekon.dubbo.domain.User;

/**
 * Created by Jaycekon on 2017/9/19.
 */
public interface UserService {
    User saveUser(User user);
}

例如,在這裏我們需要使用到生產者中的 saveUser(User user) 方法,則需要創建一個接口,然後再調用時,使用 @Reference 註解進行引用:

import com.alibaba.dubbo.config.annotation.Reference;
import com.jaycekon.dubbo.domain.City;
import com.jaycekon.dubbo.domain.User;
import org.springframework.stereotype.Component;

/**
 * 城市 Dubbo 服務消費者
 * <p>
 * Created by Jaycekon on 20/09/2017.
 */
@Component
public class CityDubboConsumerService {

    @Reference
    CityDubboService cityDubboService;

    @Reference
    UserService userService;

    public void printCity() {
        String cityName = "廣州";
        City city = cityDubboService.findCityByName(cityName);
        System.out.println(city.toString());
    }


    public User saveUser() {
        User user = new User();
        user.setUsername("jaycekon")
                .setPassword("jaycekong824");
        return userService.saveUser(user);
    }
}

3.4、服務調用

  最後,我們需要實現一個RESTful 接口,提供給用戶調用:

import com.jaycekon.dubbo.service.CityDubboConsumerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Created by Jaycekon on 2017/9/19.
 */
@RestController
public class UserController {

    @Autowired
    private CityDubboConsumerService service;


    @RequestMapping("/save")
    public Object saveUser() {

        return service.saveUser();
    }
}

3.5、目錄結構

四、總結

  本篇博客主要是博主在學習Spring-boot 的時候,總結下來的。在經過一些列的對比後,感覺Dubbo 與Spring-Cloud 還是有點差距的,不管是從服務提供,還是社區活躍來說,Spring-Cloud 還是會強一點。但是由於公司內部使用的是Dubbo,因此還是需要學習一下,後續的話,會對Spring-Cloud 進行學習以及分項。

  本文中出現的代碼,大家可以到我的 GitHub 多啦A夢 的傳送門-https://github.com/jaycekon/SpringBoot

       希望大家不要吝嗇自己的Star 和 Fork ,謝謝。

原博文地址:

https://www.cnblogs.com/jaycekon/p/SpringBootDubbo.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章