dubbo的简单应用

一. dubbo简介

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

二. 架构

  引用dubbo的架构图:

dubbo的简单应用

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

三. 应用

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

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

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

  1. 服务提供者

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

  dubbo的简单应用

  模块说明:

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

  service: 暴露的service服务接口。

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

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

  模块直接的关系如下图:

  dubbo的简单应用

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

  

 <?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bigbang</groupId>
<artifactId>provider</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>注册中心</name>
<description>服务注册</description>
<properties>
<spring.version>3.2.4.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
<finalName>service</finalName>
</build>
<modules>
<module>service</module>
<module>service-impl</module>
<module>common</module>
<module>web</module>
</modules>
</project>

pom.xml

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

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

  

 public class User implements Serializable {

     private static final long serialVersionUID = 1L;
private Long id;
private String name;
private int age; public Long getId() {
return id;
} public void setId(Long id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} @Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", age=" + age + "]";
} }

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

  

 import com.bigbang.common.domain.User;

 public interface UserService {

     User getUserById(Long id);

 }

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

  

 import com.bigbang.common.domain.User;
import com.bigbang.service.UserService; public class UserServiceImpl implements UserService { @Override
public User getUserById(Long id) {
User user = new User();
user.setId(id);
user.setAge(20);
user.setName("BigBang");
return user;
} }

  web模块没有代码,仅作为项目的启动,配置了spring和dubbo的配置文件,首先spring的配置,applicationContext.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: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-3.2.xsd"> <import resource="dubbo.xml" />
</beans>

   这里引入了dubbo的配置文件,dubbo.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://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="provider" /> <!-- 使用multicast广播注册中心暴露服务地址 -->
<dubbo:registry address="multicast://224.5.6.7:1234" /> <!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880" /> <!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="com.bigbang.service.UserService"
ref="userService" /> <bean id="userService" class="com.bigbang.service.impl.UserServiceImpl" />
</beans>

  

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

  

 <?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" 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*:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

  2. 服务消费者

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

   项目结构如下:

  dubbo的简单应用

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

  

 <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>com.bigbang</groupId>
<artifactId>consumer</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>consumer</name>
<properties>
<spring.version>3.2.4.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
</dependency> <dependency>
<groupId>com.bigbang</groupId>
<artifactId>service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
<finalName>consumer</finalName>
</build>
</project>

pom.xml

  application.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <import resource="dubbo.xml" />
</beans>

  dubbo.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://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="consumer" /> <!-- 使用multicast广播注册中心暴露发现服务地址 -->
<dubbo:registry address="multicast://224.5.6.7:1234" /> <!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880" /> <!-- 生成远程服务代理,可以和本地bean一样使用 -->
<dubbo:reference id="userService" interface="com.bigbang.service.UserService" />
</beans>

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

  

 <?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>consumer</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<description>用户查询servlet</description>
<display-name>UserQueryServlet</display-name>
<servlet-name>UserQueryServlet</servlet-name>
<servlet-class>com.bigbang.servlet.UserQueryServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>UserQueryServlet</servlet-name>
<url-pattern>/userQueryServlet</url-pattern>
</servlet-mapping>
</web-app>

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

  

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

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

  

 package com.bigbang.servlet;

 import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext; import com.bigbang.common.domain.User;
import com.bigbang.service.UserService; public class UserQueryServlet extends HttpServlet {
private static final long serialVersionUID = 1L; private UserService userService; /**
* @see HttpServlet#HttpServlet()
*/
public UserQueryServlet() {
super();
} /**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
} /**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String idStr = request.getParameter("id");
Long id = Long.parseLong(idStr);
User user = userService.getUserById(id);
response.getWriter().write(user.toString());
} @Override
public void init() throws ServletException {
super.init();
WebApplicationContext applicationContext = ContextLoader.getCurrentWebApplicationContext();
UserService userService = (UserService) applicationContext.getBean("userService");
this.userService = userService;
System.out.println("获取userService对象完成:" + userService);
} }

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

  

四. 运行

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

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

  dubbo的简单应用

  输入id点击提交之后:

  dubbo的简单应用

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

五. 总结

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

  

   

上一篇:Java 创建 Excel 数据透视表


下一篇:SASS 初学者入门