dubbo的简单应用

一. dubbo简介

  dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,是阿里巴巴SOA服务化治理方案的核心框架。

 

二. 架构

  引用dubbo的架构图:

  • Provider: 暴露服务的服务提供方。
  • Consumer: 调用远程服务的服务消费方。
  • Registry: 服务注册与发现的注册中心。
  • Monitor: 统计服务的调用次调和调用时间的监控中心。
  • Container: 服务运行容器。

三. 应用

  从上图可知dubbo存在两个基本的角色:服务提供者Provider和服务消费者Consumer。

  它的原理其实是dubbo服务提供者暴露出服务,然后消费者请求暴露的服务,由dubbo创建服务代理处理业务。其中接口服务是消费者和提供者共享的。

  下面列举一个最简单的项目来示例用法,项目示例使用maven构建。

  1. 服务提供者

  项目采用多模块构建,项目结构如下:

  

  模块说明:

  common:共同享用的模块,一般存放domain或者常用的工具类。

  service: 暴露的service服务接口。

  service-impl: 服务的实现类,也就是业务层逻辑代码。

  web: 服务启动的模块,一般是项目配置和页面等。

  模块直接的关系如下图:

  

  pom.xml仅引入了必须的jar包支持,且只应用在父模块的pom.xml:

  

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 4     <modelVersion>4.0.0</modelVersion>
 5     <groupId>com.bigbang</groupId>
 6     <artifactId>provider</artifactId>
 7     <version>0.0.1-SNAPSHOT</version>
 8     <packaging>pom</packaging>
 9     <name>注册中心</name>
10     <description>服务注册</description>
11     <properties>
12         <spring.version>3.2.4.RELEASE</spring.version>
13     </properties>
14     <dependencies>
15         <dependency>
16             <groupId>junit</groupId>
17             <artifactId>junit</artifactId>
18             <version>3.8.1</version>
19             <scope>test</scope>
20         </dependency>
21         <dependency>
22             <groupId>org.springframework</groupId>
23             <artifactId>spring-context</artifactId>
24             <version>${spring.version}</version>
25         </dependency>
26 
27         <dependency>
28             <groupId>org.springframework</groupId>
29             <artifactId>spring-core</artifactId>
30             <version>${spring.version}</version>
31         </dependency>
32 
33         <dependency>
34             <groupId>org.springframework</groupId>
35             <artifactId>spring-beans</artifactId>
36             <version>${spring.version}</version>
37         </dependency>
38 
39         <dependency>
40             <groupId>org.springframework</groupId>
41             <artifactId>spring-webmvc</artifactId>
42             <version>${spring.version}</version>
43         </dependency>
44         <dependency>
45             <groupId>com.alibaba</groupId>
46             <artifactId>dubbo</artifactId>
47             <version>2.5.3</version>
48         </dependency>
49     </dependencies>
50     <build>
51         <plugins>
52             <plugin>
53                 <groupId>org.apache.maven.plugins</groupId>
54                 <artifactId>maven-compiler-plugin</artifactId>
55                 <configuration>
56                     <source>1.8</source>
57                     <target>1.8</target>
58                 </configuration>
59             </plugin>
60         </plugins>
61         <finalName>service</finalName>
62     </build>
63     <modules>
64         <module>service</module>
65         <module>service-impl</module>
66         <module>common</module>
67         <module>web</module>
68     </modules>
69 </project>
pom.xml

 

   dobbo可以完全使用spring的配置来做或者完全使用注解的方式。因为这里都是使用了最简洁的构建,所以仅使用了spring框架作为dubbo的支撑。

   common模块只定义了domain,这里使用一个User的栗子,此处需要注意的是,如果要在分布式中传递对象,该对象必须序列化

  

 1 public class User implements Serializable {
 2 
 3     private static final long serialVersionUID = 1L;
 4     private Long id;
 5     private String name;
 6     private int age;
 7 
 8     public Long getId() {
 9         return id;
10     }
11 
12     public void setId(Long id) {
13         this.id = id;
14     }
15 
16     public String getName() {
17         return name;
18     }
19 
20     public void setName(String name) {
21         this.name = name;
22     }
23 
24     public int getAge() {
25         return age;
26     }
27 
28     public void setAge(int age) {
29         this.age = age;
30     }
31 
32     @Override
33     public String toString() {
34         return "User [id=" + id + ", name=" + name + ", age=" + age + "]";
35     }
36 
37 }

  service模块中定义了一个service接口,用于暴露服务:

  

