SpringCloud+Dubbo+Nacos整合實現RPC調用


Dubbo很多人都不陌生,這畢竟是一款從2012年就開始開源的Java RPC框架,中間由於各種各樣的原因停止更新4年半的時間,中間只發過一個小版本修了一個小bug,甚至大家都以為這個項目已經死掉了,竟然又在2017年9月份恢復了更新。
網絡上很多人都拿Dubbo和Spring Cloud做對比,可能在大家的心目中,這兩個框架是可以畫上等號的吧。后來在網絡上有一個非常流行的表格,比較詳細的對比了 Spring Cloud 和 Dubbo,表格如下:
  Dubbo SpringCloud
服務注冊中心 Zookeeper Spring Cloud Netfix Eureka
服務調用方式 RPC REST API
服務監控 Dubbo-monitor Spring Boot Admin
熔斷器 不完善 Spring Cloud Netflix Hystrix
服務網關 Spring Cloud Netflix Zuul
分布式配置 Spring Cloud Config
服務跟蹤 Spring Cloud Sleuth
數據流 Spring Cloud Stream
批量任務 Spring Cloud Task
信息總線 Spring Cloud Bus
以上列舉了一些核心部件,當然這里需要申明一點,Dubbo對於上表中總結為“無”的組件不代表不能實現,而只是Dubbo框架自身不提供,需要另外整合以實現對應的功能,這樣看起來確實Dubbo更像是Spring Cloud的一個子集。
Dubbo在國內擁有着巨大的用戶群,大家希望在使用Dubbo的同時享受Spring Cloud的生態,出現各種各樣的整合方案,但是因為服務中心的不同,各種整合方案並不是那么自然,直到Spring Cloud Alibaba這個項目出現,由官方提供了Nacos服務注冊中心后,才將這個問題完美的解決。並且提供了Dubbo和Spring Cloud整合的方案,命名為:Dubbo Spring Cloud。
 
Dubbo Spring Cloud概述
Dubbo Spring Cloud構建在原生的Spring Cloud之上,其服務治理方面的能力可認為是Spring Cloud Plus,不僅完全覆蓋Spring Cloud 原生特性,而且提供更為穩定和成熟的實現,特性比對如下表所示:
功能組件 Spring Cloud Dubbo Spring Cloud
分布式配置(Distributed configuration) Git、Zookeeper、Consul、JDBC Spring Cloud 分布式配置 + Dubbo 配置中心
服務注冊與發現(Service registration and discovery) Eureka、Zookeeper、Consul Spring Cloud 原生注冊中心 + Dubbo 原生注冊中心
負載均衡(Load balancing) Ribbon(隨機、輪詢等算法) Dubbo 內建實現(隨機、輪詢等算法 + 權重等特性)
服務熔斷(Circuit Breakers) Spring Cloud Hystrix Spring Cloud Hystrix + Alibaba Sentinel 等
服務調用(Service-to-service calls) Open Feign、RestTemplate Spring Cloud 服務調用 + Dubbo @Reference
鏈路跟蹤(Tracing) Spring Cloud Sleuth + Zipkin Zipkin、opentracing 等
以上對比表格摘自Dubbo Spring Cloud官方文檔。
而且Dubbo Spring Cloud基於Dubbo Spring Boot 2.7.1 和 Spring Cloud 2.x開發,無論開發人員是Dubbo用戶還是Spring Cloud用戶, 都能輕松地駕馭,並以接近“零”成本的代價使應用向上遷移。Dubbo Spring Cloud致力於簡化雲原生開發成本,以達成提高研發效能以及提升應用性能等目的。
 
Dubbo Spring Cloud 主要特性
(1)面向接口代理的高性能RPC調用:提供高性能的基於代理的遠程調用能力,服務以接口為粒度,屏蔽了遠程調用底層細節。
(2)智能負載均衡:內置多種負載均衡策略,智能感知下游節點健康狀況,顯著減少調用延遲,提高系統吞吐量。
(3)服務自動注冊與發現:支持多種注冊中心服務,服務實例上下線實時感知。
(4)高度可擴展能力:遵循微內核+插件的設計原則,所有核心能力如Protocol、Transport、Serialization被設計為擴展點,平等對待內置實現和第三方實現。
(5)運行期流量調度:內置條件、腳本等路由策略,通過配置不同的路由規則,輕松實現灰度發布,同機房優先等功能。
(6)可視化的服務治理與運維:提供豐富服務治理、運維工具:隨時查詢服務元數據、服務健康狀態及調用統計,實時下發路由策略、調整配置參數。
 
