Dubbo入门学习笔记

原创 2017年01月02日 22:54:41

本文为博主原创,允许转载,但请声明原文地址:http://www.coselding.cn/article/2017-01-02/dubbo-study-record.html

Dubbo是什么

Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合)。从服务模型的角度来看,Dubbo采用的是一种非常简单的模型,要么是提供方提供服务,要么是消费方消费服务,所以基于这一点可以抽象出服务提供方(Provider)和服务消费方(Consumer)两个角色。
简单说呢,Dubbo用起来就和EJB、WebService差不多,调用一个远程的服务(或者JavaBean)的时候在本地有一个接口,就像调用本地的方法一样去调用,它底层帮你实现好你的方法参数传输和远程服务运行结果传回之后的返回,就是RPC的一种封装啦~
当然,这个只是Dubbo的最基本的功能,它的特点是:
1. 它主要是使用高效的网络框架和序列化框架,让分布式服务之间调用效率更高。
2. 采用注册中心管理众多的服务接口地址,当你想调用服务的时候只需要跟注册中心询问即可,不用像使用WebService一样每个服务都得记录好接口调用方式。
3. 监控中心:实现对服务方和调用方之间运行状态的监控,还能控制服务的优先级、权限、权重、上下线等,让整个庞大的分布式服务系统的维护和治理比较方便。
4. 高可用:有个服务宕机了?注册中心就会从服务列表去掉该节点。还是调用到了?客户端会向注册中心请求另一台可用的服务节点重新调用。注册中心宕机?注册中心也能实现高可用(ZooKeeper)。
5. 负载均衡:采用软负载均衡算法实现对多个相同服务的节点的请求负载均衡。
6. 等等。。。很多高大上的,看官方文档吧,我也是文档中抄过来的~

一些参考站点或博客

* 注意 *

所有东西以官方用户指南为准:http://dubbo.io/User+Guide-zh.htm
其他第三方文章博客什么的可以参考辅助理解,但是由于阿里是国内公司,官方用户指南,特别是中文版都特别详细,真的没有很多必要去找一堆第三方的教程来看啦~

Dubbo环境准备

Dubbo需要四大基本组件:Registry、Monitor、Provider、Consumer。
image
1. 安装注册中心(Registry),我用ZooKeeper,具体参考我的ZooKeeper教程博客,安装好ZooKeeper之后注册中心就有了,先放着,等会用。
2. 安装简单监控中心:simple-monitor。网上找dubbo-monitor-simple-2.8.4-assembly.tar.gz

  • 解压,找到conf文件夹下的dubbo.properties文件,下面简单介绍各个配置参数的意义:
# 容器,就是说这个简单监控中心是在jetty和spring环境下运行的,依赖于注册中心,日志系统是log4j
dubbo.container=log4j,spring,registry,jetty
# 监控系统对整个Dubbo服务系统来说也是一个服务,这里指定了这个监控服务的名称
dubbo.application.name=simple-monitor
# 服务的所有者,这是Dubbo的服务的功能,可以指定服务的负责人
dubbo.application.owner=coselding
# 下面四个是指定注册中心地址的,分别为广播、zookeeper、redis、dubbo(自带)方式的注册中心,前面说了,我用的是Zookeeper(前面配好了),因此去掉zookeeper前面的#,配置zookeeper的ip和端口号。之后简单监控中心就能通过注册中心获取当前可用的服务列表及其状态,在页面向你汇报Dubbo中的服务运行情况。
#dubbo.registry.address=multicast://224.5.6.7:1234
dubbo.registry.address=zookeeper://{ip}:{port}
#dubbo.registry.address=redis://127.0.0.1:6379
#dubbo.registry.address=dubbo://127.0.0.1:9090
# dubbo协议端口号,保持默认即可
dubbo.protocol.port=7070
# jetty工作端口号,平时不是习惯8080吗?当然,这里为了不影响之后运行的tomcat,就不要占用8080端口啦。
dubbo.jetty.port=8082
# 一个工作目录,在这个目录会保存一些监控中心的数据,比如调用曲线图等,这里指定一个存在的空目录即可
dubbo.jetty.directory=${user.home}/monitor
# 监控中心报表存放的目录,同上,一般默认即可
dubbo.charts.directory=${dubbo.jetty.directory}/charts
# 监控中心数据资料目录,同上,一般默认即可
dubbo.statistics.directory=${user.home}/monitor/statistics
# 监控中心日志文件路径
dubbo.log4j.file=logs/dubbo-monitor-simple.log
# 监控中心日志记录级别
dubbo.log4j.level=WARN
  • 运行bin目录下的start.sh(unix系下)或start.bat(win下)即可。
  • 浏览器访问:http://{简单监控中心所在的主机ip}:8082,端口号是刚才配置文件设置的8082,即可访问查看Dubbo服务集群中的应用和服务的简单情况。
  1. 安装Dubbo管理控制台
    • 下载dubbo-admin-2.8.4.war,这个是Dubbo的管理控制台的webapp的war包,将其解压。
    • WEB-INF目录下的dubbo.properties文件配置Dubbo的信息,如下:

