SpringBoot+Dubbo+Zookeeper 例項

邊緣技術發表於2021-04-20

前言

    當下Java 生態環境裡面,微服務佔據了非常大的份額,現在大部分新開發的 Java選型的後臺程式都很奇妙的會跟微服務發生一些關係。那目前市面上主流的微服務方向主要有 Spring 家族推出的Spring Boot Cloud 還有阿里巴巴推出的 Dubbo 服務。

    這兩種服務我都大體上的使用過,說一下我的感受。我感覺Spring Boot Cloud 周邊的服務功能框架比較健全,如果希望快速的搭建起一個大型的商業型別的專案可以選擇Spring Boot Cloud,畢竟人家血統純正的 Spring Boot體系,以及最近挺火的 Spring Cloud Alibaba 感覺也挺不錯的。Dubbo 服務這邊大體就是使用 nacos 或者 zookeeper 作為註冊中心來實現微服務,可能周邊的服務框架沒有 Spring BootCloud 那樣健全,但是個人感覺 Dubbo 的服務呼叫會比 feign 和 ribbon 舒服一點。所以我就想粗略的講一下 Dubbo 和 Zookeeper 怎麼使用。

 

    建立服務 

    建立一個 maven 專案,下面三個子專案,分別是 common,provider,consumer。

    curator-recipes 和 curator-client 這兩個服務包是因為當前 dubbo 版本和 zk 版本的相容性問題,後續版本更新後應該就不需要開發人員引入了。

 parent pom.xml:

<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.learn</groupId>
  <artifactId>springboot-dubbo-zookeeper</artifactId>
  <version>1.0.0.LEARN</version>
  <packaging>pom</packaging><name>springboot-dubbo-nacos</name>
  <url>http://maven.apache.org</url><properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties><modules>
    <module>common</module>
    <module>consumer</module>
    <module>provider</module>
  </modules><dependencyManagement>
    <dependencies>
      <!-- common -->
      <dependency>
        <groupId>com.learn</groupId>
        <artifactId>common</artifactId>
        <version>${version}</version>
      </dependency><!-- Spring Boot -->
      <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <version>2.3.5.RELEASE</version>
        <scope>test</scope>
      </dependency>
      <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>2.3.5.RELEASE</version>
      </dependency>
      <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <version>2.3.5.RELEASE</version>
      </dependency><!-- Dubbo + Zookeeper -->
      <!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo-spring-boot-starter -->
      <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo-spring-boot-starter</artifactId>
        <version>2.7.8</version>
      </dependency>
      <!-- https://mvnrepository.com/artifact/org.apache.curator/curator-recipes -->
      <dependency>
        <groupId>org.apache.curator</groupId>
        <artifactId>curator-recipes</artifactId>
        <version>5.1.0</version>
      </dependency>
      <!-- https://mvnrepository.com/artifact/org.apache.curator/curator-client -->
      <dependency>
        <groupId>org.apache.curator</groupId>
        <artifactId>curator-client</artifactId>
        <version>5.1.0</version>
      </dependency>
    </dependencies>
  </dependencyManagement>
</project>

Common 模組

    common 模組用作定義 provider 和 consumer 模組當中公共的類和介面,為了怎麼程式碼的耦合度。如果不使用 common 模組,就必須在 provider 和 consumer 模組當中都定義呼叫介面和實體類。

 common pom.xml:

<?xml version="1.0"?>
<project
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
  xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><modelVersion>4.0.0</modelVersion>
  <artifactId>common</artifactId>
  <name>common</name>
  <url>http://maven.apache.org</url>
  <packaging>jar</packaging><parent>
    <groupId>com.learn</groupId>
    <artifactId>springboot-dubbo-zookeeper</artifactId>
    <version>1.0.0.LEARN</version>
  </parent><properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties><dependencies>
  </dependencies>
</project>

定義服務呼叫介面:

package com.learn.common.handler.service;
​
/**
 * 呼叫介面
 * @author xiaohu
 *
 */
public interface IHelloService {
  
  public String hello();
  
}

provider 模組

    provider 作為服務的提供者,只需要實現 common 中定義的介面就行了,然後就是把服務通過 Dubbo 註冊到 zookeeper 註冊中心。

 provider pom.xml:

<?xml version="1.0"?>
<project
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
  xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><modelVersion>4.0.0</modelVersion>
  <artifactId>provider</artifactId>
  <name>provider</name>
  <url>http://maven.apache.org</url>
  <packaging>jar</packaging><parent>
    <groupId>com.learn</groupId>
    <artifactId>springboot-dubbo-zookeeper</artifactId>
    <version>1.0.0.LEARN</version>
  </parent><properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties><dependencies>
    <!-- common -->
    <dependency>
      <groupId>com.learn</groupId>
      <artifactId>common</artifactId>
    </dependency><!-- Spring Boot -->
    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
    </dependency><!-- Dubbo + Zookeeper-->
    <!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo-spring-boot-starter -->
    <dependency>
      <groupId>org.apache.dubbo</groupId>
      <artifactId>dubbo-spring-boot-starter</artifactId>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.curator/curator-recipes -->
    <dependency>
      <groupId>org.apache.curator</groupId>
      <artifactId>curator-recipes</artifactId>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.curator/curator-client -->
    <dependency>
      <groupId>org.apache.curator</groupId>
      <artifactId>curator-client</artifactId>
    </dependency>
  </dependencies>
