flask-web —— RPC定义、结构、gRPC、Protocol Buffers

一、RPC简介

1. 什么是RPC

远程过程调用(英语:Remote Procedure Call,缩写为 RPC,也叫远程程序调用)是一个计算机通信协议。该协议允许运行于一台计算机的程序调用另一台计算机的子程序,而程序员无需额外地为这个交互作用编程。如果涉及的软件采用面向对象编程,那么远程过程调用亦可称作远程调用或远程方法调用
flask-web —— RPC定义、结构、gRPC、Protocol Buffers_第1张图片

2. 背景与用途

在单台计算机中,我们可以通过程序调用来传递控制和数据;或者说通过程序调用,我们可以将多个程序组成一个整体来实现某个功能。

如果将这种调用机制推广到多台彼此间可以进行网络通讯的计算机,由多台计算机中的多个程序组成一个整体来实现某个功能,这也是可以的。调用的一方(发起远程过程调用,然后调用这方的环境挂起,参数通过网络传递给被调用方,被调用的一方执行程序,当程序执行完成后,产生的结果再通过网络回传给调用的一方,调用的一方恢复继续执行。这样一种原型思想,就是我们所说的RPC远程过程调用。

RPC这种思想最早可以追溯到1976年,RPC的发展到今天已经40年有余了。

如今的计算机应用中,单机性能上很难承受住产品的压力,需要不断扩充多台机器来提升整体的性能。同时为了充分利用这些集群里的计算机,需要对其从架构上进行划分,以提供不同的服务,服务间相互调用完成整个产品的功能。RPC就能帮助我们解决这些服务间的信息传递和调用。

3. 概念说明

关于RPC的概念,我们可以从广义和狭义来分别进行理解。

广义

我们可以将所有通过网络来进行通讯调用的实现统称为RPC。

按照这样来理解的话,那我们发现HTTP其实也算是一种RPC实现
flask-web —— RPC定义、结构、gRPC、Protocol Buffers_第2张图片

狭义

区别于HTTP的实现方式,在传输的数据格式上和传输的控制上独立实现。比如在机器间通讯传输的数据不采用HTTP协议的方式(分为起始行、header、body三部份),而是使用自定义格式的二进制方式

我们更多时候谈到的RPC都是指代这种狭义上的理解

4. 优缺点

相比于传统HTTP的实现而言:

优点

  • 效率高
  • 发起RPC调用的一方,在编写代码时可忽略RPC的具体实现,如同编写本地函数调用一样

缺点

  • 通用性不如HTTP好 因为传输的数据不是HTTP协议格式,所以调用双方需要专门实现的通信库,对于不同的编程开发语言,都要有相关实现。而HTTP作为一个标准协议,大部分的语言都已有相关的实现,通用性更好。

——> HTTP更多的面向用户与产品服务器的通讯。面向大众的

——> RPC更多的面向产品内部服务器间的通讯。 thrift。更多的是公司内部之间 ,各个系统的调用,高效便捷

多方系统之间调用的方式:
  • 方式一: X 本地调用

    • 把推荐系统封装成工具类或函数
    • 两个系统耦合性太高 在web代码中包含了推荐系统的具体实现,关联性太高
  • 方式二: HTTP调用

    • 把推荐系统当做单独的一个小项目,独立运行部署,web直接调用

    • 耦合性很低

    • 网络调用

      由推荐系统封装HTTP 接口,在web中发起http请求进行调用

      缺点 HTTP的效率低下

        ```
        GET http://192.168.10.4:8000/recomment HTTP/1.1
        ....
        body
        ```
      
  • 方式三: RPC调用 远端过程调用

    • 将网络调用封装的如同本地函数调用一样
    • 网络通讯效率越高越好,网络上传传输的调用数据 以二进制数据为主
    • 可以调用的客户端 不像http一样 ,不是标准,只要自己系统能调用即可。
      • Facebook -> Thrift
      • Google -> gRPC 方案 传输的数据 协议 protobuf
RPC结构

RPC的设计思想是力图使远程调用中的通讯细节对于使用者透明,调用双方无需关心网络通讯的具体实现。因而实现RPC要进行一定的封装。

RPC原理上是按如下结构流程进行实现的。
flask-web —— RPC定义、结构、gRPC、Protocol Buffers_第3张图片

流程:

  1. 调用者(Caller, 也叫客户端、Client)以本地调用的方式发起调用;
  2. Client stub(客户端存根,可理解为辅助助手)收到调用后,负责将被调用的方法名、参数等打包编码成特定格式的能进行网络传输的消息体;
  3. Client stub将消息体通过网络发送给对端(服务端)
  4. Server stub(服务端存根,同样可理解为辅助助手)收到通过网络接收到消息后按照相应格式进行拆包解码,获取方法名和参数;
  5. Server stub根据方法名和参数进行本地调用;
  6. 被调用者(Callee,也叫Server)本地调用执行后将结果返回给server stub;
  7. Server stub将返回值打包编码成消息,并通过网络发送给对端(客户端);
  8. Client stub收到消息后,进行拆包解码,返回给Client;
  9. Client得到本次RPC调用的最终结果。

二、gRPC

简介

  • gRPC是由Google公司开源的高性能RPC框架。

  • gRPC支持多语言

  • gRPC原生使用C、Java、Go进行了三种实现,而C语言实现的版本进行封装后又支持C++、C#、Node、ObjC、 Python、Ruby、PHP等开发语言

  • gRPC支持多平台

    支持的平台包括:Linux、Android、iOS、MacOS、Windows

  • gRPC的消息协议使用Google自家开源的Protocol Buffers协议机制(proto3) 序列化

  • gRPC的传输使用HTTP/2标准,支持双向流和连接多路复用
    flask-web —— RPC定义、结构、gRPC、Protocol Buffers_第4张图片

架构

C语言实现的gRPC支持多语言,其架构如下

flask-web —— RPC定义、结构、gRPC、Protocol Buffers_第5张图片

使用方法
  1. 使用Protocol Buffers(proto3)的IDL接口定义语言定义接口服务,编写在文本文件(以.proto为后缀 名)中。
  2. 使用protobuf编译器生成服务器和客户端使用的stub代码
  3. 编写补充服务器和客户端逻辑代码

三 、 Protocol Buffers

Protocol Buffers 是一种与语言无关,平台无关的可扩展机制,用于序列化结构化数据。使用Protocol Buffers 可以一次定义结构化的数据,然后可以使用特殊生成的源代码轻松地在各种数据流中使用各种语言编写和读取结构化数据。

现在有许多框架等在使用Protocol Buffers。gRPC也是基于Protocol Buffers。 Protocol Buffers 目前有2和3两个版本号。

在gRPC中推荐使用proto3版本。

1 文档结构

1) Protocol Buffers版本
Protocol Buffers文档的第一行非注释行,为版本申明,不填写的话默认为版本2。

