初识dubbo

说来惭愧,自己工作了将近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;
    }
}


4)dubbo的服务可以直接在xml中定义,我们定义spring的配置文件,如下:

<?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>


看上面的例子,对于demoService的定义还比较常规,就是spring的通用定义方式,而增加的几个定义需要解析一下:

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的工作流程。







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值