Spring Cloud為什么需要RPC?
在Spring Cloud構建的微服務系統中,大多數的開發者使用都是官方提供的Feign組件來進行內部服務通信,這種聲明式的HTTP客戶端使用起來非常的簡潔、方便、優雅,但是有一點,在使用Feign消費服務的時候,相比較Dubbo這種RPC框架而言,性能堪憂。
雖說在微服務架構中,會將按照業務划分的微服務獨立部署,並且運行在各自的進程中。微服務之間的通信更加傾向於使用HTTP這種簡單的通信機制,大多數情況都會使用REST API。這種通信方式非常的簡潔高效,並且和開發平台、語言無關,但是通常情況下,HTTP並不會開啟KeepAlive功能,即當前連接為短連接,短連接的缺點是每次請求都需要建立TCP連接,這使得其效率變的相當低下。
對外部提供REST API服務是一件非常好的事情,但是如果內部調用也是使用HTTP調用方式,就會顯得顯得性能低下,Spring Cloud默認使用的Feign組件進行內部服務調用就是使用的HTTP協議進行調用。這時,我們如果內部服務使用RPC調用,對外使用REST API,將會是一個非常不錯的選擇。恰巧,Dubbo Spring Cloud給了我們這種選擇的實現方式。
 
SpringCloud+Nacos+Dubbo整合實戰
下面將會以一個簡單的入門案例,介紹一下在使用Nacos作為服務中心,使用Dubbo來實現服務提供方和服務消費方的案例。
(1)服務端接口契約定義
創建普通Maven項目dubbo-sample-api,定義服務端與消費端的接口契約。該項目僅是用於定義Dubbo服務端與消費端的接口契約。這里創建僅為更好的代碼重用以及接口、模型規格控制管理。然后打包成jar包,安裝到私有倉庫,供客戶端與Dubbo服務端接口實現的項目來依賴使用。

pom.xml不用引用任何包。

定義服務端接口類IHelloService:
package com.zxy.dubbo_sample_api;
 
public interface IHelloService {
    String sayHello(String name);
}

然后執行mvn install,將dubbo-sample-api添加到本地倉庫,供其他項目依賴。

(2)服務端服務實現
創建一個SpringBoot項目dubbo-sample-provider。該項目實現上面定義好的接口,並該項目作為服務注冊到服務注冊中心,這里采用nacos,也可以采用ZooKeeper,而且dubbo還可以支持多注冊中心。
工程依賴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.zxy</groupId>
    <artifactId>dubbo-sample-provider</artifactId>
    <version>1.0</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.7.RELEASE</version>
        <relativePath/>
    </parent>
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR10</spring-cloud.version>
        <spring-cloud-alibaba.version>2.2.5.RELEASE</spring-cloud-alibaba.version>
    </properties>
    <dependencyManagement>
        <dependencies>
            <!-- spring-cloud -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- spring-cloud-alibaba -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
 
    <dependencies>
        <!-- spring boot -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 熱部署 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- Nacos Discovery -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- Dubbo -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-dubbo</artifactId>
        </dependency>
        <!-- 健康監控,必須包含spring-boot-starter-actuator包,不然啟動會報錯 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- 需要實現的服務接口包 -->
        <dependency>
            <groupId>com.zxy</groupId>
            <artifactId>dubbo-sample-api</artifactId>
            <version>1.0</version>
        </dependency>
    </dependencies>
</project>

注意:必須包含spring-boot-starter-actuator包,不然啟動會報錯。pom中引入定義服務契約接口的API模塊的包。

實現Dubbo接口IHelloService,新建HelloServiceImpl類,代碼如下:
package com.zxy.dubbo_sample_provider.service;
import com.zxy.dubbo_sample_api.IHelloService;
import org.apache.dubbo.config.annotation.DubboService;
 
@DubboService
public class HelloServiceImpl implements IHelloService {
    public String sayHello(String name){
        return "Hello World:"+ name;
    }
}

注意:這里的@DubboService注解是Dubbo的org.apache.dubbo.config.annotation.DubboService,千萬不要引用錯誤。@DubboService注解僅聲明該Java服務(本地)實現為Dubbo服務。舊版本的dubbo使用該包下的@Service直接,后來為了防止與spring混淆改為了@DubboService。

配置文件application.properties,將Java服務(本地)配置為Dubbo服務(遠程)如下:
#Spring應用名稱,用於SpringCloud服務注冊和發現。該值在Dubbo Spring Cloud加持下被視作dubbo.application.name,因此,無需再顯示地配置dubbo.application.name。
spring.application.name=dubbo-sample-provider
server.port=3001
 
