Dubbo 采用 XML 配置方式快速搭建入门示例
Dubbo 是阿里巴巴公司开源的一个高性能优秀的服务框架,现在被 apache 作为顶级项目进行收录。它提供了 RPC 通信与微服务治理两大关键能力。使用 Dubbo 开发的微服务,将具备相互之间的远程发现与通信能力, 同时利用 Dubbo 提供的丰富服务治理能力,可以实现诸如服务发现、负载均衡、流量调度等服务治理诉求。本篇博客主要是介绍通过 XML 文件配置的方式,将 Dubbo 与 SpringMvc 进行集成并以 Web 的承载方式进行启动,快速搭建 Dubbo 入门示例。在本篇博客的最后会提供源代码的下载。
有关 Dubbo 的详细介绍请查看官网 https://dubbo.apache.org/zh/index.html
一、Zookeeper 注册中心搭建
官方提供了 Dubbo 的架构图,一个简单的 Dubbo 示例最少有 3 部分组成:注册中心、服务提供者,服务消费者。
这里暂不介绍服务监控,官网并未提供一个比较好用的监控工具,下一篇博客会介绍第三方的一个非常好用的 Dubbo 监控工具 DubboAdmin 安装部署。
Dubbo 的工作原理很好理解,服务提供者向注册中心注册接口地址,服务消费者从注册中心获取服务的接口地址,然后去调用服务提供者的接口。当服务提供者的接口地址发生变化时,注册中心会通知服务消费者,服务消费者再重新获取最新的接口地址。绝大部分情况下,Dubbo 的服务提供者和服务消费者,分别部署在不同的机器上,Dubbo 隐藏了底层复杂的 RPC 远程过程调用的细节,服务消费者调用服务提供者的接口,就像是直接调用本地方法一样方便,极大的提高了分布式应用开发的效率。
对于 Dubbo 的注册中心来说,绝大部分情况下使用的是 Zookeeper,它是一款非常优秀的分布式开源协调服务组件。无论是在 linux 还是 windows 下,安装都是非常方便。由于我机器性能有限,不想去搭建 linux 虚拟机了,所以就介绍一下 windows 操作系统下 Zookeeper 的搭建。
首先去官网下载 Zookeeper,下载地址为:https://zookeeper.apache.org/releases.html
其实就是下载一个压缩包,我下载后的稳定版本文件是:apache-zookeeper-3.7.1-bin.tar.gz
然后在自己电脑的硬盘中,解压缩即可完成安装过程。我解压缩到 d 盘下的 develop 目录下,由于个人习惯,不想使用那么长的目录名,所以将文件夹 apache-zookeeper-3.7.1-bin 的名称修改为 zookeeper,并在 zookeeper 目录下创建了一个名称为 zkdata 的文件夹,用来存放 zookeeper 的数据,如下图所示:
然后进入 conf 目录下,复制 zoo_sample.cfg 文件,将复制后的文件名称修改为 zoo.cfg ,因为 Zookeeper 以 zoo.cfg 作为默认的配置文件名称。打开 zoo.cfg 文件,一般情况下只需要注意两个配置项即可,如下所示:
# zookeeper 数据存放的目录,这里需要修改一下
# 我修改为在 zookeeper 下自己创建的 zkdata 文件夹
dataDir=D:/Develop/zookeeper/zkdata
# zookeeper 的客户端连接端口,默认是 2181
# 这里我就不改了,就使用默认的端口
clientPort=2181
修改完 zoo.cfg 的配置之后,进入 bin 目录,对于 windows 操作系统来说,运行 zkServer.cmd 即可启动 Zookeeper。
如果你想将 Zookeeper 安装成 Windows 服务,可以使用 nssm.exe 组件来实现。
nssm.exe 的下载地址为:http://www.nssm.cc/download
当前最新版本是 2.24,下载完成后,解压缩会发现有分为 32 位和 64 位,
我的电脑是 64 位,因此我将 64 位的 nssm.exe 复制到 zookeeper 的 bin 目录下(D:\Develop\zookeeper\bin)。
然后打开控制台,将 nssm.exe 拖动控制台窗口,后面跟上 install 参数,运行命令:
D:\Develop\zookeeper\bin\nssm.exe install
弹出如下窗口,然后录入相关的信息:
Application Path:填写 zkServer.cmd 的绝对路径。
Startup directory:这个是 Zookeeper 的启动目录。
Arguments:启动时指定的参数,这里不需要任何参数。
Service name:服务的名字,这个名字会显示在 Windows 服务中,这里取名为 ZookeeperService。
以上参数填写好后,点击 Install service 即可。安装成功后,到打开 服务 管理器,启动服务即可。
二、Dubbo 公共接口定义
本篇博客的 Demo 仍然采用 Maven 分模块开发管理,分为公共接口模块、Dubbo服务模块、Dubbo客户端模块。
首先需要在公共接口模块定义接口,公共接口模块非常简单,其代码接口如下所示:
在 TestService 接口中定义公共接口,定义了 2 个测试接口,代码如下所示:
package com.jobs.service;
public interface TestService {
String GetMsg(String name);
int GetCal(int a, int b);
}
三、Dubbo 服务端
Dubbo 服务端需要提供接口的具体实现,并且需要将服务接口,注册到 Zookeeper 中。另外为了能够让 Dubbo 服务启动后持续监听,因此这里将 Dubbo 服务端宿主到 Web 中,跟 SpringMvc 进行集成,因此对于 Dubbo 服务端来说,需要导入如下 jar 包:
<dependencies>
<!--导入本项目的公共接口模块-->
<dependency>
<groupId>com.jobs</groupId>
<artifactId>dubbo_interface</artifactId>
</dependency>
<!--导入 SpringMvc 和 servlet api 的 jar 包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<!--导入日志 jar 包,方便在运行过程中,从控制台查看信息-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<!--导入 dubbo 的 jar 包-->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<!--导入 zookeeper 客户端连接的 jar 包,
让本模块能够连接 Zookeeper 服务-->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
</dependency>
</dependencies>
对于本博客 Demo 的 Dubbo 的客户端来说,也需要导入以上 jar 包。
这里导入的 jar 包,没有添加 jar 包版本信息,具体的版本信息在父工程 DubboDemo 的 pom 文件中定义。
对于 Dubbo 服务端来说,其代码接口如下图所示:
在本 Demo 中,对于 Dubbo 服务端和客户端,都采用 xml 配置方式启动 SpringMvc 网站。
TestServiceImpl 是公共接口 TestService 的具体实现,代码如下所示:
package com.jobs.service.impl;
import com.jobs.service.TestService;
import org.apache.dubbo.config.annotation.Service;
//需要注意:这里的 @Service 注解是 Dubbo 提供的
//不要使用 Spring 提供的 @Service 注解
@Service
public class TestServiceImpl implements TestService {
@Override
public String GetMsg(String name) {
return "Hello " + name;
}
@Override
public int GetCal(int a, int b) {
return a + b;
}
}
对于 Dubbo 服务端来说,只需要集成 Spring 即可,因此在 resources 中添加 SpringConfig.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:application name="dubbo-service"/>
<!--配置注册中心的地址-->
<dubbo:registry address="zookeeper://localhost:2181"/>
<!--配置 dubbo 包扫描-->
<dubbo:annotation package="com.jobs.service.impl" />
<!--配置所使用的协议-->
<dubbo:protocol name="dubbo" port="20880"/>
<!--元数据配置,方便在 DubboAdmin 界面中看到服务中的方法 -->
<dubbo:metadata-report address="zookeeper://localhost:2181" />
</beans>
在 WEB-INF 下的 web.xml 中集成 Spring 配置文件,web.xm 内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- spring 启动配置-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:SpringConfig.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
四、Dubbo 客户端
Dubbo 客户端需要连接 Zookeeper 注册中心,获取接口地址,并调用 Dubbo 服务端提供的接口,获取接口返回结果。另外为了方便测试,本博客的 Demo 将 Dubbo 客户端与 SpringMvc 集成,并提供 restful 风格的 Get 接口,方便通过浏览器地址栏输入 url 进行测试。对于 Dubbo 客户端来说,其与服务端导入的 jar 包基本一致,这里就不列出来了。本博客 Demo 中 Dubbo 客户端的代码接口如下所示:
TestController 提供了 2 个测试接口,分别用于测试 Dubbo 服务的 2 个接口,代码如下:
package com.jobs.controller;
import com.jobs.service.TestService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@RestController
@RequestMapping("/test")
public class TestController {
//这里生成远程接口代理,从而可以调用远程服务接口
@Reference
private TestService testService;
@RequestMapping("/getmsg")
public String GetMsg(String name) {
String result = testService.GetMsg(name);
return result;
}
//采用 restful 风格,把传递的参数写在路径上
@GetMapping("/getcal/{num1}/{num2}")
public int GetCal(@PathVariable("num1") int a, @PathVariable("num2") int b) {
int result = testService.GetCal(a, b);
return result;
}
}
需要注意的是,对于 TestService 的注入,不再使用 @Autowared 注解,而是使用 @Reference 注解。
对于 Dubbo 客户端来说,需要与 SpringMvc 集成,因此在 resources 中添加 SpringMvcConfig.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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<mvc:annotation-driven/>
<context:component-scan base-package="com.jobs.controller"/>
<!--配置项目的名称,名称必须唯一-->
<dubbo:application name="dubbo-client">
<dubbo:parameter key="qos.port" value="22223"/>
</dubbo:application>
<!--配置注册中心的地址-->
<dubbo:registry address="zookeeper://localhost:2181"/>
<!--配置dubbo包扫描-->
<dubbo:annotation package="com.jobs.controller"/>
</beans>
这里需要注意的是:由于我在同一台机器上,同时部署了 Dubbo 服务端和客户端,因此会造成 qos 端口冲突,qos 默认端口是 22222,已经被 Dubbo 服务端占用,因此对于 Dubbo 客户端来说,需要将 qos 端口修改一下。qos 是服务质量,保障 Dubbo 服务通信的质量效果。
在 WEB-INF 下的 web.xml 中集成 SpringMvc 配置文件,web.xm 内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--统一请求的编码为 utf-8-->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Springmvc 启动配置-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:SpringMvcConfig.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
最后采用 Tomcat9 分别加载 Dubbo 服务端和客户端,先启动服务端,再启动客户端,然后访问客户端的 web 接口进行测试即可。
到此为止,有关使用 Dubbo 的快速搭建,已经介绍完毕,本博客的 Demo 代码经过详细测试无误,请先编译打包安装后,使用 tomcat 9 进行加载服务端和客户端进行测试。最后列出父工程所导入的 jar 包以及版本:
<properties>
<spring.version>5.3.18</spring.version>
<dubbo.version>2.7.4.1</dubbo.version>
<zookeeper.version>4.0.0</zookeeper.version>
<slf4j.version>1.7.21</slf4j.version>
</properties>
<dependencyManagement>
<dependencies>
<!--导入本项目的公共接口模块-->
<dependency>
<groupId>com.jobs</groupId>
<artifactId>dubbo_interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--导入 Spring 和 SpringMvc 的 jar 包
导入 jackson 相关的 jar 包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.1</version>
</dependency>
<!--servlet 相关 jar 包-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<!--dubbo 相关 jar 包-->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
</dependency>
<!--连接 zookeeper 相关的 jar 包-->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>${zookeeper.version}</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>${zookeeper.version}</version>
</dependency>
<!--日志相关 jar 包-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
本博客 Demo 的下载地址为:https://files.cnblogs.com/files/blogs/699532/DubboDemo.zip