Dubbo

一款分布式服务框架
高性能和透明化的RPC远程服务调用方案
SOA服务治理方案
每天为2千多个服务提供大于30亿次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点以及别的公司的业务中。

Dubbo架构

dubbo python 官方_dubbo


ps:图片来源于网络

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

调用流程
0.服务容器负责启动,加载,运行服务提供者。
1.服务提供者在启动时,向注册中心注册自己提供的服务。
2.服务消费者在启动时,向注册中心订阅自己所需的服务。
3.注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
4.服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
5.服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心

Dubbo注册中心
对于服务提供方,它需要发布服务,而且由于应用系统的复杂性,服务的数量、类型也不断膨胀;
对于服务消费方,它最关心如何获取到它所需要的服务,而面对复杂的应用系统,需要管理大量的服务调用。
而且,对于服务提供方和服务消费方来说,他们还有可能兼具这两种角色,即既需要提供服务,有需要消费服务。

通过将服务统一管理起来,可以有效地优化内部应用对服务发布/使用的流程和管理。服务注册中心可以通过特定协议来完成服务对外的统一。

Dubbo提供的注册中心有如下几种类型可供选择:

Multicast注册中心
Zookeeper注册中心
Redis注册中心
Simple注册中心
Dubbo优缺点

优点

透明化的远程方法调用

  • 像调用本地方法一样调用远程方法;只需简单配置,没有任何API侵入。
    软负载均衡及容错机制
    可在内网替代nginx lvs等硬件负载均衡器。
    服务注册中心自动注册 & 配置管理
    -不需要写死服务提供者地址,注册中心基于接口名自动查询提供者ip。
    使用类似zookeeper等分布式协调服务作为服务注册中心,可以将绝大部分项目配置移入zookeeper集群。
    服务接口监控与治理
    -Dubbo-admin与Dubbo-monitor提供了完善的服务接口管理与监控功能,针对不同应用的不同接口,可以进行 多版本,多协议,多注册中心管理。

缺点

只支持JAVA语言
Dubbo入门Demo
了解了Dubbo以后,自然要搭建一个简单的Demo实现。本文采用Dubbo与Zookeeper、Spring框架的整合。

主要是以下几个步骤:

  1. 安装Zookeeper,启动;
  2. 创建MAVEN项目,构建Dubbo+Zookeeper+Spring实现的简单Demo;
  3. 安装Dubbo-admin,实现监控。

1、 Zookeeper介绍与安装
本Demo中的Dubbo注册中心采用的是Zookeeper。为什么采用Zookeeper呢?

Zookeeper是一个分布式的服务框架,是树型的目录服务的数据存储,能做到集群管理数据 ,这里能很好的作为Dubbo服务的注册中心。

Dubbo能与Zookeeper做到集群部署,当提供者出现断电等异常停机时,Zookeeper注册中心能自动删除提供者信息,当提供者重启时,能自动恢复注册数据,以及订阅请求

具体的安装方法在此不一一叙述,可参考博文:zookeeper安装教程 安装完成后,进入到bin目录,并且启动zkServer.cmd,这个脚本中会启动一个java进程:

(注:需要先启动zookeeper后,后续dubbo demo代码运行才能使用zookeeper注册中心的功能)

dubbo python 官方_xml_02

2 、创建MAVEN项目

项目结构:
主要分三大模块:
dubbo-api : 存放定义的服务接口;
dubbo-consumer : 服务消费者;
dubbo-provider : 服务提供者(也是服务接口实现者)

dubbo python 官方_spring_03

