dubbo實戰之二:與SpringBoot集成
- 2021 年 3 月 5 日
- 筆記
歡迎訪問我的GitHub
//github.com/zq2599/blog_demos
內容:所有原創文章分類匯總及配套源碼,涉及Java、Docker、Kubernetes、DevOPS等;
歡迎訪問我的GitHub
這裡分類和匯總了欣宸的全部原創(含配套源碼)://github.com/zq2599/blog_demos
《dubbo實戰》系列導航
本篇概覽
- 本文是《dubbo實戰》系列的第二篇,一起來實戰SpringBoot(2.3.3.RELEASE版本)與dubbo的集成,這也是分散式服務的常用技術組合,本文由以下內容組成:
- 創建子工程springbootmulticastprovider,對外提供服務;
- 創建子工程springbootmulticastconsumer,啟動後提供一個web介面,咱們調用這個web介面時,springbootmulticastconsumer會遠程調用springbootmulticastprovider提供的服務,如下圖:
- 本篇的實戰暫不使用註冊中心,而是服務提供方啟動時廣播自己的地址,再由消費方啟動時訂閱,並隨時遠程調用,調用邏輯如下圖所示:
源碼下載
- 如果您不想編碼,可以在GitHub下載所有源碼,地址和鏈接資訊如下表所示:
名稱 | 鏈接 | 備註 |
---|---|---|
項目主頁 | //github.com/zq2599/blog_demos | 該項目在GitHub上的主頁 |
git倉庫地址(https) | //github.com/zq2599/blog_demos.git | 該項目源碼的倉庫地址,https協議 |
git倉庫地址(ssh) | [email protected]:zq2599/blog_demos.git | 該項目源碼的倉庫地址,ssh協議 |
- 這個git項目中有多個文件夾,本章的應用在dubbopractice文件夾下,如下圖紅框所示:
3. dubbopractice是父子結構的工程,本篇的程式碼在springbootmulticastprovider和springbootmulticastconsumer這兩個子工程中,如下圖:
編碼(服務提供方)
- 先創建提供服務的工程springbootmulticastprovider,一共要創建4個文件,創建順序和功能如下表:
創建順序 | 文件名 | 作用 |
---|---|---|
1 | pom.xml | 工程的pom文件 |
2 | src/main/resources/application.yml | 配置文件 |
3 | DemoServiceImpl.java | 提供具體的服務 |
4 | SpringBootMulticastProviderApplication.java | 啟動類 |
- 完整的文件位置如下圖:
- 接下來逐個創建上述內容;
- 創建名為springbootmulticastprovider的子工程,pom.xml內容如下,要重點關注的是新增依賴dubbo-spring-boot-starter,這就是dubbo在SpringBoot環境的starter依賴:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="//maven.apache.org/POM/4.0.0"
xmlns:xsi="//www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="//maven.apache.org/POM/4.0.0 //maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>dubbopractice</artifactId>
<groupId>com.bolingcavalry</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.bolingcavalry</groupId>
<artifactId>springbootmulticastprovider</artifactId>
<version>1.0-SNAPSHOT</version>
<name>springbootmulticastprovider</name>
<description>Demo project for dubbo service provider from Spring Boot, multicast mode</description>
<!--不用spring-boot-starter-parent作為parent時的配置-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${springboot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<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>
<dependency>
<groupId>com.bolingcavalry</groupId>
<artifactId>practiceinterface</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${springboot.version}</version>
</plugin>
</plugins>
</build>
</project>
- 配置文件application.yml,要注意的是registry.address的配置是廣播模式:
dubbo:
application:
#application-name 本模組名字
name: springboot-multicast-provider
id: springboot-multicast-provider
registry:
address: multicast://224.5.6.7:1234
id: registry
protocol:
name: dubbo
port: 20880
- 編寫服務實現類DemoServiceImpl.java,注意@Service註解將當前類的實例作為遠程服務對外暴露:
package com.bolingcavalry.springbootmulticastprovider;
import com.bolingcavalry.dubbopractice.service.DemoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.rpc.RpcContext;
@Slf4j
@Service
public class DemoServiceImpl implements DemoService {
@Override
public String sayHello(String name) {
log.info("I'm springboot-multicast-provider, Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "I'm springboot-multicast-provider, Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress();
}
}
- 編寫SpringBoot啟動類SpringBootMulticastProviderApplication.java,注意要添加@EnableDubbo註解:
package com.bolingcavalry.springbootmulticastprovider;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableDubbo
public class SpringBootMulticastProviderApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootMulticastProviderApplication.class, args);
}
}
- 至此服務提供方編碼完成,直接在IDEA上運行SpringBootMulticastProviderApplication類即可啟動服務,啟動成功後的日誌輸出如下圖:
編碼(服務消費方)
- 現在網路上已經有了服務,咱們再來編寫服用消費方的程式碼,一共要創建6個文件,創建順序和功能如下表:
創建順序 | 文件名 | 作用 |
---|---|---|
1 | pom.xml | 工程的pom文件 |
2 | src/main/resources/application.yml | 配置文件 |
3 | RemoteInvokeServiceImpl.java | service層,在這裡遠程調用服務提供方的服務 |
4 | DemoController.java | web介面類,對外提供web服務 |
5 | SwaggerConfig.java | swagger配置類,便於通過頁面測試介面 |
6 | SpringBootMulticastConsumerApplication.java | 啟動類 |
- 完整的文件位置如下圖:
- 接下來逐個創建上述文件;
- 創建名為springbootmulticastconsumer的子工程,pom.xml內容如下,同樣需要依賴dubbo-spring-boot-starter:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="//maven.apache.org/POM/4.0.0"
xmlns:xsi="//www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="//maven.apache.org/POM/4.0.0 //maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>dubbopractice</artifactId>
<groupId>com.bolingcavalry</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.bolingcavalry</groupId>
<artifactId>springbootmulticastconsumer</artifactId>
<version>1.0-SNAPSHOT</version>
<name>springbootmulticastconsumer</name>
<description>Demo project for dubbo service consumer from Spring Boot, multicast mode</description>
<!--不用spring-boot-starter-parent作為parent時的配置-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${springboot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<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>
<!-- swagger依賴 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
</dependency>
<!-- swagger-ui -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
</dependency>
<dependency>
<groupId>com.bolingcavalry</groupId>
<artifactId>practiceinterface</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${springboot.version}</version>
</plugin>
</plugins>
</build>
</project>
- 編寫配置文件application.yml,注意dubbo.registry.address的值,除了是廣播模式,還要添加unicast=false,這樣才能保證多個消費者進程都能收到廣播:
dubbo:
application:
name: springboot-multicast-consumer
id: springboot-multicast-consumer
qosEnable: false
registry:
address: multicast://224.5.6.7:1234?unicast=false
id: registry
protocol:
name: dubbo
port: 20880
server:
port: 8081
- 編寫調用遠程服務的程式碼,如下,可見如果想調用遠程服務,只要對介面做@Reference注釋即可,另外還通過timeout屬性增加了超時配置:
package com.bolingcavalry.springbootmulticastconsumer.service;
import com.bolingcavalry.dubbopractice.service.DemoService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Service;
@Service
public class RemoteInvokeServiceImpl {
@Reference(timeout = 2000)
private DemoService demoService;
public String sayHello(String name) {
return "from dubbo remote (multicast mode) : " + demoService.sayHello(name);
}
}
- 再編寫對外提供web服務的Controller類:
package com.bolingcavalry.springbootmulticastconsumer.controller;
import com.bolingcavalry.springbootmulticastconsumer.service.RemoteInvokeServiceImpl;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/demo")
@Api(tags = {"DemoController"})
public class DemoController {
@Autowired
private RemoteInvokeServiceImpl remoteInvokeService;
@ApiOperation(value = "獲取dubbo service provider的響應", notes="\"獲取dubbo service provider的響應")
@ApiImplicitParam(name = "name", value = "昵稱", paramType = "path", required = true, dataType = "String")
@RequestMapping(value = "/{name}", method = RequestMethod.GET)
public String sayHello(@PathVariable String name){
return remoteInvokeService.sayHello(name);
}
}
- 還要添加swagger配置類:
package com.bolingcavalry.springbootmulticastconsumer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.service.Tag;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.tags(new Tag("DemoController", "演示服務"))
.select()
// 當前包路徑
.apis(RequestHandlerSelectors.basePackage("com.bolingcavalry.springbootmulticastconsumer.controller"))
.paths(PathSelectors.any())
.build();
}
//構建 api文檔的詳細資訊函數,注意這裡的註解引用的是哪個
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
//頁面標題
.title("dubbo遠程調用服務的操作(廣播模式)")
//創建人
.contact(new Contact("程式設計師欣宸", "//github.com/zq2599/blog_demos", "[email protected]"))
//版本號
.version("1.0")
//描述
.description("API 描述")
.build();
}
}
- 最後是啟動類SpringBootMulticastConsumerApplication.java:
package com.bolingcavalry.springbootmulticastconsumer;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableDubbo
public class SpringBootMulticastConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootMulticastConsumerApplication.class, args);
}
}
- 至此,服務消費方編碼完成,直接在IDEA上運行SpringBootMulticastConsumerApplication類即可啟動;
- 通過瀏覽器訪問swagger,地址是://localhost:8081/swagger-ui.html ,如下圖,點擊紅框位置展開介面詳情:
-
如下圖,輸入web介面參數發起請求:
-
下圖紅框中就是響應的數據,內容是springbootmulticastconsumer遠程調用springbootmulticastprovider的服務得到的:
- 至此,dubbo與springboot集成的實戰就完成了,希望能給您提供一些參考,助您快速開發dubbo應用;
你不孤單,欣宸原創一路相伴
歡迎關注公眾號:程式設計師欣宸
微信搜索「程式設計師欣宸」,我是欣宸,期待與您一同暢遊Java世界…
//github.com/zq2599/blog_demos