Dubbo

Posted 凤凰山小旋风

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dubbo相关的知识,希望对你有一定的参考价值。

一:什么是Dubbo

  Dubbo是一个RPC框架;

  执行流程为:

  

  采用的协议:

    1.Dubbo

      1.1 Dubbo官方推荐的协议.

      1.2 本质:使用NIO和线程池进行处理.

      1.3 缺点:大文件传输时可能出现文件传输失败问题.

    2.RMI

      2.1 JDK提供的协议,远程方法调用协议.

      2.2 缺点:偶尔连接失败.

      2.3 优点:JDK原生,不需要进行额外配置(导入jar)

    3.Hession

      3.1 优点:基于http协议,http请求支持.

      3.2 缺点:需要额外导入jar,并在短连接时性能低

  特性:

    面向接口代理的高性能RPC调用

      提供高性能的给予代理的远程调用能力,服务以接口为粒度,为开发者屏蔽远程调用底层细节

    服务自动注册与发现

      支持多服务中心服务,服务上下线实时感知;

    运行期流量调度

      内置条件,脚本等路由策略,通过配置不同的路由规则,轻松实现灰度发布,同机房优先等功能

    智能负载均衡

      内置各种负载均衡策略,智能感知下游节点的健康状态,显著减少调用延迟,提高系统吞吐量

    高度可扩展能力

      遵循微内核+插件设计原则,所有核心能力入Protocol、Transport、Serialization呗设计为拓展点,平等对待内置实现和第三方实现;

    可视化的服务治理与运维

      提供丰富服务治理,运维工具;随时查询服务元数据,服务健康状态及调用统计,实时下发路由策略,调整配置参数

  Dubbo的架构设计:

    

  

    服务提供者(Provider):
      暴露服务的服务提供方,服务提供者在启动时,向注册中心注册自己提供的服务


    服务消费者(Consume):
      调用远程服务的服务消费方,服务消费者启动时,向注册中心订阅自己所需的服务,服务消费者,从提供者地址列表中,基于负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。 

 

    注册中心(Registry):
      注册中心返回服务提供者地址表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者


    监控中心(Monitor):
      服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心

 

  

  调用关系说明

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

  

  运行原理:

    0 启动容器,相当于在启动DubboProvider

    1 启动后会去注册中心进行注册.注册所有可以提供的服务列表

    2 Consumer启动后会去Registry中获取服务列表和Provider的地址.进行订阅.

    3 Provider有修改后,注册中心会把消息推送给Consummer

      3.1 使用了观察者设计模式(又叫发布/订阅设计模式)

    4 根据获取到的Provider地址,真实调用Provider中功能.

      4.1 Consumer方使用了代理设计模式.创建一个Provider方类的一个代理对象.通过代理对象获取Provider中真实功能,起到保护Provider真实功能的作用.

    5 ConsumerProvider每隔1分钟向Monitor发送统计信息,统计信息包含,访问次数,频率等.

二:搭建Dubbo环境:

  首先要配置zookeeper(包括监控中心和控制台)

  参见搭建zookeeper环境

  

    

  Code(HelloWord-----javase----maven)

    说明:

      1.这里的三个模块都使用了jar包的形式(具体看需求)

      2.包名取得有问题(pro和con中的service都是service,所以最好是有所区分)

    (1)生产者

       接口实现

package com.xpl.service;

import com.xpl.model.User;
import org.springframework.stereotype.Service;
//spring的service注解
@Service
public class GetUserImp implements GetUser {

    public String getUserById(int id) {
        return "徐沛蕾";
    }
}

      main主方法

package com.xpl.com.xpl.main;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        ClassPathXmlApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
        cxt.start();
        System.in.read();
    }
}

      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:dubbo="http://code.alibabatech.com/schema/dubbo"
       xmlns:dubbop="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">
    <!--1.指定当前服务/应用的名字(最好是写项目名称)-->
    <dubbo:application name="dubboprovider"/>
    <!--2.指定注册中心的位置,zookeeper默认端口号为2181-->
    <!--方式一-->
    <dubbop:registry address="zookeeper://127.0.0.1:2181"/>
    <!--方式二-->
    <!--<dubbo:registry protocol="zookeeper" address="127.0.0:2181"/>-->
    <!--3.指定通信规则(通信协议和通信端口)-->
    <!--协议有多种,端口号为自己指定的不冲突即可-->
    <dubbo:protocol name="dubbo" port="20880"/>
    <!--4.暴露接口-->
    <!--将要暴露的接口的实现类注入到spring容器中-->
    <dubbo:service interface="com.xpl.service.GetUser" ref="getUserImp"/>
    <bean class="com.xpl.service.GetUserImp" id="getUserImp"/>
  
  <!--配置监控中心-->
  <!--方式一:-->
  <!--<dubbo:monitor protocol="registry"/>-->
  <!--方式二:-->
  <dubbo:monitor address="127.0.0.1:7070"/>
