相关推荐recommended
分布式RPC框架Dubbo详解
作者:mmseoamin日期:2023-12-25

目录

 

1.架构演进

1.1 单体架构

1.2  垂直架构

1.3 分布式架构

1.4 SOA架构

1.5 微服务架构

2.RPC框架

2.1 RPC基本概念介绍

2.1.1 RPC协议

2.1.2 RPC框架

2.1.3 RPC与HTTP、TCP/ UDP、Socket的区别

2.1.4 RPC的运行流程

 2.1.5 为什么需要RPC

2.2 Dubbo 

2.2.1 Dubbo 概述

2.2.2 Dubbo实战


 

1.架构演进

架构演进如下图:

分布式RPC框架Dubbo详解,fd63343509ed4c71a56c6afa589ed8b6.png,第1张

1.1 单体架构

这里假设A,B,C,D为四个模块

当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。 此时,用于简化增删改查工作量的 数据访问框架(ORM) 是关键。

分布式RPC框架Dubbo详解,a901592742324c36b91310e4c1d03326.png,第2张

优点:

简单:开发部署都很方便,小型项目首选
缺点:

项目启动慢。可靠性差·可伸缩性差

扩展性和可维护性差·性能低

1.2  垂直架构

当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。此时,用于加速前端页面开发的 Web框架(MVC) 是关键。

分布式RPC框架Dubbo详解,83af1410e8c74b6bb6643f37bc6502a9.png,第3张

垂直架构是指将单体架构中的多个模块拆分为多个独立的项目。形成多个独立的单体架构。垂直架构存在的问题:·重复功能太多。

1.3 分布式架构

分布式架构是指在垂直架构的基础上,将公共业务模块抽取出来,作为独立的服务,供其他调用者消费,以实现服务的共亨和重用。
RPC: Remote Procedure Call远程过程调用。有非常多的协议和技术来都实现了RPC的过程。比如:HTTP REST风格,JavaRMl规范、WebService SOAP协议. Hession等等。

分布式架构存在的问题:服务提供方一旦产生变更,所有消费方都需要变更。

 

1.4 SOA架构

分布式RPC框架Dubbo详解,3c468514f7584a24956837bf1ab76f6a.png,第4张

SOA: (Service-OrientedArchitecture,面向服务的架构)是一个组件模型,它将应用程序的不同功能单元(称为服务)进行拆分,并通过这些服务之间定义良好的接口和契约联系起来。

 ESB: (Enterparise Servce Bus)企业服务总线,服务中介。主要是提供了一个服务于服务之间的交互。ESB包含的功能如:负载均衡,流量控制,加密处理,服务的监控,异常处理,监控告急等。

1.5 微服务架构

分布式RPC框架Dubbo详解,f5374f97582245a2ba459b0184cd96f0.png,第5张

 

微服务架构是在SOA上做的升华,微服务架构强调的一个重点是“业务需要彻底的组件化和服务化”,原有的单个业务系统会拆分为多个可以独立开发、设计、运行的小应用。这些小应用之间通过服务完成交互和集成。微服务架构=80%的SOA服务架构思想+100%的组件化架构思想+80%的领域建模思想。

特点:

1.服务实现组件化:开发者可以自由选择开发技术。也不需要协调其他团队。

2.服务之间交互一般使用REST API。

3.去中心化,每个微服务有自己私有的数据库持久化业务数据。

4.自动化部署,把应用拆分成为一个一个独立的单个服务,方便自动化部署、测试、运维。

 

 

 

 

2.RPC框架

2.1 RPC基本概念介绍

2.1.1 RPC协议

远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。

OSI参考模型如下图:

分布式RPC框架Dubbo详解,4db3ea7cc7304c1f8e5cc91b3c949946.png,第6张

RPC采用客户机/服务器模式。请求程序就是一个客户机,而服务提供程序就是一个服务器。首先,客户机调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在服务器端,进程保持睡眠状态直到调用信息到达为止。当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用进程接收答复信息,获得进程结果,然后调用执行继续进行。

 

2.1.2 RPC框架

在单机时代一台电脑运行多个进程,进程之间无法通讯,显然这会浪费很多资源,因此后来出现IPC(Inter-process communication:单机中运行的进程之间的相互通信),这样就能允许进程之间进行通讯,比如在一台计算机中的A进程写了一个吃饭的方法,那在以前如果在B进程中也要有一个吃饭的方法,必须要在B进程中进行创建,但有了RPC后B只需要调用A进程的程序即可完成,再到后来网络时代的出现,大家电脑都连起来,这时可不可以调用其他电脑上的进程呢,当然可以,这样RPC框架出现了。严格意义上来讲: Unix的生态系统中RPC可以在同一台电脑上不同进程进行,也可以在不同电脑上进行;而在windows里面同一台电脑上不同进程间的通讯还可以采用LPC(本地访问)。综上:RPC或LPC是上层建筑,IPC是底层基础。
RPC框架有很多:比如JAVA RMT、Thrift、Dubbo、grpc等。

 

