Dubbo框架原理简要介绍


公司为搭建分布式系统学习使用dubbo框架


参考文档: 阿里巴巴Duboo官网

一 、知识点

  1. SOA(Service Oriented Architecture):面向服务的架构。
    • 由 服务治理、服务注册和发现、RPC、监控中心、调度中心以及服务路由、负载均衡等功能模块组成的资源调度和治理中心。

二、 RPC的演进

RPC框架演变

  • 框架演进:ORM–>MVC–>RPC–>SOA
  • 架构演进:单一应用架构–>垂直应用架构—>分布式服务架构–>流动计算架构
  • 单一应用架构
    • 网站流量小的时候,将所有功能集中到单一应用以减少成本。性能瓶颈在于 ORM框架。
  • 垂直应用架构
    • 网站流量增大,横向扩展带来的效益越来越低,将应用拆分为互不相干的几个应用以提升效率。性能瓶颈在于MVC框架。
  • 分布式服务架构
    • 当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。 此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键。
  • 弹性计算架构
    • 当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。 此时,用于提高机器利用率的资源调度和治理中心(SOA)是关键。

三、 架构简介

架构图
架构图

节点角色

  1. Provider:服务提供方,在启动时向注册中心注册服务;
  2. Consumer:服务消费方,向注册中心请求服务提供方列表,在本地做负载均衡调用服务;
  3. Register:注册中心,提供服务注册与发现(一般由Zookeeper担当),通过长连接与Provider和Consumer保持连接,负责监控Provider的上下线并及时通知Consumer;
  4. Monitor:监控中心,负责统计服务的性能数据;
  5. Container:服务运行容器。

调用关系

  1. “0.start”:服务运行容器启动、加载、运行服务提供方,一般由Spring容器启动Jar运行;
  2. “1.register”: 服务提供方在启动时,向注册中心注册自己的IP、服务接口等信息;
  3. “2.subscribe”: 服务消费方向注册中心订阅自己感兴趣的服务提供方;
  4. “3.notify”: 注册中心在服务提供方发生变更时将基于长连接向消费方推送消息;
  5. “4.invoke”: 服务消费方在本地对服务列表做软负载均衡算法,选择最优的服务提供方进行RPC调用;
  6. “5.count”: 消费方和提供方向监控中心 定时异步推送服务调用次数和时间,消费方的包括网络耗时,提供方不包括网络耗时。

性能说明

  1. 连通性:注册中心通过长连接与Provider和Consumer进行通信,Provider和Consumer直接通过PRC直接调用,其只在启动时向注册中心注册和订阅,注册中心不转发请求,当注册中心宕机,Consumer依然可以通过本地缓存的Provider的地址列表进行调用;Provider和Consumer与监控中心定时地通过异步通信方式进行服务调用信息上传;
  2. 健壮性: 服务提供者无状态,任意一台宕掉后,不影响使用,服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复。
  3. 伸缩性:注册中心为对等集群,可动态增加机器部署实例,所有客户端将自动发现新的注册中心,服务提供者无状态,可动态增加机器部署实例,注册中心将推送新的服务提供者信息给消费者。
  4. 扩展性:当服务集群规模进一步扩大,带动IT治理结构进一步升级,需要实现动态部署,进行弹性计算,现有分布式服务架构不会带来阻力。

四、 使用简介

Dubbo是基于Spring的框架,其配置采用XML和注解的方式,使用Spring的BeanFactory加载Bean,运行在Spring容器中。

服务提供方

  1. 定义服务接口

DemoService.java

package com.alibaba.dubbo.demo;
public interface DemoService {
    String sayHello(String name);
}

打包成Jar包在服务提供方和消费者处使用,该工程里除了接口定义以外,还有各种实体类和通用工具类

  • 实现服务接口

  • DemoServiceImpl.java

    package com.alibaba.dubbo.demo.provider;
    import com.alibaba.dubbo.demo.DemoService;
    public class DemoServiceImpl implements DemoService {
       public String sayHello(String name) {
           return "Hello " + name;
       }
    }

    公司里将接口定义和服务实现分为了两个工程,不便于开发人员使用,建议采用Maven的多项目结构,将接口定义和服务实现定义在同一个父项目下。

  • 暴露服务

    • XML方式
    <beans>
    <!--省略schema--!>
    <!-- 提供方应用信息,用于计算依赖关系 -->
    <dubbo:application name="hello-world-app"  />
    <!-- 使用multicast广播注册中心暴露服务地址 -->
    <dubbo:registry address="multicast://224.5.6.7:1234" />
    <!-- 用dubbo协议在20880端口暴露服务 -->
    <dubbo:protocol name="dubbo" port="20880" />
    <!-- 声明需要暴露的服务接口 -->
    <dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService" />
    <!-- 和本地bean一样实现服务 -->
    <bean id="demoService" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl" />
    </beans>
    • 注解方式(推荐)

    FooServiceImpl.java

    import com.alibaba.dubbo.config.annotation.Service;
    @Service(version="1.0.0")
    public class FooServiceImpl implements FooService {
    }

    provider.xml

    <!-- 公共信息,也可以用dubbo.properties配置 -->
    <dubbo:application name="annotation-provider" />
    <dubbo:registry address="127.0.0.1:4548" />
    <!-- 扫描注解包路径,多个包用逗号分隔,不填pacakge表示扫描当前ApplicationContext中所有的类-->
    <dubbo:annotation package="com.foo.bar.service" />
  • 启动

  • public static void main(String[] args) throws Exception {
        //加载xml配置启动Spring的BeanFactory
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"http://10.20.160.198/wiki/display/dubbo/provider.xml"});
        context.start();
        System.in.read(); // 按任意键退出
    }

    服务启动时,将向注册中心注册本服务的IP、接口等信息

    服务消费方

    1. 引用远程服务接口

    • xml方式

    consumer.xml

    <!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
    <dubbo:application name="consumer-of-helloworld-app"  />
    
    <!-- 使用multicast广播注册中心暴露发现服务地址 -->
    <dubbo:registry address="multicast://224.5.6.7:1234" />
    
    <!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
    <dubbo:reference id="demoService" interface="com.alibaba.dubbo.demo.DemoService" />
  • 注解方式(推荐)

  •     @Component
        public class BarAction {
            @Reference(version="1.0.0")
            private FooService fooService;
        }
      
      
    • 调用服务

       public static void main(String[] args) throws Exception {
           ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"http://10.20.160.198/wiki/display/dubbo/consumer.xml"});
           context.start();
           DemoService demoService = (DemoService)context.getBean("demoService"); // 获取远程服务代理
      
           String hello = demoService.sayHello("world"); // 执行远程方法
           System.out.println( hello ); // 显示调用结果
      }

    猜你喜欢

    转载自blog.csdn.net/qq_38025219/article/details/85336296