1.什么是 RPC 框架
RPC(Remote Procedure Call,远程过程调用)是一种计算机通信协议,允许调用不同进程空间的程序。RPC 的客户端和服务器可以在一台机器上,也可以在不同的机器上。程序员使用时,就像调用本地程序一样,无需关注内部的实现细节。
不同的应用程序之间的通信方式有很多,比如浏览器和服务器之间广泛使用的基于 HTTP 协议的 Restful API。与 RPC 相比,Restful API 有相对统一的标准,因而更通用,兼容性更好,支持不同的语言。HTTP 协议是基于文本的,一般具备更好的可读性。但是缺点也很明显:
- Restful 接口需要额外的定义,无论是客户端还是服务端,都需要额外的代码来处理,而 RPC 调用则更接近于直接调用。
- 基于 HTTP 协议的 Restful 报文冗余,承载了过多的无效信息,而 RPC 通常使用自定义的协议格式,减少冗余报文。
- RPC 可以采用更高效的序列化协议,将文本转为二进制传输,获得更高的性能。
- 因为 RPC 的灵活性,所以更容易扩展和集成诸如注册中心、负载均衡等功能。
2.简单实现一个RPC, 但是 Python
实现的话,我们并没有使用现有的rpc框架,选择返璞归真采用socket模块简单做一个最基础的
在这里首先贴上源代码
服务端类:rpc_serve
import socketserver
# 自定义处理器类
class RPCRequestHandler(socketserver.BaseRequestHandler):
def handle(self):
# 接收请求数据
request_data = self.request.recv(1024).strip().decode("utf-8")
print("Received request:", request_data)
# 解析请求参数
method, params = request_data.split("|")
params = [int(param) for param in params.split(",")]
# 执行远程过程
if method == "add":
result = self.add(*params)
elif method == "subtract":
result = self.subtract(*params)
else:
result = "Unknown method"
# 发送响应数据
self.request.sendall(str(result).encode("utf-8"))
def add(self, x, y):
return x + y
def subtract(self, x, y):
return x - y
# 创建服务器并启动
server = socketserver.TCPServer(("localhost", 8000), RPCRequestHandler)
print("Starting RPC server on localhost:8000...")
server.serve_forever()
客户端类:rpc_client
import socket
# 创建套接字并连接服务器
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(("localhost", 8000))
# 构造请求数据
method = "add"
params = "5,3"
request_data = f"{method}|{params}".encode("utf-8")
# 发送请求数据
client_socket.sendall(request_data)
# 接收响应数据
response_data = client_socket.recv(1024).strip().decode("utf-8")
# 打印结果
print("Response:", response_data)
# 关闭套接字连接
client_socket.close()
那么, 输出示例是这样的:
Starting RPC server on localhost:8000...
Received request: add|5,3
Response: 8
这个输出示例是一个简单的RPC示例的运行结果。当你启动服务端和客户端后,它们之间建立了TCP连接。
- 服务端输出了一条消息:"Starting RPC server on localhost:8000...",表示服务端已成功启动并在本地主机的8000端口监听连接请求。
- 客户端发送了一条请求数据给服务端:method为"add",params为"5,3",表示要调用服务端的"add"方法,并传入参数5和3。
- 服务端接收到客户端的请求数据,解析后发现是调用"add"方法,并将参数5和3相加得到结果8。
- 服务端将结果8作为响应数据发送给客户端。
- 客户端接收到服务端的响应数据后,输出了一条消息:"Response: 8",表示收到了服务端返回的结果8。
这个示例展示了一个简单的RPC通信过程:客户端发送请求给服务端,服务端处理请求并返回结果给客户端。通过这种方式,客户端可以间接调用服务端的函数或方法,实现远程过程调用。
3.谈谈 socket
Socket(套接字)是一种用于实现网络通信的编程接口。它提供了一组用于网络数据传输的函数和方法,使得应用程序可以通过网络与其他应用程序进行通信。
在计算机网络中,不同主机之间的通信需要使用协议进行规范和管理。其中,TCP/IP协议栈是互联网上最常用的协议栈之一。套接字则是在TCP/IP协议栈中应用层与传输层之间的接口,它将传输层提供的功能封装成一组易于使用的函数和方法,使得应用程序能够方便地进行网络通信。
套接字可以用于两种类型的网络通信:TCP(传输控制协议)和UDP(用户数据报协议)。
-
TCP套接字:TCP提供可靠的、面向连接的通信。TCP套接字通过建立连接、传输数据、断开连接的方式进行通信。它包含以下特点:
- 可靠性:TCP使用可靠的数据传输机制,确保数据的完整性和顺序性。
- 面向连接:在通信之前,发送方和接收方需要建立一个连接,形成一个虚拟的数据通路。
- 全双工:建立连接后,两端可以同时发送和接收数据。
- 流式传输:数据以字节流的形式进行传输,没有消息边界。
-
UDP套接字:UDP提供不可靠的、无连接的通信。UDP套接字通过无连接地发送数据报给对方进行通信。它包含以下特点:
- 不保证可靠性:UDP不保证数据的完整性和顺序性,传输过程中可能会丢失、重复或乱序。
- 无连接:每个数据报都是独立地发送,无需建立虚拟的数据通路。
- 面向报文:每个UDP数据报都被当作一个单独的报文进行处理。
套接字编程可以使用不同的编程语言来实现,如Python、Java、C++等。在编程中,通常通过创建套接字对象、设置套接字选项、绑定地址和端口、监听连接请求、接收和发送数据等方式来实现网络通信。
套接字的应用场景非常广泛。例如,Web服务器使用套接字与客户端进行HTTP通信;电子邮件客户端通过套接字与邮件服务器进行SMTP或POP3通信;P2P文件共享应用程序使用套接字进行节点间的通信等。
总结起来,套接字是一种网络编程接口,它为应用程序提供了一组函数和方法,使得应用程序能够方便地进行网络通信。它是构建各种网络应用的基础,实现了不同主机之间的数据传输和通信。
more:现有的大厂商的自研rpc都是基于什么技术
大厂商的自研 RPC(远程过程调用)框架通常不直接基于底层的 Socket 技术,而是在 Socket 的基础上进行封装和扩展,以提供更高级、更便捷的网络通信功能。以下是一些常见的大厂商自研 RPC 框架和它们使用的技术:
- gRPC (Google RPC):gRPC 是 Google 开发的开源 RPC 框架,主要用于构建分布式系统。它使用 Protocol Buffers 作为数据序列化机制,并支持多种语言(如C++、Java、Python、Go等)。底层通信协议可以使用基于 HTTP/2 的传输层,或者采用 Google 自主研发的 QUIC 协议。
- Dubbo:Dubbo 是阿里巴巴自研的高性能、轻量级的分布式服务框架。它支持异步的、基于 TCP 的远程调用,并提供了负载均衡、服务注册与发现、容错处理等功能。
- Thrift:Thrift 是 Facebook 开源的跨语言的 RPC 框架,它支持多种编程语言(如C++、Java、Python等)。Thrift 使用 IDL(接口定义语言)来定义接口和数据类型,并使用自动生成的代码来实现跨语言的通信。底层通信可以使用基于 Socket 的传输层,也可以使用其他协议(如HTTP)。
- Spring Cloud:Spring Cloud 是 Spring 社区提供的一套微服务框架。它基于 Spring Boot,提供了诸多功能组件,包括服务注册与发现、负载均衡、断路器等。Spring Cloud 可以使用不同的通信方式来实现远程调用,例如基于 HTTP/REST 的调用、基于 RabbitMQ 的消息队列、基于 Kafka 的消息中间件等。
尽管底层通信协议可能不同,但这些 RPC 框架都致力于简化分布式系统中的远程调用过程,并提供高性能、高可靠性的网络通信能力。它们通过封装和抽象,提供了更方便的开发接口,使开发者能够更轻松地构建分布式应用,并且具备自动的序列化、反序列化、负载均衡等特性。
final
本文到此结束,如有错误或遗漏请指正,谢谢