syntax = "proto3";
或者
syntax = "proto2";

2)Package包
Protocol Buffers 可以声明package,来防止命名冲突。 Packages是可选的。

package foo.bar;
message Open { ... }

使用的时候,也要加上命名空间,

message Foo {
  ...
  foo.bar.Open open = 1;
  ...
}

注意:对于Python而言,package会被忽略处理,因为Python中的包是以文件目录来定义的。

3)导入
Protocol Buffers 中可以导入其它文件消息等,与Python的import类似。

import “myproject/other_protos.proto”;

4)定义各种消息和服务

消息messge是用来定义数据的,服务service是用来gRPC的方法的。

其实,Protocol Buffers 是一种IDL(交互式数据语言),类似于一种脚本,编译后生成对应的后台接口

四、实际项目子系统对接

在首页中 获取特定用户的推荐文章列表 需要web系统和推荐系统配合

  • 有web系统告知 推荐系统 用户id是谁
  • 推荐系统 根据用户id 决定 推荐的文章id
  • web系统 根据推荐的文章id 查询文章数据,返回给客户端

在Web系统中

构建客户端请求首页数据的接口

GET  /articles?channel_id=10
class ArticleListResource(Resource):
    
    def get(self):
        channel_id
        user_id
        # 调用推荐系统的接口 获取推荐文章id
        ret = recommend_article(channel_id, user_id)  方式一
        ret = urllib.reqeust('http://192.168.10.4:8000/recomment') 方式二
        # 查询缓存或数据库 获取文章的具体信息( 通过我们自己分装的缓存工具类)
        。。
        return 
  • 方式一: X 本地调用

    • 把推荐系统封装成工具类或函数
    • 两个系统耦合性太高 在web代码中包含了推荐系统的具体实现,关联性太高
  • 方式二: HTTP调用

    • 把推荐系统当做单独的一个小项目,独立运行部署,web直接调用

    • 耦合性很低

    • 网络调用

      由推荐系统封装HTTP 接口,在web中发起http请求进行调用

      缺点 HTTP的效率低下

      GET http://192.168.10.4:8000/recomment HTTP/1.1
      ....
      body
      
  • 方式三: RPC调用 远端过程调用

    • 将网络调用封装的如同本地函数调用一样
    • 网络通讯效率越高越好,网络上传传输的调用数据 以二进制数据为主
    • 可以调用的客户端 不像http一样 ,不是标准,只要自己系统能调用即可。
      • Facebook -> Thrift
      • Google -> gRPC 方案 传输的数据 协议 protobuf
使用RPC方法
  1. 声明RPC调用的接口形式

     ret = recommend_article(channel_id, user_id)
    

    接口的名字 recommend_article

    调用时传递的参数 int channel_id , int user_id

    接口返回数据 int list [article_id, article_id, ....]

  2. 生成 调用的代码 (包含了 参数转换为二进制传输的方法、网络传输收发的方法)

    rpc框架会提供生成代码的工具 (编译器)

    使用编译器生成不同语言的代码

    调用方 python -> 使用编译器 根据上面的接口描述 ,生成python代码

    被调用方 java -> 使用编译器 根据上面的接口,生成java代码

  3. 需要补充代码

    在被调用的一端 服务端 补充被调用时执行的逻辑函数

    在调用的一方,需要在 调用的代码地方 补充上调用的代码

你可能感兴趣的:(python-web,flask,python,python,rpc,grpc,flask)