1 import com.bigbang.common.domain.User;
2 
3 public interface UserService {
4 
5     User getUserById(Long id);
6     
7 }

  service-impl中代码是对服务的实现:

  

 1 import com.bigbang.common.domain.User;
 2 import com.bigbang.service.UserService;
 3 
 4 public class UserServiceImpl implements UserService {
 5 
 6     @Override
 7     public User getUserById(Long id) {
 8         User user = new User();
 9         user.setId(id);
10         user.setAge(20);
11         user.setName("BigBang");
12         return user;
13     }
14 
15 }

   web模块没有代码,仅作为项目的启动,配置了spring和dubbo的配置文件,首先spring的配置,applicationContext.xml:

  

1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
4     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
5         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
6         
7     <import resource="dubbo.xml" />
8 </beans>

   这里引入了dubbo的配置文件,dubbo.xml:

  

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
 4     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo  
 5     http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
 6 
 7     <!-- 提供方应用信息,用于计算依赖关系 -->
 8     <dubbo:application name="provider" />
 9     
10     <!-- 使用multicast广播注册中心暴露服务地址 -->
11     <dubbo:registry address="multicast://224.5.6.7:1234" />
12     
13     <!-- 用dubbo协议在20880端口暴露服务 -->
14     <dubbo:protocol name="dubbo" port="20880" />
15     
16     <!-- 声明需要暴露的服务接口 -->
17     <dubbo:service interface="com.bigbang.service.UserService"
18         ref="userService" />
19         
20     <bean id="userService" class="com.bigbang.service.impl.UserServiceImpl" />
21 </beans>

  

  项目启动文件web.xml配置仅加载spring:

  

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <web-app id="WebApp_ID" version="2.5"
 3     xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
 5     <context-param>
 6         <param-name>contextConfigLocation</param-name>
 7         <param-value>classpath*:applicationContext.xml</param-value>
 8     </context-param>
 9     <listener>
10         <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
11     </listener>
12     <welcome-file-list>
13         <welcome-file>index.jsp</welcome-file>
14     </welcome-file-list>
15 </web-app>

 

    2. 服务消费者

    服务消费者可以看做是一个客户端,不限于web或者普通的java程序,此处还是使用一个maven webapp项目作为示例,为了从简,使用spring支撑dubbo,使用servlet做应用请求。

   项目结构如下:

  

  pom.xml文件如下,仅引入spring和dubbo必须的包:

  

 1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 2     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 3     <modelVersion>4.0.0</modelVersion>
 4     <groupId>com.bigbang</groupId>
 5     <artifactId>consumer</artifactId>
 6     <packaging>war</packaging>
 7     <version>0.0.1-SNAPSHOT</version>
 8     <name>consumer</name>
 9     <properties>
10         <spring.version>3.2.4.RELEASE</spring.version>
11     </properties>
12     <dependencies>
13         <dependency>
14             <groupId>junit</groupId>
15             <artifactId>junit</artifactId>
16             <version>3.8.1</version>
17             <scope>test</scope>
18         </dependency>
19         <dependency>
20             <groupId>javax.servlet</groupId>
21             <artifactId>servlet-api</artifactId>
22             <version>2.3</version>
23         </dependency>
24         <dependency>
25             <groupId>org.springframework</groupId>
26             <artifactId>spring-context</artifactId>
27             <version>${spring.version}</version>
28         </dependency>
29 
30         <dependency>
31             <groupId>org.springframework</groupId>
32             <artifactId>spring-core</artifactId>
33             <version>${spring.version}</version>
34         </dependency>
35 
36         <dependency>
37             <groupId>org.springframework</groupId>
38             <artifactId>spring-beans</artifactId>
39             <version>${spring.version}</version>
40         </dependency>
41 
42         <dependency>
43             <groupId>org.springframework</groupId>
44             <artifactId>spring-webmvc</artifactId>
45             <version>${spring.version}</version>
46         </dependency>
47         <dependency>
48             <groupId>org.springframework</groupId>
49             <artifactId>spring-orm</artifactId>
50             <version>${spring.version}</version>
51         </dependency>
52 
53         <dependency>
54             <groupId>com.alibaba</groupId>
55             <artifactId>dubbo</artifactId>
56             <version>2.5.3</version>
57         </dependency>
58 
59         <dependency>
60             <groupId>com.bigbang</groupId>
61             <artifactId>service</artifactId>
62             <version>0.0.1-SNAPSHOT</version>
63         </dependency>
64     </dependencies>
65     <build>
66         <plugins>
67             <plugin>
68                 <groupId>org.apache.maven.plugins</groupId>
69                 <artifactId>maven-compiler-plugin</artifactId>
70                 <configuration>
71                     <source>1.8</source>
72                     <target>1.8</target>
73                 </configuration>
74             </plugin>
75         </plugins>
76         <finalName>consumer</finalName>
77     </build>
78 </project>
pom.xml

 

  application.xml配置文件如下:

  

1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
5 
6     <import resource="dubbo.xml" />
7 </beans>

  dubbo.xml配置文件如下:

  

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
 4     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo  
 5     http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
 6 
 7     <!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
 8     <dubbo:application name="consumer" />
 9 