</project>

啟動類:

package com.learn.provider;
​
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
​
/**
 * 服務提供者啟動類
 * 
 * @author xiaohu
 *
 */
// 啟用 Dubbo 服務
@EnableDubbo
@SpringBootApplication
public class ProviderApplication {
  public static void main(String[] args) {
    System.out.println("Provider Application Starter ...");
    SpringApplication.run(ProviderApplication.class, args);
    System.out.println("Provider Application Starter Successful!");
  }
}

application.properties:

# 啟動埠
server.port=8000# dubbo + zookeeper
dubbo.application.name=provider
dubbo.registry.address=zookeeper://127.0.0.1:2181
# -1 表示自動獲取一個未被佔用的埠
dubbo.protocol.port=-1
dubbo.protocol.name=dubbo

介面實現:

package com.learn.provider.handler.service;
​
import org.apache.dubbo.config.annotation.DubboService;
​
import com.learn.common.handler.service.IHelloService;
​
/**
 * IHelloService 實現類
 * @author xiaohu
 *
 */
@DubboService
public class HelloService implements IHelloService {
​
  public String hello() {
    // TODO Auto-generated method stub
    return "Hello World!";
  }
  
}

consumer 模組

consumer 作服務的消費者,呼叫服務介面。

consumer pom.xml:

<?xml version="1.0"?>
<project
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
  xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><modelVersion>4.0.0</modelVersion>
  <artifactId>consumer</artifactId>
  <name>consumer</name>
  <url>http://maven.apache.org</url>
  <packaging>jar</packaging><parent>
    <groupId>com.learn</groupId>
    <artifactId>springboot-dubbo-zookeeper</artifactId>
    <version>1.0.0.LEARN</version>
  </parent><properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties><dependencies>
    <!-- common -->
    <dependency>
      <groupId>com.learn</groupId>
      <artifactId>common</artifactId>
    </dependency><!-- Spring Boot -->
    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Dubbo + Zookeeper-->
    <!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo-spring-boot-starter -->
    <dependency>
      <groupId>org.apache.dubbo</groupId>
      <artifactId>dubbo-spring-boot-starter</artifactId>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.curator/curator-recipes -->
    <dependency>
      <groupId>org.apache.curator</groupId>
      <artifactId>curator-recipes</artifactId>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.curator/curator-client -->
    <dependency>
      <groupId>org.apache.curator</groupId>
      <artifactId>curator-client</artifactId>
    </dependency>
  </dependencies>
</project>

啟動類:

package com.learn.consumer;
​
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
​
/**
 * 服務消費者啟動類
 * 
 * @author xiaohu
 *
 */
// 啟用 Dubbo
@EnableDubbo
@SpringBootApplication
public class ConsumerApplication {
  public static void main(String[] args) {
    System.out.println("Consumer Application Starter ...");
    SpringApplication.run(ConsumerApplication.class, args);
    System.out.println("Consumer Application Starter Successful!");
  }
}

application.properties:

# 啟動埠
server.port=8001# dubbo + zookeeper
dubbo.application.name=consumer
dubbo.registry.address=zookeeper://127.0.0.1:2181
# -1 表示隨機一個未被使用埠 dubbo.protocol.port=-1 dubbo.protocol.name=dubbo

服務呼叫:

package com.learn.consumer.endpoint.controller;
​
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
​
import com.learn.common.handler.service.IHelloService;
​
/**
 * 服務呼叫
 * @author xiaohu
 *
 */
@RestController
public class HelloController {
  
  @DubboReference
  private IHelloService helloService;
  
  @RequestMapping(value = "/hello", method = RequestMethod.GET)
  public String hello() {
    return helloService.hello();
  }
  
}

執行測試一下:

先啟動 zookeeper 服務:

再依次啟動 provider 和 consumer 服務:

兩個服務都已經成功的起來了。可以訪問 http://localhost:8001/hello 測試一下。

成功返回了 Hello World!

 

總結

    到此,一個簡單的通過 Dubbo 完成的服務呼叫就寫完了。這裡需要說明,common 模組並不是必須的,只是個人的編碼習慣,為的實體類和介面可以複用而已。如果不喜歡的可以在呼叫和實現模組中定義就行了,但是必須保證介面內容能對上。

    服務啟動順序最好是按照,服務提供者優先啟動,服務消費者後面啟動的原則。

    現在來說 Dubbo 經過了一段時間的斷維之後,又開始維護了。我覺得這個是一件好的事情,給我們提供了更多元化的一個選擇。也希望這篇文章能夠幫助到大家,謝謝。

 

 有興趣的話可以掃碼或搜尋 "邊緣技術" 關注我的微信公眾號,非常感謝大家。

# -1 表示自動獲取一個未被佔用的埠