RPC入门与源码剖析

本文介绍了RPC的基本概念,对比了RPC与HTTP调用的区别,并详细剖析了Python中xmlrpc的实现原理,包括客户端、服务器端的工作流程。通过Python的xmlrpc示例,展示了如何构建和使用RPC服务,最后探讨了RPC框架的核心功能,为读者提供了深入理解RPC的思路。
摘要由CSDN通过智能技术生成

在这里插入图片描述

前言

RPC到底是什么?
gRPC又是什么?
与HTTP直接存在什么关系?

本文将讨论一下RPC相关的概念并以Python中自带的xmlrpc为例,简单剖析源码,理解它的实现原理,理解后,自己也可以轻松实现一个玩具RPC框架。

RPC概念

RPC简单定义:

RPC(Remote Procedure Call)– 远程过程调用,通过「网络通信」调用不同的服务,共同支撑一个软件系统,是分布式系统中的基石技术。

阅读完RPC定义,我内心疑惑是:

1.服务之间通过API的方式走HTTP不也可以实现通过网络通信调用不同的服务的目的?
2.它与HTTP有啥差别?
3.相比于API调用的方式有何优势?

首先,RPC 是一种技术思想而非一种规范或协议,RPC可以基于HTTP来实现,也可以基于其他方式,比如常见的TCP或自己定义协议通过Socker来实现。

gRPC是Google知名的RPC框架,RPC框架是对RPC技术思想的现实实现,类似于idea和相应idea的project的关系,gRPC本身是构建于HTTP2.0上的,使用Google的Protobuf协议来传输信息。

那相比与API调用,它有什么优势?

系统内部API调用在系统间交互较少,接口不多的情况下,确实是一种有效的通信手段,它实现简单、直接,但一个大系统,子系统的交互可能很多,如果要使用API,就需要定义非常多的接口,难以维护。

此外,使用RPC框架后,远程调用会与本地调用一样简单,底层网络传输的过程对用户而言是透明的。RPC框架会自动进行数据序列化、协议编码和网络传输等过程。

题外话:很多介绍RPC的博文会聊到系统间API调用走HTTP要进行3次握手、4次挥手,请求量大起来是很耗资源的,而RPC框架调用会维持长连接,从而减少网络开销。

这其实存在概念性错误,HTTP协议可以维持长连接,只需要在包头添加上Connection:keep-alive,HTTP/1.0默认使用短连接,但HTTP/1.1起,默认使用的就是长连接了,HTTP是应用层协议,它的长连接和短连接,实质上是 TCP 协议的长连接和短连接。

gRPC使用HTTP/2.0默认就会使用长连接来传输数据。

常见RPC框架

  • gPRC:Google开源的RPC框架,基于HTTP/2.0实现,可支持常见的多种语言,底层使用了Netty框架。
  • Thrift:Facebook开源的RPC框架,一个跨语言服务开发框架。
  • Dubbo:阿里巴巴开源的RPC框架,协议和序列化框架都可以插拔。

RPC框架常用的通信协议:RMI、Socket、SOAP(HTTP XML)、REST(HTTP JSON)

通信框架:MINA 和 Netty

RPC核心功能

知名开源RPC框架代码比较复杂,具有很多功能,但RPC最核心的功能非常简单,所以这里去繁从简,只了解RPC框架最核心的功能,然后通过Python自带的xmlrpc来学习一下RPC代码层面的实现。

一个RPC框架其核心功能可以分成5个主要部分,分别是:客户端、客户端 Stub、网络传输模块、服务端 Stub、服务端等,之间的关系如下图。

  • 客户端(Client):服务调用方。
  • 客户端存根(Client Stub):存放服务端地址信息,将客户端的请求参数数据信息打包成网络消息,再通过网络传输发送给服务端。
  • 服务端存根(Server Stub):接收客户端发送过来的请求消息并进行解包,然后再调用本地服务进行处理。
  • 服务端(Server):服务的真正提供者。
  • Network Service:底层传输,可以是 TCP 或 HTTP。

通过Python的xmlrpc简单使用一下,加深对上面概念的理解。

首先构建一个Server端。

from xmlrpc.server import SimpleXMLRPCServer

def is_even(n):
    return n % 2 == 0

server = SimpleXMLRPCServer(('127.0.0.1', 5000))
print('Listening on port 5000....')
server.register_function(is_even, 'is_even') # 注册服务
server.serve_forever()

上述代码中,使用了SimpleXMLRPCServer类构建了RPC Server实例,然后将Server端可以被远程调用的方法通过register_function方法进行注册,这里将is_even方法注册,客户端可以无感调用is_even方法,最后调用serve_forever方法让Server端一直轮训监听5000端口。

除了使用register_function方法注册方法,你还可以通过register_instance方法注册类实例,此时该类下的所有方法都可以被远程Client端调用,更多用法参考文档。

接着构建一个Client端。

import xmlrpc.client

with xmlrpc.client.ServerProxy('http://127.0.0.1:5000/') as proxy:
    res1 = proxy.is_even(3) # 调用服务端的is_even方法
    print('res1: ', res1)
    res2 = proxy.is_even(100)
    print('res2: ', res2)

Cliet端的代码更简洁,通过with上下文机制管理 xmlrpc.client.ServerProxy,然后直接调用Server端的方法,看上去很神奇。

仔细观察Server端的输出,可以发现Client端的两次调用,其实就是两次POST请求,走的是HTTP/1.1,这说明Python的xmlrpc基于HTTP/1.1作为网络传输协议。

xmlrpc源码剖析

Client端如同调用本地方法的形式实现对Server端方法的调用,这效果非常棒,那它是怎么实现的呢?我自己可不可以写一个呢?

剖析源码前,要思考一下从哪里入手,其实从Client端看更易理解(我一开始看Server端,绕了半天…)。

仔细观察下面的代码。

with xmlrpc.client.ServerProxy('http://127.0.0.1:5000/') as proxy:
    res1 = proxy.is_even(3) # 调用服务端的is_even方法
    print('res1: ', res1)
    res2 = proxy.is_even
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

懒编程-二两

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值