上一篇我们一起认识了Dubbo与RPC,今天我们就来一起学习如何使用Dubbo,并将Dubbo集成到Spring Boot的项目中。我们来看下今天要使用到的软件及版本:
软件 | 版本 | 说明 |
Java | 11 | |
Spring Boot | 2.7.13 | Spring Boot 3.0版本开始,最低支持到Java 17 |
Dubbo | 3.2.2 | |
3.8.1 | 作为Dubbo的注册中心 |
注册中心的选择没有什么强制要求,我们这里以Zookeeper为例来做示范。
TIps:今天我们只处理Spring Boot,Dubbo与Zookeeper的集成,不会涉及到其他框架的集成。
我们先来部署一个Zookeeper,这里我提供Windows和Linux的部署教程,如果你已经部署成功,可以跳过这部分内容。
首先是下载Zookeeper,这里我们选择Zookeeper-3.8.1版本。
Linux下可以使用wget命令下载:
wget https://archive.apache.org/dist/zookeeper/zookeeper-3.8.1/apache-zookeeper-3.8.1-bin.tar.gz
Tips:注意,这里我们下载的是apache-zookeeper-3.8.1-bin.tar.gz这个文件。
解压Zookeeper:
tar -zxvf apache-zookeeper-3.8.1-bin.tar.gz
Zookeeper的配置文件,配置文件位于../Zookeeper/conf目录下,复制zoo_sample.cfg文件,并命名为zoo.cfg:
cp zoo_sample.cfg zoo.cfg
在Dubbo的学习中,我们使用Zookeeper的默认配置即可,所以此处我们不需要再修改zoo.cfg。
修改profile文件:
vim /etc/profile
将Zookeeper的配置添加到profile文件中:
- export ZOOKEEPER_HOME=/opt/opt/apache-zookeeper-3.8.1-bin
- export PATH=$ZOOKEEPER_HOME/bin:$PATH
- export PATH
刷新profile文件:
source profile
启动Zookeeper:
zkServer.sh start
正常情况下会输出日志:
- ZooKeeper JMX enabled by default
- Using config: /opt/apache-zookeeper-3.8.1-bin/bin/../conf/zoo.cfg
- Starting zookeeper ... STARTED
可以使用命令来查看Zookeeper的状态:
zkServer.sh status
单机状态输出如下日志:
- ZooKeeper JMX enabled by default
- Using config: /opt/apache-zookeeper-3.8.1-bin/bin/../conf/zoo.cfg
- Client port found: 2181. Client address: localhost. Client SSL: false.
- Mode: standalone
到这里我们就在Linux服务器上成功的部署了一个简单可用的单机版Zookeeper了。
参照Linux上部署Zookeeper的步骤来到修改配置文件的部分,Windows上我们要修改dataDir的路径,并新增dataLogDir的路径:
- tickTime=2000
- initLimit=10
- syncLimit=5
- dataDir=D:\Apache\Apache Zookeeper 3.8.1\data
- dataLogDir=D:\Apache\Apache Zookeeper 3.8.1\logs
- clientPort=2181
如果系统中没有配置环境变量JAVA_HOME,我们要修改zkEnv.cmd中的JAVA_HOME配置,该文件位于../Apache Zookeeper/bin目录下:
- @echo off
- REM Licensed to the Apache Software Foundation (ASF) under one or more
- REM contributor license agreements. See the NOTICE file distributed with
- REM this work for additional information regarding copyright ownership.
- REM The ASF licenses this file to You under the Apache License, Version 2.0
- REM (the "License"); you may not use this file except in compliance with
- REM the License. You may obtain a copy of the License at
- REM
- REM http://www.apache.org/licenses/LICENSE-2.0
- REM
- REM Unless required by applicable law or agreed to in writing, software
- REM distributed under the License is distributed on an "AS IS" BASIS,
- REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- REM See the License for the specific language governing permissions and
- REM limitations under the License.
-
- set ZOOCFGDIR=%~dp0%..\conf
- set ZOO_LOG_DIR=%~dp0%..\logs
-
- REM for sanity sake assume Java 1.6
- REM see: http://java.sun.com/javase/6/docs/technotes/tools/windows/java.html
-
- REM add the zoocfg dir to classpath
- set CLASSPATH=%ZOOCFGDIR%
-
- REM make it work in the release
- SET CLASSPATH=%~dp0..\*;%~dp0..\lib\*;%CLASSPATH%
-
- REM make it work for developers
- SET CLASSPATH=%~dp0..\build\classes;%~dp0..\build\lib\*;%CLASSPATH%
-
- set ZOOCFG=%ZOOCFGDIR%\zoo.cfg
-
- @REM setup java environment variables
-
- if not defined JAVA_HOME (
- echo Error: JAVA_HOME is not set.
- goto :eof
- )
-
- set JAVA_HOME=%JAVA_HOME%
-
- if not exist "%JAVA_HOME%"\bin\java.exe (
- echo Error: JAVA_HOME is incorrectly set: %JAVA_HOME%
- echo Expected to find java.exe here: %JAVA_HOME%\bin\java.exe
- goto :eof
- )
-
- REM strip off trailing \ from JAVA_HOME or java does not start
- if "%JAVA_HOME:~-1%" EQU "\" set "JAVA_HOME=%JAVA_HOME:~0,-1%"
-
- set JAVA="%JAVA_HOME%"\bin\java
我们将第41行的set JAVA_HOME=%JAVA_HOME%
提前到第36行前,在在判断环境变量中是否存在JAVA_HOME前进行设置,并使用完整的路径,如:set JAVA_HOME=D:\Java\jdk11.0.18
。
上述内容修改完成后直接双击执行zkServer.cmd就可以启动Zookeeper了。注意,Windows下启动可能出现各种各样的错误,最常见的如启动闪退,这时可以在PowerShell中启动zkServer.cmd,来查看日志解决问题:
- cd D:
- PS D:\> cd '.\Apache\Apache Zookeeper 3.8.1\bin\'
- PS D:\Apache\Apache Zookeeper 3.8.1\bin> .\zkServer.cmd
好了,到这里你应该已经完成了Zookeeper的部署工作了,接下来我们在Spring Boot应用中集成Dubbo。
首先我们准备两个工程,DubboProviderXML和DubboConsumerXML,模仿服务提供方和服务使用方,创建工程的部分我们就直接跳过了,相信这一步大家都没问题。
另外Dubbo官方提供了Dubbo Initializer项目脚手架,方便大家快速构建Dubbo项目:
使用方式类似于Spring Initializr:
Tips:
在DubboProviderXML项目下创建了两个子工程:
此时工程结构如下:
现在修改DubboProviderXML工程的POM文件:
- <modelVersion>4.0.0</modelVersion>
- <groupId>com.wyz</groupId>
- <artifactId>DubboProviderXML</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <packaging>pom</packaging>
- <name>DubboProviderXML</name>
- <description>DubboProviderXML</description>
-
- <properties>
- <maven.compiler.source>11</maven.compiler.source>
- <maven.compiler.target>11</maven.compiler.target>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- </properties>
-
- <modules>
- <module>provider-api</module>
- <module>provider-service</module>
- </modules>
通常我会在DubboProviderXML工程中添加所有子项目都会用到的依赖,例如:lombok,commons-lang3等,在此我们忽略这部分内容。
接着处理子工程provider-api中的POM文件:
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>com.wyz</groupId>
- <artifactId>DubboProviderXML</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- </parent>
- <artifactId>provider-api</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <name>provider-api</name>
- <packaging>jar</packaging>
- <description>provider-api</description>
然后在provider-api中声明RPC接口:
- package com.wyz.api;
-
- /**
- * @author wyz
- * @version 1.0
- * @date 2023/6/28
- */
- public interface DubboDemoXMLService {
- String say(String message);
- }
这样provider-api就配置完成了,DubboProviderXML就有了对外提供RPC服务的入口。
Tips:需要将provider-api打包成jar,以便DubboConsumerXML使用。
下面我们配置子工程provider-service的POM文件:
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>com.wyz</groupId>
- <artifactId>DubboProviderXML</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- </parent>
- <artifactId>provider-service</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <name>provider-service</name>
- <description>provider-service</description>
-
- <properties>
- <spring.boot.version>2.7.13</spring.boot.version>
- <dubbo.version>3.2.2</dubbo.version>
- <zookeeper.version>3.8.1</zookeeper.version>
- </properties>
-
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter</artifactId>
- <version>${spring.boot.version}</version>
- </dependency>
-
- <!-- dubbo-spring-boot-starter引入了dubbo -->
- <dependency>
- <groupId>org.apache.dubbo</groupId>
- <artifactId>dubbo-spring-boot-starter</artifactId>
- <version>${dubbo.version}</version>
- </dependency>
-
- <!-- DUbbo与Zookeeper的连接器 -->
- <!-- curator5自身引入了Zookeeper的依赖,因此无需额外引入 -->
- <dependency>
- <groupId>org.apache.dubbo</groupId>
- <artifactId>dubbo-dependencies-zookeeper-curator5</artifactId>
- <version>${dubbo.version}</version>
- <type>pom</type>
- </dependency>
-
- <dependency>
- <groupId>com.wyz</groupId>
- <artifactId>provider-api</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- </dependency>
- </dependencies>
接下来我们在provider-service中实现这个接口:
- package com.wyz.service.impl;
-
- import com.wyz.DubboDemoXMLService;
-
- /**
- * @author wyz
- * @version 1.0
- * @date 2023/7/3
- */
- public class DubboDemoXMLServiceImpl implements DubboDemoXMLService {
-
- @Override
- public String say(String message) {
- return "XML Provider say : " + message;
- }
- }
现在,我们有了接口,也有了接口的实现,只需要配置成Dubbo的服务即可,新增dubbo-provider.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://dubbo.apache.org/schema/dubbo"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://dubbo.apache.org/schema/dubbo
- http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
-
- <!-- Dubbo的基本配置-->
- <dubbo:application name="DubboProviderXML" qos-port="2222"/>
- <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
- <dubbo:protocol name="dubbo"/>
-
- <!-- 配置提供的服务dubboDemoXMLServiceImpl -->
- <bean id="dubboDemoXMLServiceImpl" class="com.wyz.service.impl.DubboDemoXMLServiceImpl"/>
- <dubbo:service interface="com.wyz.api.DubboDemoXMLService" ref="dubboDemoXMLServiceImpl"/>
- </beans>
所有配置完成后,我们导入dubbo-provider.xml文件:
- package com.wyz.service;
-
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.context.annotation.ImportResource;
-
- /**
- * @author wyz
- * @version 1.0
- * @date 2023/7/3
- */
- @SpringBootApplication
- @ImportResource(locations = "classpath:dubbo-provider.xml")
- public class ProviderServiceApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(ProviderServiceApplication.class, args);
- }
- }
到这里我们的DubboProviderXML工程就配置完了,此时工程的结构如下:
我们继续配置服务使用方DubboConsumerXML工程,整体流程和DubboProviderXML的配置基本一致,我们直接快进到consumer-service中的配置部分。
consumer-service的POM文件与DubboProviderXML工程的子工程provider-service完全一致,我们也直接跳过这部分内容。
接下来实现对DubboDemoXMLService#say
的调用:
- package com.wyz.service.impl;
-
- import com.wyz.DubboDemoXMLService;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.boot.CommandLineRunner;
- import org.springframework.stereotype.Component;
-
- /**
- * @author wyz
- * @version 1.0
- * @date 2023/7/3
- */
- @Component
- public class DubboConsumerXMLService implements CommandLineRunner {
-
- @Autowired
- DubboDemoXMLService dubboDemoXMLServiceImpl;
-
- @Override
- public void run(String... args) {
- String message = dubboDemoXMLServiceImpl.say("wyz");
- System.out.println(message);
- }
- }
接着我们新增dubbo-consumer.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://dubbo.apache.org/schema/dubbo"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://dubbo.apache.org/schema/dubbo
- http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
-
- <!-- Dubbo的基本配置-->
- <dubbo:application name="DubboConsumerXML" qos-port="2223"/>
- <dubbo:registry address="zookeeper://106.75.33.232:2181"/>
- <dubbo:protocol name="dubbo"/>
-
- <!-- 配置需要调用的服务 -->
- <dubbo:reference id="DubboDemoXMLService" interface="com.wyz.api.DubboDemoXMLService"/>
- </beans>
同样的,我们导入dubbo-consumer.xml文件:
- package com.wyz.service;
-
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.context.annotation.ImportResource;
-
- /**
- * @author wyz
- * @version 1.0
- * @date 2023/7/3
- */
- @SpringBootApplication
- @ImportResource(locations = "classpath:dubbo-consumer.xml")
- public class ConsumerServiceApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(ConsumerServiceApplication.class, args);
- }
- }
最后,我们启动程序,控制台应该输出如下日志:
此时DubboConsumerXML的工程结构如下:
除了使用XML外,我们还可以使用注解的方式配置Dubbo(毕竟有很多人不喜欢XML)。同样的我们需要先创建两个工程DubboProviderAnnotation和DubboConsumerAnnotation。
DubboProviderAnnotation工程与DubboProviderXML的配置步骤基本一致,我们快进到接口的实现部分,这次我们需要使用@DubboService
注解声明这是一个Dubbo服务:
- package com.wyz.service.impl;
-
- import com.wyz.api.DubboProviderAnnotationService;
- import org.apache.dubbo.config.annotation.DubboService;
-
- /**
- * @author wyz
- * @version 1.0
- * @date 2023/7/3
- */
- @DubboService
- public class DubboProviderAnnotationServiceImpl implements DubboProviderAnnotationService {
-
- @Override
- public String say(String message) {
- return "DubboProviderAnnotationService say : " + message;
- }
- }
接口有了,实现也有了,我们来配置Dubbo的相关内容,这次我们使用YAML配置:
- dubbo:
- application:
- name: DubboProviderAnnotation
- qos-port: 2222
- protocol:
- name: dubbo
- registry:
- address: zookeeper://${zookeeper.address:127.0.0.1}:2181
接着,我们在启动类上添加@EnableDubbo
注解,开启Dubbo的自动注入:
- package com.wyz.service;
-
- import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
-
- /**
- * @author wyz
- * @version 1.0
- * @date 2023/7/3
- */
- @SpringBootApplication
- @EnableDubbo
- public class ProviderServiceApplication {
- public static void main(String[] args) {
- SpringApplication.run(ProviderServiceApplication.class, args);
- }
- }
此时DubboProviderAnnotation的结构如下:
最后我们就可以正常启动DubboProviderAnnotation项目了。
有了前面的基础,相信你一定可以想到DubboConsumerAnnotation该如何配置,我们先来写调用DubboDemoAnnotationService#say
的调用逻辑,此时通过@DubboReference
注入接口:
- package com.wyz.service.impl;
-
- import com.wyz.api.DubboProviderAnnotationService;
- import org.apache.dubbo.config.annotation.DubboReference;
- import org.springframework.boot.CommandLineRunner;
- import org.springframework.stereotype.Component;
-
- /**
- * @author wyz
- * @version 1.0
- * @date 2023/7/3
- */
- @Component
- public class DubboConsumerAnnotationService implements CommandLineRunner {
-
- @DubboReference
- DubboProviderAnnotationService dubboProviderAnnotationService;
-
- @Override
- public void run(String... args) {
- String message = dubboProviderAnnotationService.say("wyz");
- System.out.println(message);
- }
- }
接着来配置YAML文件:
- dubbo:
- application:
- name: DubboConsumerAnnotation
- qos-port: 2223
- protocol:
- name: dubbo
- registry:
- address: zookeeper://${zookeeper.address:127.0.0.1}:2181
同样的,我们需要在服务使用方添加@EnableDubbo
注解,开启Dubbo的自动注入:
- package com.wyz.service;
-
- import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
-
- /**
- * @author wyz
- * @version 1.0
- * @date 2023/7/3
- */
- @SpringBootApplication
- @EnableDubbo
- public class ConsumerServiceApplication {
- public static void main(String[] args) {
- SpringApplication.run(ConsumerServiceApplication.class, args);
- }
- }
此时DubboConsumerAnnotation的结构如下:
最后我们就可以正常启动DubboConsumerAnnotation项目了。
到这里我们就完成了两种形式在Spring Boot中集成Dubbo 3.X。通常来说我会选择使用XML的形式来配置Dubbo提供的服务,但会选择将Dubbo的基本信息,如:协议类型,注册中心地址等配置到YAML文件中,这是为了统一管理对外提供的服务和使用的服务,可以一目了然的看到项目提供了哪些能力,和依赖了哪些外部接口。
如果本文对你有帮助的话,还请多多点赞支持。如果文章中出现任何错误,还请批评指正。最后欢迎大家关注分享硬核Java技术的金融摸鱼侠王有志,我们下次再见!