2.1.3 RPC与HTTP、TCP/ UDP、Socket的区别


TCP/UDP:都是传输协议,主要区别是tcp协议连接需要3次握手,断开需要四次挥手,是通过流来传输的,就是确定连接后,一直发送信息,传完后断开。udp不需要进行连接,直接把信息封装成多个报文,直接发送。所以udp的速度更快写,但是不保证数据的完整性。
Http:超文本传输协议是一种应用层协议,建立在TCP协议之上
Socket:是在应用程序层面上对TCPIP协议的封装和应用。其实是一个调用接口,方便程序员使用TCPIP协议栈而已。程序员通过socket来使用tcp/ip协议。但是socket并不是一定要使用tcp/ip协议,Socket编程接口在设计的时候,就希望也能适应其他的网络协议。
RPC是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。所以RPC的实现可以通过不同的协议去实现比如可以使http、RMl等。


2.1.4 RPC的运行流程

首先,要解决通讯的问题,主要是通过在客户端和服务器之间建立TCP连接,远程过程调用的所有交换的数据都在这个连接里传输。连接可以是按需连接,调用结束后就断掉,也可以是长连接,多个远程过程调用共享同一个连接。

第二,要解决寻址的问题,也就是说,A服务器上的应用怎么告诉底层的RPC框架,如何连接到B服务器(如主机或IP地址)以及特定的端口,方法的名称名称是什么,这样才能完成调用。比如基于Web服务协议栈的RPC,就要提供一个endpoint URI,或者是从UDD(一种目录服务,通过该目录服务进行服务注册与搜索)服务上查找。如果是RMI调用的话,还需要一个RMl Registry来注册服务的地址。

第三,当A服务器上的应用发起远程过程调用时,方法的参数需要通过底层的网络协议如TCP传递到B服务器,由于网络协议是基于二进制的,内存中的参数的值要序列化成二进制的形式,也就是序列化(Serialize)或编组(marshal),通过寻址和传输将序列化的二进制发送给B服务器。

第四,B服务器收到请求后,需要对参数进行反序列化(序列化的逆操作),恢复为内存中的表达方式,然后找到对应的方法(寻址的一部分)进行本地调用,然后得到返回值。

第五,返回值还要发送回服务器A上的应用,也要经过序列化的方式发送,服务器A接到后,再反序列化,恢复为内存中的表达方式,交给A服务器上的应用

如图所示:

分布式RPC框架Dubbo详解,6e476058ef8644a7ba3764a242ca8035.png,第7张

 2.1.5 为什么需要RPC

论复杂度,RPC框架肯定是高于简单的HTTP接口的。但毋庸置疑,HTTP接口由于受限于HTTP协议,需要带HTTP请求头,导致传输起来效率或者说安全性不如RPC。

现在问题是,遇到怎样的瓶颈了才需要或者说更适合用RPC(比如像阿里这么大的请求并发量,简单的HTTP肯定达不到预期),但问题是像阿里这么大的量是比较少的,甚至说1/1000的量可能都没有,那我们还需要使用RPC吗?技术应该不是为了使用新技术而去使用,而应该是旧技术存在某些瓶颈,存在难以支撑或者扩展性越老越差等问题暴露出来之后,用新技术来进行解决。

那RPC最大的优点,或者说它相比简单的HTTP接口,它的优势、更适合它的业务场景是怎样呢?简单的HTTP又哪里不足,哪些场景明显不太适合呢?

http接口是在接口不多、系统与系统交互较少的情况下,解决信息初期常使用的一种通信手段;优点就是简单、直接、开发方便。利用现成的http协议进行传输。但是如果是一个大型的网站,内部子系统较多、接口非常多的情况下,RPC框架的好处就显示出来了,首先就是长链接,不必每次通信都要像http一样去3次握手什么的,减少了网络开销(这个问题在http2.0已经被解决不再算是问题了);其次就是RPC框架一般都有注册中心,有丰富的监控管理;发布、下线接口、动态扩展等,对调用方来说是无感知、统一化的操作。第三个来说就是安全性。最后就是流行的服务化架构、服务化治理,RPC框架是一个强力的支撑。

RPC是一种概念,http也是RPC实现的一种方式,用http交互其实就已经属于RPC了。RPC框架可以做到灵活部署和解耦。系统做大了,肯定是需要做微服务的。现在我们做电商就是这样,单独有一个订单系统,支付系统,商品系统,用户系统。都是分开部署,单独上线的。