# 配置注册中心地址,和简单监控中心一样,通过注册中心才能监控当前所有可用的服务。
dubbo.registry.address=zookeeper://127.0.0.1:2181
# root账户的密码,网页进入控制台界面之前需要输入帐号密码
dubbo.admin.root.password=root
# guest访客账户的密码
dubbo.admin.guest.password=guest
  • 将修改完配置的dubbo-admin的整个目录复制到tomcat的webapps目录下,重启tomcat,说白了dubbo-admin就是tomcat的一个webapp的形式存在。

Dubbo注册中心

上面已经安装完成了zookeeper的注册中心了,这个注册中心主要就是负责dubbo的所有服务地址列表维护,并且可以通过在ZooKeeper节点中设置相应的值来实现对这个服务的权重、优先级、是否可用、路由、权限等的控制。 你可以先记住,之后在Dubbo的管理控制台对服务的一堆治理策略设置和调整,实际上就是修改了注册中心中的服务对应的配置数据(即修改了zookeeper中服务对应的节点的配置数据)。 之后`Consumer`从注册中心请求到服务的数据时就能根据这些配置数据进行相应的治理配置参数的代码执行生效。

Dubbo样例服务开发

这里我用maven构建项目,在Spring环境中配置Provider和Consumer。 先说明使用的依赖:
        <!-- Spring所需依赖 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>4.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>4.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.2.3.RELEASE</version>
        </dependency>

        <!-- dubbo所需依赖 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.8.4</version>
        </dependency>
        <dependency>
            <groupId>javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.12.0.GA</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.netty</groupId>
            <artifactId>netty</artifactId>
            <version>LATEST</version>
        </dependency>

        <!-- ZooKeeper所需依赖 -->
        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.10</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.12</version>
        </dependency>
  1. Provider
  • 声明服务的接口:
public interface IMyDemo {
        String sayHello(String name);
}
  • 对接口进行实现(这里是Provider,需要真的实现,之后在Consumer端调用接口之后实际就是在这里的实现代码执行所需逻辑的):
public class MyDemo implements IMyDemo {
        @Override
        public String sayHello(String name) {
            String hello = "hello " + name;
            System.out.println(hello);
            return hello;
        }
}
  • Spring配置相应的Dubbo服务(provider.xml):
<?xml version="1.0" encoding="UTF-8"?>
<!-- 这里添加了dubbo的命名空间,之后Spring通过dubbo中扩展的配置解析生成对应的dubbo实例放到Spring的IoC容器中 -->
<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中层次级别是先分为多个应用(可以理解为一个项目),在每个应用下有多个服务(可以理解为项目下具体的某个提供服务的服务类) -->
    <!-- 这里就是指定一个应用的名称,指定相同的应用名的服务在dubbo中都会被分配在同一个应用分支下 -->
    <dubbo:application name="hello-world-app"  />
    <!-- 之前配置好的ZooKeeper服务器作为注册中心,这里指定好ZooKeeper的地址,此处的Dubbo才能连接上注册服务器,很好理解 -->
    <dubbo:registry address="zookeeper://119.29.153.56:2181" id="registry" />
    <!-- Dubbo的每个节点之间通信可以支持rmi、Http、Dubbo等一系列的协议,这里指定默认的dubbo协议,以及此处的服务Provider对外暴露的服务端口号 -->
    <dubbo:protocol name="dubbo" port="20880" />
    <!-- 到这里,这个Provider节点就已经能连上注册服务器,并使用指定的协议进行通信了 -->
    <!-- 这里对外暴露刚才编写的接口,并指定IoC容器中接口的实现来为这个接口提供实际的服务 -->
    <dubbo:service interface="com.weidian.dubbo.IMyDemo" ref="myDemo"/>
    <!-- 这里是Spring原始的JavaBean声明方式,并放在IoC容器中 -->
    <bean id="myDemo" class="com.weidian.dubbo.MyDemo"/>
