zoukankan      html  css  js  c++  java
  • RPC 框架

    RPC

    谁能用通俗的语言解释一下什么是 RPC 框架? - 远程过程调用协议RPC(Remote Procedure Call Protocol)

    RPC就是要像调用本地的函数一样去调远程函数。

    推荐:https://www.zhihu.com/question/25536695

    RPC框架解释

    首先了解什么叫RPC,为什么要RPC,RPC是指远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。RPC采用客户机/服务器模式。请求程序就是一个客户机,而服务提供程序就是一个服务器。首先,客户机调用进程发送-一个有进程参数的调用信息到服务进程,然后等待应答信息。

    比如两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。比如说,一个方法可能是这样定义的:
    Employee getEmployeeByName(String fullName)那么:

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

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

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

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

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

    为什么RPC呢?就是无法在一个进程内,甚至一个计算机内通过本地调用的方式完成的需求,比如比如不同的系统间的通讯,甚至不同的组织间的通讯。由于计算能力需要横向扩展,需要在多台机器组成的集群上部署应用。

    要知道实现RPC很麻烦呀,什么多线程、什么Socket、什么I/O,都是让咱们普通程序员很头疼的事情。于是就有牛人开发出RPC框架(比如,CORBA、RMI、Web Services、RESTful Web Services等等)。简单点讲,RPC框架就是可以让程序员来调用远程进程上的代码一套工具。有了RPC框架,咱程序员就轻松很多了,终于可以逃离多线程、Socket、I/O的苦海了。

    RPC的协议有很多,比如最早的CORBA,Java RMI,Web Service的RPC风格,Hessian,Thrift,甚至Rest API。

    关于Netty

    而Netty框架不局限于RPC,更多的是作为一种网络协议的实现框架,比如HTTP,由于RPC需要高效的网络通信,就可能选择以Netty作为基础。除了网络通信,RPC还需要有比较高效的序列化框架,以及一种寻址方式。如果是带会话(状态)的RPC调用,还需要有会话和状态保持的功能。大体上来说,Netty就是提供一种事件驱动的,责任链式(也可以说是流水线)的网络协议实现方式。网络协议包含很多层次,很多部分组成,如传输层协议,编码解码,压缩解压,身份认证,加密解密,请求的处理逻辑,怎么能够更好的复用,扩展,业界通用的方法就是责任链,一个请求应答网络交互通常包含两条链,一条链(Upstream)是从传输层,经过一系列步骤,如身份认证,解密,日志,流控,最后到达业务层,一条链(DownStream)是业务层返回后,又经过一系列步骤,如加密等,又回到传输层。

    这样每一层都有一个处理接口,都可以进行不同的操作,比如身份认证,加解密,日志,流控,将
    不同的处理实现像拼积木那样插接起来就可以实现一个网络协议了(快速开发) 。每层都有自己
    的实现,上层不需要关注面向网络的操作 (可维护) 。Netty已经提供了很多实现。

    当然Netty还有许多好处,比如对非阻塞I0 (NIO) 的支持,比如在链上传递时最大程度的减少
    buffer的copy (高性能)。

    netty跟RPC有什么关系

    RPC要做到用户无感知的调用远程服务必定要经过网络传输,而netty正好是是Java编写的快速开发高性能高可靠性的网络编程框架。

    目前使用netty作为传输层的RPC框架很多,国内知名的有dubbo,motan等。

    下面以新浪开源的motan为例,说明netty在RPC的位置:

    下图中transport即使使用netty实现的。

    总结来说,netty就是解决RPC网络传输的。

    分布式RPC需要解决哪些问题呢?

    1. protocol:传输协议
    2. proxy:client代理,服务引用方调用方法通过代理发送远程消息
    3. codec:协议编解码压缩等
    4. transport:协议传输
    5. registry:注册中心,服务注册服务发现
    6. cluster:负载均衡,服务容错策略
    7. 其他:服务降级,服务隔离,服务治理

    如何实现一个分布式的RPC框架呢?

    现在互联网已经很少单点服务了,一个好的rpc框架能帮我们省掉很多工作,那么如何撸一个自己喜欢的RPC框架呢?

    现在写rpc框架已经不难了,我们可以有很多参考,很多成熟的第三方开源项目可以依赖,可以说是站在巨人的肩膀上。

    第一步,选择传输协议:

    高性能的rpc和良好的编码协议是分不开的。好的协议不仅耗用流量小,而且序列化和反序列化更快。

    现在比较流行的协议有thrift,protobuf,json,restful等。其中thrfit和protobuf性能都比较优异,而且占用空间小,最重要的是跨语言,具有语言平台无关性。但,美中不足的是他们都需要预先根据协议文件预先生成好代码。开发极不流畅。

    我们也可以自定义协议,像dubbo和motan一样,定制自己的私有协议,

    比如motan协议的header部分如下:

    body部分采用hession或者fastjson序列化,

    如果不考虑跨语言,这种算是比较完美的解决方案。

    定义协议过程中的一些重要且容易忽略的问题:

    • 协议版本号
    • 消息id
    • 协议扩展字段

    第二步,协议传输层

    一个高性能RPC框架最重要的四个点就是:传输协议,框架线程模型,IO模型,零拷贝。

    java程序如果能做好这四点,那么性能应该不会比c++程序差多少。

    而作为java开发者,netty正好解决了后三个点,所以使用netty作为RPC框架的传输层会事半功倍。

    第三部,注册中心的选择

    现在有很多提供服务注册发现的服务,实现成本比较低就是zookeeper,可以很容易的实现服务注册和服务发现的功能。


    解决了这三部,后面的就得脚踏实地码代码了,当然后续会有很多细节,不过都不是问题,现在有好多成熟的开源框架可以参考。

    当然也可以参考我最近实现的分布式RPC框架,也欢迎提issue(后续会持续优化)。

    自己撸一个RPC还是很不错的,如果有兴趣建议自己撸一遍玩玩。

    下面是广告时间>>>>>>>>>

    dempeZheng/forestRPC 基于netty, spring,轻量的高性能分布式RPC服务框架

    Overview

    基于netty, spring,轻量的高性能分布式RPC服务框架。简单,易用,高效。

    Features

    • 服务端支持多种序列化方式:fastjson,hession,kryo
    • 服务端支持多种压缩方式:gzip,snappy
    • 服务端可根据group进行线程隔离,支持基于spring对不同的group配置不同的业务线程池
    • 支持注解配置,也支持spring xml配置
    • 支持服务发现服务注册
    • client端支持多种负载均衡策略和容灾策略
    • client内置连接池
    • 基于netty 4.x版本实现,高性能(win 8cpu单机8w+)

    TODO

    • 服务降级功能
    • http服务支持
    • 跨语言协议支持
    • 服务治理管理后台

    郑大侠的回答 - 知乎
    https://www.zhihu.com/question/25536695/answer/134976748

    RPC流程

    RPC:远程调用。通过RPC框架,使得我们可以像调用本地方法一样地调用远程机器上的方法:

    1、本地调用某个函数方法

    2、本地机器的RPC框架把这个调用信息封装起来(调用的函数、入参等),序列化(json、xml等)后,通过网络传输发送给远程服务器

    3、远程服务器收到调用请求后,远程机器的RPC框架反序列化获得调用信息,并根据调用信息定位到实际要执行的方法,执行完这个方法后,序列化执行结果,通过网络传输把执行结果发送回本地机器

    4、本地机器的RPC框架反序列化出执行结果,函数return这个结果

    服务调用端(本地机器):

    服务提供端(远程机器):

    Java Netty 是在TCP(Socket)层对nio进行封装的框架,在RPC框架中可用于解决网络传输问题。

    现在流行的微服务框架(dubbo、spring cloud等),实际上就是各种各样的RPC框架



    https://www.zhihu.com/question/25536695/answer/285844835

    https://www.zhihu.com/question/25536695/answer/36197244

  • 相关阅读:
    【BZOJ4637】期望 Kruskal+矩阵树定理
    IEnumerable是什么
    (转)IIS windows认证
    使用pgrouting进行最短路径搜索
    Nginx设置防止IP及非配置域名访问
    java 调用c# web api 代码
    一台机器部署多个tomcat服务 nginx反向代理多个服务 笔记
    利用Kettle 从Excel中抽取数据写入SQLite
    sql server 统计信息
    sql server 索引碎片相关问题
  • 原文地址:https://www.cnblogs.com/wwct/p/12945750.html
Copyright © 2011-2022 走看看