dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,以及 SOA 服务治理方案。它采用全 Spring 配置方式,透明化接入应用,对应用没有任何API侵入,只需用 Spring 加载 dubbo 的配置即可。如需了解更多相关信息可前往官方文档用户指南部分的介绍。

1. 创建项目

创建一个 maven 多模块项目,结构如下:

1
2
3
4
5
6
7
dubbo-quickstart-sample(父模块)
|
|__ user-module-api(服务接口模块)
|
|__ user-module-provider(服务提供者)
|
|__ user-module-consumer(服务消费者)

1.1 父模块项目

dubbo-quickstart-sample/pom.xml 配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.fanlychie</groupId>
<artifactId>dubbo-quickstart-sample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>dubbo-quickstart-sample</name>
<description>Sample project for Dubbo</description>
<url>http://maven.apache.org</url>
<modules>
<module>user-module-api</module>
<module>user-module-provider</module>
<module>user-module-consumer</module>
</modules>
<properties>
<dubbo.version>2.5.3</dubbo.version>
<spring.version>4.3.7.RELEASE</spring.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.fanlychie</groupId>
<artifactId>user-module-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<!-- dubbo依赖的spring版本(2.5)较低, 排除此依赖, 使用自己的spring版本 -->
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</exclusion>
</exclusions>
<version>${dubbo.version}</version>
</dependency>
<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.8.8</version>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>

1.2 服务接口模块

user-module-api/pom.xml 配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.fanlychie</groupId>
<artifactId>dubbo-quickstart-sample</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>user-module-api</artifactId>
<packaging>jar</packaging>
<name>user-module-api</name>
<url>http://maven.apache.org</url>
</project>

编写注册用户的示例服务接口:

1
2
3
4
5
6
7
package org.fanlychie.service;
public interface UserService {
void register(String username, String password);
}

1.3 服务提供者

user-module-provider/pom.xml 配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.fanlychie</groupId>
<artifactId>dubbo-quickstart-sample</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>user-module-provider</artifactId>
<packaging>jar</packaging>
<name>user-module-provider</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>org.fanlychie</groupId>
<artifactId>user-module-api</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 打包配置, 输出可执行的 jar 包 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifest>
<mainClass>com.alibaba.dubbo.container.Main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
</project>

实现服务接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
package org.fanlychie.service;
public class UserServiceImpl implements UserService {
@Override
public void register(String username, String password) {
System.out.println("---------------------------------------------------------");
System.out.println(String.format("接收到注册用户请求 - {username:%s, password:%s}",
username, password));
System.out.println("---------------------------------------------------------");
}
}

user-module-provider/src/main/resources/dubbo.properties 配置如下:

1
2
3
4
# 服务容器
dubbo.container=spring
# 容器加载的 spring 配置文件
dubbo.spring.config=classpath:spring-dubbo-provider.xml

user-module-provider/src/main/resources/spring-dubbo-provider.xml 配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?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://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="user-module-provider"/>
<!-- 使用ZK注册中心暴露服务地址 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!-- 用Dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880"/>
<!-- 和本地Bean一样实现服务 -->
<bean id="userService" class="org.fanlychie.service.UserServiceImpl"/>
<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="org.fanlychie.service.UserService" ref="userService"/>
</beans>

user-module-provider/src/main/resources/log4j.properties 配置如下:

1
2
3
4
5
log4j.rootCategory = INFO, console
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.target = System.out
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.conversionPattern = %d{yyyy-MM-dd HH:mm:ss:SSS} [%t] %-5p [%c{1}:%L] - %m%n

1.4 服务消费者

user-module-consumer/pom.xml 配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.fanlychie</groupId>
<artifactId>dubbo-quickstart-sample</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>user-module-consumer</artifactId>
<packaging>war</packaging>
<name>user-module-consumer</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>org.fanlychie</groupId>
<artifactId>user-module-api</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
</dependency>
</dependencies>
<build>
<finalName>autosellrobot-wechat</finalName>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<path>/</path>
<port>8080</port>
<uriEncoding>UTF-8</uriEncoding>
<url>http://localhost:8080/manager/html</url>
</configuration>
</plugin>
</plugins>
</build>
</project>