RPC:远程过程调用。RPC的核心并不在于使用什么协议。RPC的目的是让你在本地调用远程的方法,而对你来说这个调用是透明的,你并不知道这个调用的方法是部署哪里。通过RPC能解耦服务,这才是使用RPC的真正目的。RPC的原理主要用到了动态代理模式,至于http协议,只是传输协议而已。
RPC是一个软件结构概念,是构建分布式应用的理论基础。就好比为啥你家可以用到发电厂发出来的电?是因为电是可以传输的。至于用铜线还是用铁丝还是其他种类的导线,也就是用http还是用其他协议的问题了。这个要看什么场景,对性能要求怎么样。比如在java中的最基本的就是RMI技术,它是java原生的应用层分布式技术。我们可以肯定的是在传输性能方面,RMI的性能是优于HTTP的。那为啥很少用到这个技术?那是因为用这个有很多局限性,首先它要保证传输的两端都要要用java实现,且两边需要有相同的对象类型和代理接口,不需要容器,但是加大了编程的难度,在应用内部的各个子系统之间还是会看到他的身影,比如EJB就是基于rmi技术的。这就与目前的bs架构的软件大相径庭。用http必须要服务端位于http容器里面,这样减少了网络传输方面的开发,只需要关注业务开发即可。

 

2.2 Dubbo 

2.2.1 Dubbo 概述

Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。简单的说,dubbo就是个服务框架。

dubbo提供了三大核心能力:

  • 面向接口的远程方法调用;
  • 智能容错和负载均衡;
  • 以及服务自动注册和发现;

    dubbo 架构图如下所示:

    分布式RPC框架Dubbo详解,133513b36fff4cf28a48ab5406ea8806.png,第8张

     节点角色说明:

    分布式RPC框架Dubbo详解,78fbf6e81bf24e6b91a7dbbe5bc8a1d3.png,第9张

     

    调用关系说明

    1、服务容器负责启动,加载,运行服务提供者。

    2、服务提供者在启动时,向注册中心注册自己提供的服务。

    3、服务消费者在启动时,向注册中心订阅自己所需的服务。

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

    5、服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。

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

    2.2.2 Dubbo实战

    这里设置一个订单微服务和一个用户微服务,通过查询订单返回订单信息,订单中有用户信息,所有需要根据订单中的用户id调用用户微服务进行查询然后进行赋值返回订单信息,这里采用nacos和Dubbo相结合的方式。

    2.2.2.1 生产者(用户模块微服务)和消费者(订单模块微服务)导入依赖

           
                com.alibaba.cloud
                spring-cloud-starter-dubbo
            

    2.2.2.2 公共模块

    设置接口用于查询用户信息

    public interface UserService {
        public User queryUserId(Long id);
    }

     

    2.2.2.3 生产者(用户模块微服务)

    application.yml文件配置

    spring:
      cloud:
        nacos:
          server-addr: localhost:8848
          discovery:
            cluster-name: SH
      
    dubbo:
       #服务名称
      application:
        name: dubbo-user
      #注册中心
      registry:
        address: nacos://127.0.0.1:8848
      protocol:
        #协议名称
        name: dubbo
        #协议端口号
        port: 20880
      scan:
        base-packages: com.example.user.Imp  #扫描包的位置
    

    在com.example.user.Imp中建立DubboUserServiceImpl类并继承UserService类,代码如下;

    package com.example.user.Imp;
    import com.example.entity.JieKou.UserService;
    import com.example.entity.entities.User;
    import org.apache.dubbo.config.annotation.Service;
    @Service(version = "1.0")
    public class DubboUserServiceImpl implements UserService {
        public User queryUserId(Long id) {
            User user=new User();
            user.setId((long) 3);
            user.setUsername("admin");
            user.setAddress("ShanDon");
            return user;
        }
    }

    2.2.2.4 消费者(订单模块微服务)

    application.yml文件配置如下:

    dubbo:
      protocol:
        port: 20881
        name: dubbo
      registry:
        address: nacos://localhost:8848

    Controller类业务逻辑代码如下:

    @RestController                                 
    @RefreshScope                                   
    public class UserController {  
                     
        @Autowired                                  
        OrdersMapper ordersMapper;                  
               
     
        @Reference(version = "1.0",parameters = {"unicast","false"})  //服务提供的可以被多个消费者消费            
        UserService userService;                    
     
                  
                         
        @GetMapping("/order1/{id}")                 
        public Orders orders1(@PathVariable("id") Long id){                                        
            Orders orders = ordersMapper.selectById(id);                                           
            User user = userService.queryUserId(orders.getUserId());                               
            orders.setUser(user);                   
            return orders;                          
        }                                           
    }
     

    至此代码基本完成,运行结果如下图:

    分布式RPC框架Dubbo详解,e9bb2282600f44888cc5b6e738389436.png,第10张