zoukankan      html  css  js  c++  java
  • RPC原理

    今天开始聊一些微服务的实践,第一块,RPC框架的原理及实践,为什么说要搞定微服务架构,先搞定RPC框架呢?

    一、需求缘起

    服务化的一个好处就是,不限定服务的提供方使用什么技术选型,能够实现大公司跨团队的技术解耦,如下图:

     

    服务A是欧洲团队提供服务,欧洲团队的技术背景是Java,可以用Java实现服务;

    服务B是美洲团队提供服务,可以用C++实现服务;

    服务C是中国团队提供服务,可以用Go实现服务;

    服务的上游调用方,按照接口、协议即可完成对远端服务的调用。

    但实际上,99.9%的公司的团队规模有限,技术团队人数也有限,基本是使用同一套技术体系来调用和提供服务的:

     

    这样的话,如果没有统一的服务框架,RPC框架,各个团队的服务提供方就需要各自实现一套序列化、反序列化、网络框架、连接池、收发线程、超时处理、状态机等“业务之外”的重复技术劳动,造成整体的低效。所以,统一RPC框架把上述“业务之外”的技术劳动统一处理,是服务化首要解决的问题。

    在达成【“使用统一的RPC框架”是正确的道路】这个一致的前提下,本文期望用简单通俗的言语简述一下一个通用RPC框架的技术点与实现。

    二、RPC背景与过程

    什么是RPC(Remote Procedure Call Protocol),远程过程调用?

    先来看下什么是本地函数调用,当我们写下:

    int result = Add(1, 2);

     

    这段代码的时候,我们知道,我们传入了1,2两个入参数,调用了本地代码段中的一个Add函数,得到了result出参。此时,传入数据,传出数据,代码段在同一个进程空间里,这是本地函数调用。

    那有没有办法,我们能够调用一个跨进程(所以叫“远程”,典型的,这个进程部署在另一台服务器上)的函数呢?

     

    最容易想到的,两个进程约定一个协议格式,使用Socket通信,来传输【入参】【调用哪个函数】【出参】。

    假设请求报文协议是一个11字节的字节流:

     

    (1)前3个字节填入函数名

    (2)中间4个字节填入第一个参数

    (3)末尾4个字节填入第二个参数

    同时可以设计响应报文协议是一个4字节的字节流:

     

    即处理结果。

    调用方的代码可能变为:

    1. request = MakePacket(“add”, 1, 2);  
    2. SendRequest_ToService_B(request); 
    3. response = RecieveRespnse_FromService_B(); 
    4. int result = unMakePacket(respnse); 

    简单解释一下:

    (1)讲传入参数变为字节流

    (2)将字节流发给服务B

    (3)从服务B接受返回字节流

    (4)将返回字节流变为传出参数

    服务方的代码可能变为:

    1. request = RecieveRequest(); 
    2. args/function = unMakePacket(request); 
    3. result = Add(1, 2); 
    4. response = MakePacket(result); 
    5. SendResponse(response); 

    这个过程也很好理解:

    (1)服务端收到字节流

    (2)将字节流转为函数名与参数

    (3)本地调用函数得到结果

    (4)将结果转变为字节流

    (5)将字节流发送给调用方

     

    这个过程用一张图描述如上,调用方与服务方的处理步骤都是非常清晰的。这个过程存在最大的问题是什么呢?

    回答:调用方太麻烦了,每次都要关注很多底层细节

    (1)入参到字节流的转化,即序列化应用层协议细节

    (2)socket发送,即网络传输协议细节

    (3)socket接受

    (4)字节流到出参的转化,即反序列化应用层协议细节

    能不能调用层不关注这个细节呢?

    回答:可以,RPC框架就是解决这个问题的,它能够让调用方“像调用本地函数一样调用远端的函数(服务)”。

    三、RPC框架职责

    通过上面的讨论,RPC框架要向调用方屏蔽各种复杂性,要向服务提供方也屏蔽各类复杂性:

    (1)调用方感觉就像调用本地函数一样

    (2)服务提供方感觉就像实现一个本地函数一样来实现服务

    所以整个RPC框架又分为client部分与server部分,负责把整个非(1)(2)的各类复杂性屏蔽,这些复杂性就是RPC框架的职责。

     

    再细化一些,client端又包含:序列化、反序列化、连接池管理、负载均衡、故障转移、队列管理,超时管理、异步管理等等等等职责。

    server端包含:服务端组件、服务端收发包队列、io线程、工作线程、序列化反序列化、上下文管理器、超时管理、异步回调等等等等职责。

    however,因为篇幅有限,这些细节不做深入展开。

    四、结论

    (1)RPC框架是架构微服务化的首要基础组件,它能大大降低架构微服务化的成本,提高调用方与服务提供方的研发效率,屏蔽跨进程调用函数(服务)的各类复杂细节

    (2)RPC框架的职责是:让调用方感觉就像调用本地函数一样调用远端函数、让服务提供方感觉就像实现一个本地函数一样来实现服务

  • 相关阅读:
    手把手教你利用create-nuxt-app脚手架创建NuxtJS应用
    初识NuxtJS
    webpack打包Vue应用程序流程
    用选择器代替表格列的筛选功能
    Element-UI
    Spectral Bounds for Sparse PCA: Exact and Greedy Algorithms[贪婪算法选特征]
    Sparse Principal Component Analysis via Rotation and Truncation
    Generalized Power Method for Sparse Principal Component Analysis
    Sparse Principal Component Analysis via Regularized Low Rank Matrix Approximation(Adjusted Variance)
    Truncated Power Method for Sparse Eigenvalue Problems
  • 原文地址:https://www.cnblogs.com/zourui4271/p/9690300.html
Copyright © 2011-2022 走看看