</beans>
  • 本地测试一下这个服务是否可用,这里还没用到Dubbo,只是先测试一下Spring容器是否有问题:
@org.junit.Test
public void testDubbo() throws InterruptedException {
        ApplicationContext providerContext = new ClassPathXmlApplicationContext("provider.xml");
        IMyDemo demo = providerContext.getBean(IMyDemo.class);
        System.out.println(demo.sayHello("world"));
        Thread.sleep(60000);
    }
  • 运行结果:
    这里写图片描述
    Provider内部代码输出了一遍,返回到测试代码又输出了一遍,总共两遍hello world
    1. Consumer
  • 编写和Provider服务的对应接口:
public interface IMyDemo {
        String sayHello(String name);
}
  • Spring配置远程的服务为本地的JavaBean(consumer.xml):
<?xml version="1.0" encoding="UTF-8"?>
<!-- 这里添加了dubbo的命名空间,之后Spring通过dubbo中扩展的配置解析生成对应的dubbo实例放到Spring的IoC容器中 -->
<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">
    <!-- 声明要连接的应用名称,要和Provider声明的指定的应用名一致 -->
    <dubbo:application name="hello-world-app"  />
    <!-- 之前配置好的ZooKeeper服务器作为注册中心,这里指定好ZooKeeper的地址,此处的Dubbo才能连接上注册服务器,很好理解 -->
    <dubbo:registry address="zookeeper://119.29.153.56:2181" id="registry" />
    <!-- Dubbo的每个节点之间通信可以支持rmi、Http、Dubbo等一系列的协议,这里指定默认的dubbo协议,
        以及此处的Consumer对外暴露的服务端口号,因为注册中心有服务节点列表更新是要实时推送到Consumer中的 
        -->
    <dubbo:protocol name="dubbo" port="20880" />
    <!-- 到这里,这个Consumer节点就已经能连上注册服务器,并使用指定的协议进行通信了 -->
    <!-- 接口指定Consumer端的那个服务接口,之后它就会通过这个接口的应用名和全限定名去注册中心
        查找实际的服务Provider地址列表,再通过指定的dubbo协议进行通信,实现RPC,而在Consumer
        本机端对Spring的IoC容器指定id,方便之后对这个远程JavaBean的引用调用 -->
    <dubbo:reference id="demoRemote" interface="com.weidian.dubbo.IMyDemo" protocol="dubbo"/>
</beans>
  • 另外,也能绕过Registry直连Provider,如下:
<dubbo:reference interface="com.weidian.dubbo.IMyDemo" version="1.0" id="myDemo" url="dubbo://127.0.0.1:20880/"></dubbo:reference>
  • 远程过程调用测试(前提是先把Provider的服务先运行起来再来运行这个Consumer(在两个端的测试代码尾部都添加了sleep代码的原因):
@org.junit.Test
public void testGetRemoteService() throws InterruptedException {
        ApplicationContext consumerContext = new ClassPathXmlApplicationContext("consumer.xml");
        IMyDemo demoRemote = consumerContext.getBean(IMyDemo.class);
        System.out.println(demoRemote.sayHello("world"));
        Thread.sleep(30000);
    }
  • 运行结果:
    Provider:
    image
    启动Provider输出了两遍,Consumer调用时本地实现又输出了一遍,共三遍。
    Consumer:
    这里写图片描述
    启动Consumer,远程返回输出了一遍。

Dubbo简单监控中心

简单介绍,其实用处不大,我觉得管理后台的功能已经把这个监控中心的功能覆盖了,仅仅只是拿来测试使用一下。

  • 主界面:
    这里写图片描述
  • 服务列表界面,显示所有服务以及它的Provider和Consumer情况:
    这里写图片描述

Dubbo管理后台使用

之前Tomcat中配置好了dubbo-admin的webapp,现在只要打开tomcat,并输入相应的地址即可访问dubbo-admin的界面,如我的是http://127.0.0.1:8080/dubbo-admin/
其实就是一个很常见的管理后台,可以控制每个服务、应用的状态、权重、路由控制、访问控制、负载均衡、各个应用的服务情况和消费情况等,不需要教程,直接上手使用即可,至于其中的一些可能有疑问的概念,下面的内容将一一说明。

服务路由

路由,顾名思义,就是通过配置去设定哪些Consumer节点的请求由哪些节点的Provider节点的服务来进行响应,可以在一定程度上控制负载分布。
知道这个概念,那剩下就是配置的问题了,明白怎么回事其实就很简单啦~

在dubbo-admin主界面——服务治理——路由规则,如下:
这里写图片描述
点击新增
这里写图片描述
路由名称:为你定义的这个路由规则声明一个名称,之后可以根据这个名称来找这个路由规则。
优先级:很明显,一个int数值代表这个路由规则的优先级,优先级越高这个规则越先匹配。
服务名:列表选择的,从注册中心中已有的服务列表中选择一个服务,表示这个路由规则要约束的是哪个服务。
方法名:列表选择的,选择要约束的这个服务中的哪个方法。
匹配条件:填写匹配下面的列表就表示匹配了条件才受这个路由规则约束,否则就是不匹配规则才受该规则约束。
消费者IP地址:要约束的Consumer的IP地址列表,逗号隔开。
消费者应用名:要约束的Consumer的应用名列表。
消费者集群:按照提示上写的去找,没找到相应的选项,暂时也没用到,之后再回头编辑。
过滤规则:填写匹配下面的列表就表示匹配了条件才受这个路由规则约束,否则就是不匹配规则才受该规则约束。
提供者IP地址:要约束的Provider的IP地址列表,逗号隔开。
提供者集群:按照提示上写的去找,没找到相应的选项,暂时也没用到,之后再回头编辑。
提供者协议:指定Provider的协议,不是该协议的也不约束。
提供者端口:指定Provider的端口,不是这个端口的也不约束。

测试样例展示:
这里写图片描述
这样配置的路由就能够生效,效果是:com.weidian.dubbo.IMyDemo服务的sayHello方法下,地址为192.168.31.164的Consumer的请求由(地址:192.168.31.164;协议:dubbo;端口:20880)的Provider进行响应,如果没有匹配的Provider就会默认返回所有的Provider列表给Consumer,让Consumer自己选。
点击保存,保存新增的路由规则,并在路由规则列表中启用这个规则,如下:
这里写图片描述
点击预览,在消费者地址填写192.168.31.164,点击预览,如下图所示:
这里写图片描述
运行Consumer程序,查看消费者状态,可知设定的这个路由规则对该对应地址的消费真生效了,如下图:
这里写图片描述
另外,IP地址支持结尾为匹配所有,如10.0.0.或者10.0.*等。
不匹配的配置规则和匹配的配置规则是一致的。

负载均衡

dubbo提供4种负载均衡方式:
Random:随机,按权重配置随机概率,调用量越大分布越均匀,默认是这种方式
RoundRobin:轮询,按权重设置轮询比例,如果存在比较慢的机器容易在这台机器的请求阻塞较多
LeastActive:最少活跃调用数,不支持权重,只能根据自动识别的活跃数分配,不能灵活调配
ConsistentHash:一致性hash,对相同参数的请求路由到一个服务提供者上,如果有类似灰度发布需求可采用
dubbo的负载均衡机制是在客户端调用时通过内存中的服务方信息及配置的负责均衡策略选择,如果对自己系统没有一个全面认知,建议先采用random方式。

Dubbo过滤器

有需要自己实现dubbo过滤器的,可关注如下步骤:
1. dubbo初始化过程加载ClassPath下的META-INF/dubbo/internal/META-INF/dubbo/META-INF/services/三个路径(classloader resource)下面的com.alibaba.dubbo.rpc.Filter文件。
文件内容:
每行Name=FullClassName,这些类必须是实现Filter接口,如下图:
这里写图片描述
2. 自定义Filter类:

import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.rpc.*;
//激活这个过滤器的注解,标记这个过滤器在消费者端加入过滤器链
@Activate(group = Constants.CONSUMER)
//dubbo过滤器的实现类
public class DubboTestFilter implements Filter {
    /**计时器过滤器,记录这个RPC的整个过程执行时间
     * @param invoker
     * @param invocation
     * @return
     * @throws RpcException
     */
    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        long start = System.currentTimeMillis();
        //这个是RPC的实现体,Result就是RPC的执行结果,和Servlet的过滤器有些类似
        Result result = invoker.invoke(invocation);
        System.out.println("time = " + (System.currentTimeMillis() - start) + "ms");
        System.out.println(result.getValue());
        return result;
    }
}
  1. consumer.xml配置文件中配置这个过滤器,如下图:
    这里写图片描述
  2. 先来看看配置完成之后的执行效果:
    这里写图片描述

    对比上面的过滤器代码可知,先输出了RPC过程的运行时间,之后在过滤器中输出了一遍执行结果hello world,之后单元测试本身再把执行结果输出一遍,因此hello world输出了两遍。

  3. Dubbo过于这个过滤器的加载过程:

    (1) 先加载那三个路径下的com.alibaba.dubbo.rpc.Filter文件里面的键值对,key为过滤器的名称,value为过滤器的类全限定名(这个类必须实现Dubbo中的Filter接口);
    (2) 这样就能找到这个类的class文件了,检查@Activate注解加载这个过滤器设定的一些全局基本属性;
    (3) Spring在加载consumer.xml文件的时候,通过

<dubbo:consumer filter="dubboTestFilter" id="dubboTestFilter" retries="0"/>

指定消费者端要加载的过滤器,通过filter属性指定过滤器名称(就是配置文件中的过滤器key),这样刚才加载的过滤器类就加入消费者代码逻辑中的过滤器链了。
6. 关于@Activate注解: —— 自动激活

group:(provider|consumer)匹配了对应的角色才被加载
value:标明过滤条件,不写则所有条件下都会被加载,写了则只有dubbo URL中包含该参数名且参数值不为空才被加载,这个参数会以dubbo协议的一个参数K-V对传到Provider。


还欠缺安全保护和集群性能调优方面的讲解,毕竟才刚入门,待我在公司的项目中使用一段时间有了真正的一些实战感悟再来好好总结~

本文为博主原创,允许转载,但请声明原文地址:http://www.coselding.cn/article/2017-01-02/dubbo-study-record.html

Dubbo实战(一)快速入门

Dubbo是什么?Dubbo[]是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。其核心部分包含: 远程通讯: 提供对多种基于长连接的NIO框架抽象封装,...
  • FX_SKY
  • FX_SKY
  • 2016年03月30日 00:44
  • 29771

Dubbo入门基础与实例讲解

Dubbo是阿里巴巴SOA服务化治理方案的核心框架,每天为2,000+个服务提供3,000,000,000+次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。Dubbo是一个分布式服务框架,致力于...

Dubbo新手入门实例HelloWorld(zookeeper)

最近刚接触dubbo,新手入门遇到好多麻烦,网上搜来的入门demo也是各种问题,百般周折自己终于倒腾出来了,与大家共享~ 1.创建服务方项目dubbo-server,在pom.xml中构建项目依赖...

Dubbo+Zookeeper入门实例

现在的公司接口调用是通过dubbo来实现的,所以这两天就了解了一下dubbo是如何进行通信的,写了一个最简单的例子。自上得来终觉浅,绝知此事要躬行。      一.dubbo介绍           ...

dubbo简单入门(helloworld例子)

Dubbo现在支持的有三种方式: 1.multicast; 2.zookeeper; 3.redis 下面的Demo使用的是multicast方式。提供者项目结构: 消...

Dubbo入门---搭建一个最简单的Demo框架

Dubbo背景和简介Dubbo开始于电商系统,因此在这里先从电商系统的演变讲起。 单一应用框架(ORM) 当网站流量很小时,只需一个应用,将所有功能如下单支付等都部署在一起,以减少部署节点和成本。 ...

Dubbo入门---搭建一个最简单的Demo框架

转自:http://blog.csdn.net/noaman_wgs/article/details/70214612 Dubbo背景和简介Dubbo开始于电商系统,因此在这里先从电商系...

Dubbo分布式服务框架入门(附工程)

本文介绍了dubbo的一些概念,并对zookeeper、dubbo-admin、提供者、消费者的搭建进行了详细的讲解,且附有工程源码...

Dubbo之入门例子HelloWorld

1、项目的目录结构  2、关于Zookeeper的安装       关于Zookeeper的安装,详情见前面的博客  http://blog.csdn.net/zbw18297786698/arti...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Dubbo入门学习笔记
举报原因:
原因补充:

(最多只允许输入30个字)