10     <!-- 使用multicast广播注册中心暴露发现服务地址 -->
11     <dubbo:registry address="multicast://224.5.6.7:1234" />
12     
13     <!-- 用dubbo协议在20880端口暴露服务 -->
14     <dubbo:protocol name="dubbo" port="20880" />
15 
16     <!-- 生成远程服务代理,可以和本地bean一样使用 -->
17     <dubbo:reference id="userService" interface="com.bigbang.service.UserService" />
18 </beans>

  项目启动配置文件web.xml:

  

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3     xmlns="http://java.sun.com/xml/ns/javaee"
 4     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
 5     id="WebApp_ID" version="2.5">
 6     <display-name>consumer</display-name>
 7     <context-param>
 8         <param-name>contextConfigLocation</param-name>
 9         <param-value>classpath*:applicationContext.xml</param-value>
10     </context-param>
11     <listener>
12         <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
13     </listener>
14     <welcome-file-list>
15         <welcome-file>index.jsp</welcome-file>
16     </welcome-file-list>
17     <servlet>
18         <description>用户查询servlet</description>
19         <display-name>UserQueryServlet</display-name>
20         <servlet-name>UserQueryServlet</servlet-name>
21         <servlet-class>com.bigbang.servlet.UserQueryServlet</servlet-class>
22         <load-on-startup>1</load-on-startup>
23     </servlet>
24     <servlet-mapping>
25         <servlet-name>UserQueryServlet</servlet-name>
26         <url-pattern>/userQueryServlet</url-pattern>
27     </servlet-mapping>
28 </web-app>

   index.jsp页面很简单,就是做一个提交form的请求:

  

1 <form action="/userQueryServlet" method="post">
2         ID:<input name="id" type="text" placeholder="请输入要查询的id" /><br/>
3     <input type="submit" value="sumbit"/>
4 </form>

  UserServlet.java代码也很简单,仅仅用于接收请求并且调用暴露的服务:

  

 1 package com.bigbang.servlet;
 2 
 3 import java.io.IOException;
 4 import javax.servlet.ServletException;
 5 import javax.servlet.http.HttpServlet;
 6 import javax.servlet.http.HttpServletRequest;
 7 import javax.servlet.http.HttpServletResponse;
 8 
 9 import org.springframework.web.context.ContextLoader;
10 import org.springframework.web.context.WebApplicationContext;
11 
12 import com.bigbang.common.domain.User;
13 import com.bigbang.service.UserService;
14 
15 public class UserQueryServlet extends HttpServlet {
16     private static final long serialVersionUID = 1L;
17 
18     private UserService userService;
19 
20     /**
21      * @see HttpServlet#HttpServlet()
22      */
23     public UserQueryServlet() {
24         super();
25     }
26 
27     /**
28      * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
29      *      response)
30      */
31     protected void doGet(HttpServletRequest request, HttpServletResponse response)
32             throws ServletException, IOException {
33         doPost(request, response);
34     }
35 
36     /**
37      * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
38      *      response)
39      */
40     protected void doPost(HttpServletRequest request, HttpServletResponse response)
41             throws ServletException, IOException {
42         String idStr = request.getParameter("id");
43         Long id = Long.parseLong(idStr);
44         User user = userService.getUserById(id);
45         response.getWriter().write(user.toString());
46     }
47 
48     @Override
49     public void init() throws ServletException {
50         super.init();
51         WebApplicationContext applicationContext = ContextLoader.getCurrentWebApplicationContext();
52         UserService userService = (UserService) applicationContext.getBean("userService");
53         this.userService = userService;
54         System.out.println("获取userService对象完成:" + userService);
55     }
56 
57 }

  在servlet的init()方法中,我使用了spring类获取暴露的服务接口,实际上获取到的是dubbo创建的代理对象。

  

 

四. 运行

  因为dubbo是基于长连接发送数据的,所以消息订阅者在启动时就会去查找这个认为已经注册的服务,如果不存在这个服务,则会报错。所以应该先注册服务,在开启订阅者订阅。故应该先启动Provider项目再启动Consumer项目。

  一切运行成功之后,打开Consumer的index.jsp页面:

  

 

  输入id点击提交之后:

  

  说明服务调用成功,分布式作用起效了。

 

五. 总结

  此代码仅作为抛砖引玉的作用,用来说明dubbo的基本应用。dubbo官方的文档写的很详细,从配置到说明示例。目前很多地方还没有探索到,比如启动是顺序其实可以设置服务启动时候是否检查,暴露服务的协议使用hessian还是dubbo,服务超时连接设置、服务暴露方式使用zookeeper等等。

 

 

  

   

 

posted @ 2017-06-21 17:12  BigBang92  阅读(1837)  评论(0编辑  收藏  举报