公共依赖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>dubbo</groupId>
  <artifactId>dubbo</artifactId>
  <version>1.0.0</version>
  <packaging>pom</packaging>
  <name>this is fist dubbo demo</name>
  <modules>
    <module>dubbo-consumer</module>
    <module>dubbo-provider</module>
    <module>dubbo-api</module>
  </modules>
  
  <properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <!-- spring版本号 -->
    <spring.version>4.2.5.RELEASE</spring.version>
    <!-- mybatis版本号 -->
    <mybatis.version>3.2.8</mybatis.version>
    <!-- mysql驱动版本号 -->
    <mysql-driver.version>5.1.29</mysql-driver.version>
    <!-- log4j日志包版本号 -->
    <slf4j.version>1.7.18</slf4j.version>
    <log4j.version>1.2.17</log4j.version>
  </properties>
  
  <dependencies>
      <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <!-- 添加jstl依赖 -->
    <dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>
    <dependency>
      <groupId>javax</groupId>
      <artifactId>javaee-api</artifactId>
      <version>7.0</version>
    </dependency>
    <!-- 添加junit4依赖 -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <!-- 指定范围,在测试时才会加载 -->
      <scope>test</scope>
    </dependency>
    <!-- 添加spring核心依赖 -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-oxm</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</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-context</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context-support</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <!-- 添加mybatis依赖 -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>${mybatis.version}</version>
    </dependency>
    <!-- 添加mybatis/spring整合包依赖 -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.2.2</version>
    </dependency>
    <!-- 添加mysql驱动依赖 -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>${mysql-driver.version}</version>
    </dependency>
    <!-- 添加数据库连接池依赖 -->
    <dependency>
      <groupId>commons-dbcp</groupId>
      <artifactId>commons-dbcp</artifactId>
      <version>1.2.2</version>
    </dependency>
    <!-- 添加fastjson -->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.22</version>
    </dependency>
    <!-- 添加日志相关jar包 -->
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>${log4j.version}</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>${slf4j.version}</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>${slf4j.version}</version>
    </dependency>
    <!-- log end -->
    <!-- 映入JSON -->
    <dependency>
      <groupId>org.codehaus.jackson</groupId>
      <artifactId>jackson-mapper-asl</artifactId>
      <version>1.9.13</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->;
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.8.0</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->;
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.8.0</version>
    </dependency>
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.1</version>
    </dependency>
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.4</version>
    </dependency>
    <dependency>
      <groupId>commons-codec</groupId>
      <artifactId>commons-codec</artifactId>
      <version>1.9</version>
    </dependency>
    <dependency>
      <groupId>org.quartz-scheduler</groupId>
      <artifactId>quartz</artifactId>
      <version>2.2.1</version>
    </dependency>
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-core</artifactId>
      <version>1.3.2</version>
    </dependency>
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-web</artifactId>
      <version>1.3.2</version>
    </dependency>
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-spring</artifactId>
      <version>1.3.2</version>
    </dependency>
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-ehcache</artifactId>
      <version>1.3.2</version>
    </dependency>
    <dependency>
      <groupId>org.apache.zookeeper</groupId>
      <artifactId>zookeeper</artifactId>
      <version>3.4.9</version>
    </dependency>
    <!-- dubbo -->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>dubbo</artifactId>
      <version>2.5.3</version>
      <exclusions>
        <exclusion>
          <groupId>org.springframework</groupId>
          <artifactId>spring</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>com.101tec</groupId>
      <artifactId>zkclient</artifactId>
      <version>0.10</version>
    </dependency>
  </dependencies>
  
  <build>
    <finalName>dubbo</finalName>
  </build>
</project>

下面,我为大家具体讲解三个子项目。

1、服务接口dubbo-api

pom.xml

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>dubbo</groupId>
    <artifactId>dubbo</artifactId>
    <version>1.0.0</version>
  </parent>
  <groupId>dubbo</groupId>
  <artifactId>dubbo-api</artifactId>
  <version>1.0.0</version>
  <name>dubbo-api</name>
  <url>http://maven.apache.org</url>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

DemoService.java

package com.dubbo.api.demo;
/**
 * 
* @ClassName: DemoService
* @Description: 定义服务接口
* @author chenqi
* @date 2018年10月4日
*
 */
public interface DemoService {
    
    String helloDubbo(String str);
}

2、 服务提供者(也是服务接口实现者)dubbo-provider

pom依赖

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>dubbo</groupId>
    <artifactId>dubbo</artifactId>
    <version>1.0.0</version>
  </parent>
  
  <artifactId>dubbo-provider</artifactId>
  <name>dubbo-provider</name>
  <description>服务提供者</description>
  <url>http://maven.apache.org</url>
  
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  
  <dependencies>
      
    <!-- 引入api模块 -->
    <dependency>
      <groupId>dubbo</groupId>
      <artifactId>dubbo-api</artifactId>
      <version>${project.version}</version>
    </dependency>
  
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  
</project>