编写用户注册的服务方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/user/register")
public String register(String username, String password) {
if (!StringUtils.hasText(username) || !StringUtils.hasText(password)) {
return "用户名或密码不能为空";
}
userService.register(username, password);
return "注册完成";
}
}

user-module-consumer/src/main/webapp/WEB-INF/web.xml 配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>encodingFilter</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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<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:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

user-module-consumer/src/main/resources/spring-context.xml 配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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: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/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<context:component-scan base-package="org.fanlychie"/>
<import resource="spring-dubbo-consumer.xml"/>
</beans>

user-module-consumer/src/main/resources/spring-dubbo-consumer.xml 配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?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://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="user-module-consumer"/>
<!-- 使用ZK注册中心暴露服务地址 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!-- 生成远程服务代理,可以和本地Bean一样使用 -->
<dubbo:reference id="userService" interface="org.fanlychie.service.UserService" />
</beans>

user-module-consumer/src/main/resources/spring-mvc.xml 配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?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: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/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="useSuffixPatternMatch" value="true"/>
<property name="useTrailingSlashMatch" value="true"/>
</bean>
<bean id="stringHttpMessageConverter" class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=utf-8</value>
<value>application/xml;charset=utf-8</value>
<value>application/json;charset=utf-8</value>
</list>
</property>
</bean>
<bean id="mappingJackson2HttpMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="prefixJson" value="false"/>
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=utf-8</value>
<value>application/xml;charset=utf-8</value>
<value>application/json;charset=utf-8</value>
</list>
</property>
</bean>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="stringHttpMessageConverter"/>
<ref bean="mappingJackson2HttpMessageConverter"/>
</list>
</property>
</bean>
<context:component-scan base-package="org.fanlychie.**.controller"/>
</beans>

user-module-consumer/src/main/resources/log4j.properties 配置如下:

1
2
3
4
5
log4j.rootCategory = INFO, console
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.target = System.out
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.conversionPattern = %d{yyyy-MM-dd HH:mm:ss:SSS} [%t] %-5p [%c{1}:%L] - %m%n

2. 启动服务

首先需要先启动 zookeeper 服务(可参考Zookeeper安装和配置),再启动 dubbo-admin 应用(可选,可参考dubbo-admin管理控制台应用安装)。

2.1 启动服务提供者

本示例将启用2个服务提供者的实例,并使用 dubbo 提供的com.alibaba.dubbo.container.Main启动类来启动服务提供者的实例。下面介绍3种较为常用的启动命令。

2.1.1 maven 命令启动
1
2
3
4
# 启动第一个实例, 端口 20881
> mvn exec:java -Ddubbo.protocol.port=20881 -Dexec.mainClass=com.alibaba.dubbo.container.Main
# 启动第二个实例, 端口 20882
> mvn exec:java -Ddubbo.protocol.port=20882 -Dexec.mainClass=com.alibaba.dubbo.container.Main
2.1.2 application 启动

以开发工具 IntelliJ IDEA 为例,Run -> Edit Configurations添加一个 Application,配置如下:

2.1.3 jar 包启动

在父模块项目 dubbo-quickstart-sample 根目录下执行打包命令:

1
> mvn package

执行完成之后,在 dubbo-quickstart-sample/user-module-provider/target 目录下将得到一个可执行的 jar 包:user-module-provider-0.0.1-SNAPSHOT.jar

1
2
3
4
# 启动第一个实例, 端口 20881
> java -jar -Ddubbo.protocol.port=20881 user-module-provider-0.0.1-SNAPSHOT.jar
# 启动第二个实例, 端口 20882
> java -jar -Ddubbo.protocol.port=20882 user-module-provider-0.0.1-SNAPSHOT.jar

2.2 启动服务消费者

服务消费者 user-module-consumer 是一个 web 项目,使用内置 tomcat 容器或部署到外部的 tomcat 运行即可。

如使用内置 tomcat 插件启动的 maven 命令:

3. 访问服务

访问地址:http://localhost:8080/user/register?username=fanlychie&password=123456可在服务提供者的控制台查看相关的输出信息。你也可以在 dubbo-admin 应用查看和管理相关的服务:

示例项目开发环境:Java-8、Maven-3、IntelliJ IDEA-2017、Spring-4.7、Dubbo-2.5.3
完整示例项目链接:dubbo-quickstart-sample
参考文档文献链接:dubbo用户指南