前言
當下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 表示自動獲取一個未被占用的端口