配置文件provider.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-admin 或 dubbo-monitor 会显示这个名字,方便辨识-->
    <dubbo:application name="demotest-provider" owner="programmer" organization="dubbox"/>
    <!--使用 zookeeper 注册中心暴露服务,注意要先开启 zookeeper-->
    <dubbo:registry address="zookeeper://localhost:2181"/>
    <!-- 用dubbo协议在20880端口暴露服务 -->
    <dubbo:protocol name="dubbo" port="20880" />
    <!--使用 dubbo 协议实现定义好的 api.PermissionService 接口-->
    <dubbo:service interface="com.dubbo.api.demo.DemoService" ref="demoService" protocol="dubbo" />
    <!--具体实现该接口的 bean-->
    <bean id="demoService" class="com.dubbo.provider.demo.DemoServiceImpl"/>
</beans>

服务接口实现类(用于提供服务)
实现服务接口,此实现对消费者隐藏

package com.dubbo.provider.demo;
import com.dubbo.api.demo.DemoService;
/**
 * 
* @ClassName: DemoServiceImpl
* @Description: 服务接口实现类(用于提供服务)
* @author chenqi
* @date 2018年10月4日
*
 */
public class DemoServiceImpl implements DemoService {
    
    /**
     * 实现  DemoService  中的 helloDubbo 接口
     */
    public String helloDubbo(String str) {
        return "hello " + str;
    }
}

服务启动类

package com.dubbo.provider.demo;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.io.IOException;
/**
 * 
* @ClassName: Provider
* @Description: 服务启动类
* @author chenqi
* @date 2018年10月4日
*
 */
public class ProviderApplication {
    
    public static void main(String[] args) throws IOException {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("provider.xml");
        System.out.println(context.getDisplayName() + ": here");
        context.start();
        System.out.println("服务已经启动...");
        System.in.read();
    }
}

3、服务消费者dubbo-consumer

pom依赖

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>dubbo</groupId>
    <artifactId>dubbo</artifactId>
    <version>1.0.0</version>
  </parent>
  
  <artifactId>dubbo-consumer</artifactId>
  <name>dubbo-consumer</name>
  <description>服务消费者</description>
  <url>http://maven.apache.org</url>
  
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  
  <dependencies>
  
      <!-- 引入api模块 -->
    <dependency>
      <groupId>dubbo</groupId>
      <artifactId>dubbo-api</artifactId>
      <version>${project.version}</version>
    </dependency>
    
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  
</project>

配置文件consumer.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="demotest-consumer" owner="programmer" organization="dubbox"/>
    <!--向 zookeeper 订阅 provider 的地址,由 zookeeper 定时推送-->
    <dubbo:registry address="zookeeper://localhost:2181"/>
    <!--使用 dubbo 协议调用定义好的 api.PermissionService 接口-->
    <dubbo:reference id="permissionService" interface="com.dubbo.api.demo.DemoService"/>
</beans>

测试服务消费者获取服务接口

package com.dubbo.consumer.demo;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.dubbo.api.demo.DemoService;
/**
 * 
* @ClassName: ConsumerTest
* @Description: 测试服务消费者获取服务接口
* @author chenqi
* @date 2018年10月7日
*
 */
public class ConsumerTest {
    public static void main(String[] args) {
        //测试常规服务
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("consumer.xml");
        context.start();
        System.out.println("consumer start");
        DemoService demoService = context.getBean(DemoService.class);
        System.out.println("consumer");
        System.out.println(demoService.helloDubbo("dubbo"));
    }
}

OK,下面我们依次启动服务提供者和服务消费者,注意确保provider已被运行后再启动consumer

启动服务提供者:

dubbo python 官方_spring_04


启动报了点错误,暂时忽略。运行消费者进行测试:

dubbo python 官方_zookeeper_05

可以看到,消费者成功调用提供者所提供的远程服务。当然,这只是一个模拟的项目,实际中有多提供者多消费者情况,比这要复杂的多,当然只有这样才能体现dubbo的特性。

Dubbo管理控制台介绍

管理控制台功能

路由规则,动态配置,服务降级

访问控制,权重调整

负载均衡

dubbo python 官方_xml_06

网上自行下载dubbo-admin,下载后是一个war包,直接放到tomcat安装目录的webapps目录下,然后启动tomcat即可

dubbo python 官方_dubbo python 官方_07

dubbo python 官方_spring_08

浏览器访问:http://localhost:28080/dubbo-admin/ 输入用户名密码 root

dubbo python 官方_dubbo_09

查看服务提供者

dubbo python 官方_spring_10

查看服务消费者

dubbo python 官方_spring_11

通过上面的内容,相信大家应该对dubbo有了初步的认知和了解。

ps:如果该文章有帮助到您,就点个赞吧!您的支持与肯定是我持续更新最大的动力。