#Dubbo服務實現類的掃描基准包路徑
dubbo.scan.base-packages=com.zxy.dubbo_sample_provider.service
#Dubbo服務暴露的協議配置,其中子屬性name為協議名稱,port為協議端口(-1 表示自增端口,從 20880 開始)
#因為項目中存在多個服務提供端比如商品服務、會員服務等,這里為了方便設置為了-1
dubbo.protocol.name=dubbo
dubbo.protocol.port=-1
#Dubbo服務注冊中心的配置地址,它的值spring-cloud://localhost表示掛載到Spring Cloud注冊中心,不配置的話會提示沒有配置注冊中心的錯誤。
dubbo.registry.address=spring-cloud://localhost
 
#nacos
#spring.cloud.nacos.discovery定義Nacos服務發現與注冊配置,其中子屬性server-addr指定Nacos服務器主機和端口。
spring.cloud.nacos.discovery.server-addr=localhost:8848

注意:在暴露Dubbo服務方面,推薦使用外部化配置的方式,即指定Java服務實現類的掃描基准包。

Dubbo Spring Cloud 繼承了 Dubbo Spring Boot 的外部化配置特性,也可以通過標注@DubboComponentScan來實現基准包掃描。
創建應用主類,即項目入口DubboSampleProviderApplication.java文件。如果使用SpringBoot自動創建項目該文件是自動創建的不用做任何修改。
package com.zxy.dubbo_sample_provider;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
 
@SpringBootApplication
public class DubboSampleProviderApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(DubboSampleProviderApplication.class, args);
    }
 
}

運行dubbo-sample-provider項目,將會在Nacos中注冊服務。(注意:在運行項目前,先安裝並啟動Nacos服務端)

 

 

 

 (3)消費端(客戶端)實現

創建一個SpringBoot項目dubbo-consumer,實現調用以上的服務。
工程依賴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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>com.zxy</groupId>
    <artifactId>dubbo-consumer</artifactId>
    <version>1.0</version>
 
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.7.RELEASE</version>
        <relativePath/>
    </parent>
 
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR10</spring-cloud.version>
        <spring-cloud-alibaba.version>2.2.5.RELEASE</spring-cloud-alibaba.version>
    </properties>
 
    <dependencyManagement>
        <dependencies>
            <!-- spring-cloud -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- spring-cloud-alibaba -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
 
    <dependencies>
        <!-- spring boot -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 熱部署 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- web項目 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- Nacos Discovery -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- Dubbo -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-dubbo</artifactId>
        </dependency>
        <!-- 健康監控,必須包含spring-boot-starter-actuator包,不然啟動會報錯 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
 
        <!-- dubbo服務接口契約包 -->
        <dependency>
            <groupId>com.zxy</groupId>
            <artifactId>dubbo-sample-api</artifactId>
            <version>1.0</version>
        </dependency>
 
    </dependencies>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

注意:pom中一定要引入定義服務契約接口的API模塊的包dubbo-sample-api。

工程配置application.properties:
#服務名稱
spring.application.name=dubbo-consumer
server.port=4001
 
#表示要訂閱服務的服務名,可以配置'*'代表訂閱所有服務(不推薦使用)。若需訂閱多應用,使用","分割。
dubbo.cloud.subscribed-services=dubbo-sample-provider
 
#nacos
spring.cloud.nacos.discovery.server-addr=localhost:8848
#禁止該服務注冊到Nacos服務列表中
spring.cloud.nacos.discovery.register-enabled=false

實現服務調用,新建HelloController.java類:

package com.zxy.dubbo_consumer.control;
 
import com.zxy.dubbo_sample_api.IHelloService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
public class HelloController {
 
    @DubboReference
    private IHelloService helloService;
 
    @GetMapping("/say")
    public String sayHello(){
        return helloService.sayHello("Lily");
    }
}

注意:這里的@DubboReference注解是Dubbo的org.apache.dubbo.config.annotation.DubboReference,千萬不要引用錯誤。

手寫過RPC框架的同學,應該都知道,客戶端通過服務端的接口契約可以調用服務端的接口,其實是采用動態代理的方式,dubbo中默認采用javasist,大家不妨debug一下。@DubboReference作用就是將動態代理注入進來。
創建應用主類,即項目入口DubboConsumerApplication.java文件。如果使用SpringBoot自動創建項目該文件是自動創建的不用做任何修改。
package com.zxy.dubbo_consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DubboConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(DubboConsumerApplication.class, args);
    }
}

(4)測試:

啟動Nacoe、啟動服務提供項目dubbo-sample-provider、服務消費項目dubbo-consumer、確保接口契約項目已經添加到maven本地倉庫中。啟動完成后,我們可以訪問Nacos控制台的服務列表上已經注冊的以上服務。具體參照之前的步驟。
我們打開瀏覽器訪問:http://localhost:4001/say,可以看到頁面正常顯示Hello World:Lily!表示測試成功。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM