说来惭愧,自己工作了将近7年时间,却从来没有用到过dubbo,一款非常出名的分布式服务治理框架。当然,也不是完全没有接触过远程服务调用,之前的项目,多多少少用到过RMI,以及WebService,一些大厂也有自己的分布式服务框架,比如以前的部门内有一个叫天路的服务框架,在JD,内部也有叫做杰夫的框架,但毕竟都不是直接使用了dubbo。在分布式,高并发,大数据这些概念十分流行的当下,如果还对这些一无所知,那么出去真的都不好意思说自己是做JAVA服务端应用开发的。
当你出去面试的时候,面试官也多多少少会问到dubbo,如果对其毫无所知,恐怕会给面试官留下非常不好的印象,成功的功能性也大打折扣。基于此,前段时间简单了解了一下dubbo,虽然这个框架好长时间没有经更新了(但最近好像是连着更新了三个版本,看来这个框架又焕发了生机),但这款开源框架中涉及到的知识点非常多,如果能够钻研通透,对于个人知识面的拓展和一些技术的提高非常有帮助。所以,计划花一段时间(3个月)的空闲时间把这个框架认真的学习下,并及时总结,今天是第一篇,总结一下我们为什么要用dubbo,以及自己如何使用dubbo来搭建的第一个例子。
一、什么是dubbo
学习的最好方式是看官方文档,作为一个之前对dubbo一无所知的人,我最刚开始是在CSDN上疯狂地找各种介绍dubbo入门的例子,同时也看官方文档,但对比之下,还是官方文档介绍的比较清楚,所以本文中很多介绍以及图例,都会直接引用官方文档中的相关介绍。比如对于dubbo的介绍。
那么什么是dubbo呢?我们直接引用官网首页的一段话的定义,如下:
Dubbo |ˈdʌbəʊ| is ahigh-performance, java basedRPC framework open-sourced by Alibaba. As in many RPC systems, dubbo is based around the idea of defining a service, specifying the methods thatcan be called remotelywith their parameters and return types. On the server side, the server implements this interface and runs a dubbo server to handle client calls. On the client side, the client has a stub that provides the same methods as the server.
上面的大概意思,就是说dubbo是阿里开源的一个款基于JAVA的高性能的RPC框架,和别的RPC框架一样,其作用也是为了支持服务能够远程调用,服务的提供端启动一个dubbo服务器来处理请求,服务使用端只需要有接口的声明。也就是说,dubbo框架的主要作用,就是支持远程服务调用调用。这也是RPC的定义之所在(Remote Procedure Call)。
二、为什么我们要使用dubbo
这个其实要分两个方面来回答,即首先,为什么我们要使用RPC,直接本地服务调用行不行?二是,在当前的RPC框架中,为什么我们要使用dubbo而不是别的?
同样,我们借用dubbo手册上的图来描述一下,如下:
上图描述了系统的规模在不同的量级时,系统结构可能发生的一些变化。
1)1- 10: 这个阶段网站流量一般都比较小,系统功能也不复杂,那么,把所有的应用部署在一起,甚至是把数据库和WEB应用共用一台机器都没有问题,比如以前在我读研的阶段我曾为人事处做过所里的职工考勤系统,那么这个系统几乎只有负责考勤的几个职工使用,功能上也比较简单,这种肯定就没有必要用分布式。
2)10-1000:这个时候系统变复杂了,可能是需要把一个大的应用拆分成几个独立的应用,这种适合于那种应用间相对独立的系统,比如一个学校网站应用中,新闻模块和论坛模块就基本上可以拆分为两个独立的应用。
3)1000~1000: 应用越来越复杂,而且应用间有交互,所以需要把服务模块抽取出来单独作为服务供多个模块调用,这个时候要用到RPC框架了,比如我们之前做过一个CRM系统,多个子系统都需要用到客户管理的相关服务,但CRM终究是一个内部系统,只是业务复杂,所以当时就使用了RMI来暴露一部分服务作为远程服务。
4)10000+:当应用规模继续扩大,服务越来越多,为了更好的管理和监控这些服务,那么就需要进行服务化(SOA)。
对比系统结构的演进,我们可以发现服务化是在系统应用发展到一定规模时,为了更好的管理服务,保证整个系统运行的稳定性,不得不采用的一种技术手段。相比RMI,Hessian等RPC框架, dubbo使用更简单,扩展性更好,而且可以监控服务的使用情况,所以自其开源之后,很多公司也是当其作为RPC框架的首选。
当然,并不是说,规模小的应用就不能使用dubbo,作为一种优秀的架构,如果刚开始就能实现服务化,那么在后续扩展时,就会方便得多。
三、如何使用
记得刚工作了一年多之后,想换工作,去一个公司面试的时候,那位面试官问了我一个问题,说你是怎么学习一个新的框架的?我说那就看文档,从头到尾看一篇。那个面试官说,其实最好的方式是自己动手去写一个例子,把程序跑起来,然后再去研究这个框架在这个例子中起到了什么。后来我记住了这句话,每当学习新东西的时候,第一要做的事情,就是搭环境,跑例子。比如说你要学es,那么先下载一个ES安装起来,建个索引,存储点数据再查询试试。同样,下面我们就结合官网的例子来真实的使用一把。
由于我们实际使用dubbo时都以WEB服务的形式,而官网的例子里,服务提供都和使用者都是一个简单的main函数,所以我们稍加改造,用WEB应用的方式来发布服务和使用。
1)首先我们要引入dubbo的相关maven依赖,如下:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.7</version>
</dependency>
2)其次,我们要定义一个服务接口,由于这个需要在客户端和服务端共用,所以我们可以用一个单独的模块来定义,如下:
package com.jd.macs.service;
/**
* Created by machangsheng on 17/11/15.
*/
public interface DemoService {
String sayHello(String name);
}
3)在服务端,我们引入第二步的模块,并实现其定义的服务接口,如下:
package com.jd.macs.service.impl;
import com.jd.macs.service.DemoService;
/**
* Created by machangsheng on 17/11/15.
*/
public class DemoServiceImpl implements DemoService {
public String sayHello(String name) {
return "Hello " + name;
}
}
<?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="demo-provider"/>
<dubbo:registry address="multicast://224.5.6.7:1234"/>
<dubbo:protocol name="dubbo" port="20880"/>
<dubbo:service interface="com.jd.macs.service.DemoService" ref="demoService"/>
<bean id="demoService" class="com.jd.macs.service.impl.DemoServiceImpl"/>
</beans>
4.1)dubbo:application 这个用于指定生产者的名称
4.2)dubbo:registy 定义注册中心的协议及广播地址,此处使用的协议是multicast. 此外还有zookeeper, redis, simple.
4.3) dubbo:protocal 定义协议,实际上默认的协议就是dubbo,所以这个是可选的
4.4)dubbo:service 定义要发布的服务,其ref中指向demoService,一个普通的bean,表示接口用它来实现
至此,服务端的dubbo使用要用到的配置就算是完成了,结合springmvc的配置,我们可以启动一个服务端WEB应用,这样服务就算是正常发布了。很简单的样子。
5)定义消费端的引用,也可以直接在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="demo-consumer"/>
<dubbo:registry address="multicast://224.5.6.7:1234"/>
<!-- define demo service -->
<dubbo:reference interface="com.jd.macs.service.DemoService"
id="demoService" />
</beans>
除开前面介绍的,可以看到这里定义了一个reference,标明了这个服务的接口类型,但并没有指定实现类,这样消费者端也就定义好了。
6)编写必要的页面,web.xml,spring mvc 的配置文件, Controller,这里以服务消费者为例,服务提供者与之类似,就不再一一写出。
其实我们的关键在于这三个文件,这三个文件设置好了,WEB应用也就算搭建好了,下面介绍如下:
6.1) web.xml
这个就是配置如何引用spring的配置文件和设置DispatcherServlet,如下:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!-- spring configuration -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/spring/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dubbo-demo-provider</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dubbo-demo-consumer</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
6.2)springmvc.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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
">
<context:component-scan base-package="com.jd.macs.dubbodemo.controller" />
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
6.3)Controller定义如下:
package com.jd.macs.dubbodemo.controller;
import com.jd.macs.service.DemoService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.annotation.Resource;
/**
* 演示用Controller
* Created by machangsheng on 17/11/15.
*/
@RequestMapping("/dubbo-demo")
@Controller
public class IndexController {
@Resource
private DemoService demoService;
@RequestMapping("/")
public String index(){
return "index";
}
@RequestMapping("/sayHello")
public String sayHello(String name,Model model){
String sayHello = demoService.sayHello(name);
model.addAttribute("hello", sayHello);
return "sayHello";
}
}
7) 配置好tomcat,provider和consumer都启动起来,访问测试,结果如下:
至此,一个简单的dubbo发布与调用的示例程序就写完了,除了引入dubbo, 我们并没有依赖其它的第三方框架(当然spring和spring mvc除外)。
四、总结
总结一下,在项目中引用dubbo还是比较方便的,示例中,我们仅仅是在spring的配置文件中增加了几个dubbo的配置,而其它的都跟搭建一个普通的web项目相比没有任何不同,这说明dubbo的侵入性还是比较小的,而且也帮我们做了很多事情。但这毕竟是个demo,不代表在正式环境中我们一定也可以这样使用。所以接下来,还有很多事情要做。
至少,我们要了解以下内容:
1)dubbo是如何工作的,如何连接的消费者和生产者?
2)如何监控服务的注册及使用情况?
3)生产环境的使用方式和demo有无差别,应该如何使用?
对于这些问题,我目前也回答不上来,但是我会带着这些问题,查资料也好,分析源码也好,会在接下的学习中慢慢去理解,在下一篇博文中,会基于这个简单的demo,重点分析dubbo的工作流程。