</beans>

    (2)消费者

       接口实现

package com.xpl.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
//spring的service注解
@Service
public class OrderServiceImp implements OrderService {

    @Autowired
    GetUser getUser;
    public String getNameByID(int id) {
        String name = getUser.getUserById(id);
        return name;
    }
}

      main主方法

package com.xpl.main;

import com.xpl.service.OrderService;
import com.xpl.service.OrderServiceImp;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        ClassPathXmlApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
//        OrderService bean = (OrderService) cxt.getBean("orderServiceImp");
        OrderService bean = cxt.getBean(OrderService.class);
        String nameByID = bean.getNameByID(1);
        System.out.println(nameByID);
        System.in.read();
    }
}

      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:dubbo="http://code.alibabatech.com/schema/dubbo"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:bean="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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <!--将加了注解的组件扫描进来-->
    <context:component-scan base-package="com.xpl.service"/>
    <!--1.指定当前服务/应用的名字(最好是写项目名称)-->
    <dubbo:application name="dubboconsumer"/>
    <!--订阅的服务地址-->
    <!--方式一-->
    <!--<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"/>-->
    <!--方式二:-->
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
    <!--消费的服务就是provider中暴露的接口-->
    <dubbo:reference interface="com.xpl.service.GetUser" id="getUserImp"/>
  <!--配置监控中心-->
  <!--方式一:-->
  <!--<dubbo:monitor protocol="registry"/>-->
  <!--方式二:-->
<dubbo:monitor address="127.0.0.1:7070"/>
</beans>

    (3)common

       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">
    <parent>
        <artifactId>DubboTest</artifactId>
        <groupId>com.xpl</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>dubboService</artifactId>

    <dependencies>

        <!--<artifactId>dubbo</artifactId>-->
        <!--<artifactId>zookeeper</artifactId>-->
        <!--<artifactId>zkclient</artifactId>-->
        <!--<artifactId>curator-recipes</artifactId>-->
        <!--这三个是生产者和消费者都需要引入的依赖生产和消费有需要引入service所以在service中引入-->

        <!--依赖一如方式一-->

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.11</version>
        </dependency>
        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.10</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>4.0.1</version>
        </dependency>


        <!--依赖一如方式二-->
        <!--2.6.2版本以后引入这两个就可以了-->
        <!--<dependency>-->
            <!--<groupId>com.alibaba</groupId>-->
            <!--<artifactId>dubbo</artifactId>-->
            <!--<version>2.6.2</version>-->
        <!--</dependency>-->
        <!--<dependency>-->
            <!--<groupId>org.apache.curator</groupId>-->
            <!--<artifactId>curator-framework</artifactId>-->
            <!--<version>2.12.0</version>-->
        <!--</dependency>-->
    </dependencies>
</project>

      service

package com.xpl.service;

import com.xpl.model.User;

/**
 * 提供一个获取User的接口
 */
public interface GetUser {
    public String getUserById(int id);
}
package com.xpl.service;

import com.xpl.model.User;

/**
 * 提供一个获取通过id获取name的接口
 */
public interface OrderService {
    public String getNameByID(int id);
}

      model

package com.xpl.model;

import java.io.Serializable;
//implements Serializable 序列化
public class User implements Serializable {

    private int id;
    private String name;
    private String address;


    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name=\'" + name + \'\\\'\' +
                ", address=\'" + address + \'\\\'\' +
                \'}\';
    }
}

   

  总结梳理:

    1.首先是在一个Maven项目中创建多模块(生产者、消费者、公共模块)

    2.公共模块提供生产者和消费者所需要的接口和公共使用的实体类,同时在pom模块中引入生产者和消费者所共同依赖的jar包

    3.生产者将其注册到zookeeper中并暴露服务

    4.生产者订阅zookeeper中的服务

    5.注册服务主要分为:

      注册的服务名称

      所在注册中心的位置(注册中心的地址和端口号)

      通信方式和端口

      将实现类注入到spring容器中

      暴露接口(上边注入到spring容器中的Bean对应的接口) 

    6.订阅服务主要分为

      指定当前服务的名称

      订阅服务在注册中心的地址(注册中心的地址和端口号)

      消费的服务(就是自己需要代用的接口,也是提供者暴露的那个接口)

三、注解版

  

 

 

以上是关于Dubbo的主要内容,如果未能解决你的问题,请参考以下文章

Dubbo多个远程代码执行漏洞

Dubbo 存在远程代码执行漏洞

Dubbo 被曝出“高危”远程代码执行漏洞

响应式编程的实践

构建dubbo分布式平台-maven代码结构

构建dubbo分布式平台-maven代码结构