当前位置: 首页 > article >正文

RPC是啥?

笨人从本科开始学习网络到现在已经4年了,tcp、http相关的概念背是可以背下来,理解上好像也差不多?但总是感觉有点怪怪的,不太清楚为什么网络架构要这样设计,今天结合一下chat老师和小林coding的回答,把自己一知半解的搞清楚,要不然永远都无法深入理解网络,rpc这样方便的东西也永远不可能从自己的手里写出来。主要是梳理自己不理解的东西,会很啰嗦。

3.8 既然有 HTTP 协议,为什么还要有 RPC? | 小林coding

Socket和端口的区别是啥

这一部分对了解,为什么有了tcp还要有http和rpc,以及为什么会有这俩有帮助

📌 Socket 和 端口的区别

💡 一句话理解:

端口(Port)门牌号 🏠,用于区分计算机上的不同服务。

Socket通信管道 🚇,用来建立 两台设备之间的数据传输通道


🔹 1. 端口(Port)是什么?

🔸 端口是 操作系统分配给应用程序的“门牌号”,用于区分同一台计算机上运行的不同程序。

🔸 一个 IP 地址 + 一个端口 组成一个唯一地址,用于接收或发送数据。

🔸 端口号范围: 0-65535,其中:

• 0-1023 👉 系统端口(如 HTTP 用 80,HTTPS 用 443)

• 1024-49151 👉 注册端口(常见应用,如 MySQL 3306)

• 49152-65535 👉 临时端口(客户端随机分配)

📝 举个例子:

• 192.168.1.10:80(访问网站)

• 192.168.1.10:3306(连接 MySQL 数据库)

同一 IP 地址,不同端口,对应不同的服务!


🔹 2. Socket 是什么?

🔸 Socket 是“通信管道” 🚇,连接 两台设备之间的数据流

🔸 由 4 个元素唯一标识

(客户端 IP, 客户端端口, 服务器 IP, 服务器端口)

🔸 服务器监听端口,等待客户端建立 Socket 连接,连接成功后双方就可以互相收发数据。


🔹 3. 端口 vs. Socket 对比

🔍 对比项

🏠 端口(Port)

🚇 Socket

作用

标识应用程序的门牌号

建立数据流,连接两个设备

范围

0 - 65535

由 IP、端口 组成

谁在使用

服务器和客户端

服务器和客户端

是否可以共享

✅ 可以多个进程监听不同端口

❌ 一个 Socket 只能属于一条连接

例子

127.0.0.1:8080

(127.0.0.1, 50000, 127.0.0.1, 8080)


🔹 4. 举个通俗的例子 🎭

🍕 比喻:

端口(Port)➡ 餐厅的座位号 🪑(不同顾客在不同座位点餐)

Socket(Socket)➡ 电话通话 📞(服务员和顾客建立连接沟通)

场景 1:

• 你去餐厅(IP 地址)找座位(端口),比如桌子 8080 号

• 服务员(服务器)在 8080 号桌子 监听顾客的需求(等待连接)。

场景 2:

• 你拨打电话(客户端创建 Socket 连接)。

• 服务员接听电话,双方可以交流(服务器 accept 连接)。

如果没有端口,计算机就不知道数据该发给谁;如果没有 Socket,客户端和服务器就无法真正通信。 🎯

为什么http是基于tcp的?以及他们的封装方式是什么样子。为什么一定要有http,直接给http设计三次握手,这样没有tcp不是也可以了吗

🔹 为什么 HTTP 是基于 TCP 的?

💡 一句话理解:

HTTP 需要 可靠的传输,确保网页内容 完整、无误、按顺序到达,而 TCP 提供了这种 可靠的传输机制,所以 HTTP 建立在 TCP 之上


🔹 HTTP vs. TCP 的关系

HTTP(HyperText Transfer Protocol,超文本传输协议)是应用层协议,它不关心数据如何传输,只负责定义如何请求和响应数据(如网页、图片、视频等)。

而 TCP(Transmission Control Protocol,传输控制协议)是传输层协议,它负责数据可靠传输,解决丢包、乱序、重复等问题。

📌 简单来说:

HTTP 负责”内容”(网页、图片等),TCP 负责”快递”(确保完整送达)。

• HTTP 依赖 TCP 提供可靠的通信管道,因为 HTTP 需要数据必须按顺序到达,不能丢失,也不能重复

• TCP 提供三次握手来建立连接,四次挥手来关闭连接,确保数据无误。


🔹 HTTP & TCP 之间的封装方式

💡 链条式逻辑:

当你在浏览器输入 http://example.com 并回车后,数据经历 层层封装,最终到达服务器 ⬇️

📌 1. HTTP 层(应用层)

🔹 你请求一个网页,浏览器会构造一个 HTTP 请求报文

GET /index.html HTTP/1.1
Host: example.com
User-Agent: Chrome/122.0

⬇(封装)⬇

📌 2. TCP 层(传输层)

🔹 HTTP 数据被封装进 TCP 报文段,TCP 负责可靠传输

TCP 头部(序号、确认号、端口号等)
HTTP 数据(请求内容)

💡 TCP 头部包含

源端口 & 目标端口(如 50000 → 80)

序号 & 确认号(确保数据按顺序)

ACK 确认机制(保证数据送达)

三次握手 & 四次挥手(建立 & 关闭连接)

⬇(封装)⬇

📌 3. IP 层(网络层)

🔹 TCP 数据被封装进 IP 数据包,IP 负责寻址 & 传输

IP 头部(源 IP, 目标 IP)
TCP 头部(端口号、序号等)
HTTP 数据

💡 IP 头部包含

源 IP & 目标 IP(如 192.168.1.10 → 93.184.216.34)

分片机制(如果数据太大,会被拆成小块)

⬇(封装)⬇

📌 4. 物理层(数据链路层)

🔹 IP 数据包被转换成二进制电信号(0 和 1),在网线/Wi-Fi 里传输。📡⚡


🔹 反向过程(解封装)

当服务器收到数据,过程会反向解封装

1️⃣ 物理层(收到二进制数据 📡)

2️⃣ 解析 IP 头部(确认目标是自己的 IP 📍)

3️⃣ 解析 TCP 头部(确认端口是 80,重组 TCP 数据)

4️⃣ 解析 HTTP 头部(交给 Web 服务器,如 Nginx 处理)

5️⃣ 最终,服务器返回 HTML 网页内容! 🎉


🔹 HTTP 为什么不直接基于 IP?

HTTP 直接使用 IP(UDP)会出问题:

• 📌 数据可能丢失(网页内容不完整)

• 📌 数据可能乱序(HTML 代码错乱)

• 📌 数据可能重复(影响页面解析)

• 📌 UDP 无法建立连接(无法确认对方是否在线)

而 TCP 解决了这些问题:

• 📦 确保数据可靠送达(丢了会重传)

• 🗂 数据按序到达(不乱序)

• 🤝 建立连接,保证完整性(三次握手)

➡ 所以,HTTP 必须依赖 TCP 保障网页数据完整传输!


🔹 总结

💡 HTTP 是“快递内容”的规则,TCP 是“快递运输”的保证。

1️⃣ HTTP 是基于 TCP 的应用层协议,因为 TCP 保证数据可靠送达

2️⃣ 数据传输层层封装,HTTP ⬇ TCP ⬇ IP ⬇ 物理层(Wi-Fi / 网线)。

3️⃣ TCP 解决了数据丢失、乱序、重复的问题,是 HTTP 稳定通信的基础

📌 一句话总结:

HTTP 像是点外卖(网页内容),但真正送餐的是 TCP,保证餐品完整送达! 🍕🚀

这是个很有意思的问题!如果 HTTP 自己实现三次握手,那么我们其实就是让 HTTP 重新发明了一遍 TCP,但为什么我们不这么做呢?🤔


🔹 直接让 HTTP 负责连接管理可行吗?

理论上是可行的,但实际上不划算,因为:

1️⃣ HTTP 的职责是”传输网页内容”,不该管”数据如何可靠送达”。

2️⃣ TCP 已经是通用的可靠传输协议,HTTP 直接复用它就好,没必要重复造轮子。

3️⃣ 让 HTTP 处理网络可靠性问题,会导致更复杂、更低效的实现。


🔹 如果 HTTP 自己实现可靠传输,会有什么问题?

💡 如果 HTTP 不使用 TCP,而自己处理连接管理(比如自己实现”HTTP 三次握手”),会遇到以下问题:

📌 1. HTTP 需要重写所有 TCP 的功能

HTTP 需要自己实现”超时重传”(如果数据丢失,得自己重发)。

HTTP 需要自己保证数据按序到达(否则网页内容可能乱掉)。

HTTP 需要自己做流量控制(防止网络拥塞影响用户体验)。

HTTP 需要自己做拥塞控制(防止服务器被请求压垮)。

但 TCP 已经帮 HTTP 解决了这些问题,HTTP 只需要专注于”网页请求”。

📌 2. HTTP 不是唯一需要可靠传输的协议

除了 HTTP,SMTP(邮件协议)、FTP(文件传输协议)、SSH(远程登录) 也都需要可靠传输。

如果每个协议都自己实现”三次握手”和”可靠传输”,那就是 每个协议都要自己维护一套复杂的连接管理机制,这极度浪费资源

有了 TCP,所有应用层协议(HTTP、SMTP、FTP、SSH)都可以直接用,避免重复开发。

📌 3. 服务器和客户端的兼容性问题

TCP 是操作系统内置的协议,所有网络设备都支持。

如果 HTTP 直接管理连接,每个 HTTP 服务器和浏览器都要改,网络上的所有设备(如路由器、防火墙)也要重新适配,工程量巨大。

现在所有编程语言(Java、Python、Go)都有 TCP 库,直接用 TCP 就行,何必重新实现?

📌 4. HTTP 主要是”请求-响应”模式,TCP 适用于更广泛场景

• HTTP 的核心是 “请求”(客户端发请求)和 “响应”(服务器返回网页),所以 HTTP 不适合处理:

长连接(WebSocket 需要 TCP)。

低延迟通信(游戏、语音通话更适合 UDP)。

高并发数据流(比如视频流,HTTP 需要 QUIC)。

TCP 作为通用协议,能适应各种场景,而 HTTP 只是其中之一,不适合自己搞三次握手。


🔹 那么 QUIC 是怎么回事?

你可能听说过 HTTP/3 使用 QUIC,而不是 TCP,那是不是证明 HTTP 可以自己搞连接管理?

🧐 不是的!QUIC 只是用 UDP 替代 TCP,但仍然提供了类似 TCP 的功能,比如:

QUIC 仍然有三次握手(甚至比 TCP 更快)。

QUIC 仍然有可靠传输、流量控制、拥塞控制。

QUIC 只是换了”底层传输方式”,但并没有让 HTTP 直接负责数据传输。

➡  QUIC 只是把 TCP 的功能搬到了 UDP 里,HTTP 依然不负责可靠传输。


🔹 总结

💡 为什么 HTTP 不自己实现三次握手?

1️⃣ HTTP 的重点是”传输网页数据”,不该负责”如何保证数据可靠送达”。

2️⃣ TCP 已经提供了成熟的”可靠传输”能力,HTTP 直接复用,避免重复造轮子。

3️⃣ 如果 HTTP 负责连接管理,每个应用层协议都要自己实现类似 TCP 的功能,极其低效。

4️⃣ 服务器、客户端、网络设备都已经优化了 TCP,直接使用 TCP 兼容性更好。

5️⃣ QUIC 也没有让 HTTP 直接管理连接,而是把 TCP 的功能搬到了 UDP 上,证明 HTTP 本身并不适合做这个事情。

📌 一句话总结:

HTTP 就像一个饭店的点餐系统,只管点菜(请求网页),而 TCP 像是厨房+送餐员,负责把菜按顺序送到你桌上。如果让 HTTP 自己管理送餐,那饭店就得自己培养送餐员、设计外卖路线,反而更复杂!🍽️🚀

rpc和http有啥区别?rpc按照我的理解就是封装了一些http这样直接调用函数就可以了

你理解得很接近了!RPC(远程过程调用)和 HTTP 主要的区别是:

💡 RPC 就像本地函数调用一样,而 HTTP 更像是发请求拿数据。


🚀 1. RPC 和 HTTP 的核心区别

🚀 对比

🏗️ RPC(远程过程调用)

🌍 HTTP(超文本传输协议)

本质

让远程服务器的方法 像本地函数一样调用

通过 URL 发 请求、拿 响应

调用方式

直接调用远程方法,比如 UserService.getUser(1)

发送 HTTP 请求,比如 GET /users/1

协议

可基于 TCP、UDP(比如 gRPC 用 HTTP/2)

严格基于 HTTP(一般是 RESTful API)

数据格式

高效的二进制格式(如 Protobuf、MessagePack)

基于文本的 JSON、XML

性能

(更少的开销、更紧凑的消息)

相对慢(文本解析开销大,HTTP 头部冗余)

适用场景

微服务通信、高性能分布式系统

开放 API、Web 应用、跨平台访问


🔹 2. 为什么 RPC 更快?

RPC 不像 HTTP 需要包装完整的请求,它的通信更轻量,比如:

HTTP 需要发送完整的 URL、请求头等

GET /users/1 HTTP/1.1
Host: example.com
Content-Type: application/json

这里的 GET /users/1 HTTP/1.1 + Host 这些都需要网络传输,冗余信息多

RPC 直接用二进制传输

message GetUserRequest {
  int32 id = 1;
}

这个结构化的数据直接通过二进制流传输,省去了 HTTP 头部的额外开销,性能更高。


🔹 3. 为什么 HTTP 依然常用?

虽然 RPC 更快、更高效,但 HTTP 依然流行,因为:

1️⃣ HTTP 更通用,浏览器、服务器、各种编程语言都支持 HTTP。

2️⃣ REST API 基于 HTTP,适合跨平台访问,比如前端、后端、移动端都可以调用。

3️⃣ HTTP 比 RPC 更容易调试,直接用浏览器或 Postman 就能测试,而 RPC 需要专门的工具。


🔹 4. 实际应用

场景

适合 RPC

适合 HTTP(REST API)

微服务之间通信

✅ gRPC、Thrift

❌ HTTP 开销太大

前端调用后端 API

❌(前端不易用)

✅ REST API 是 Web 开发标准

跨语言系统

✅ gRPC 可支持多种语言

✅ HTTP 也是通用协议

需要高性能的系统

✅ RPC 更快、流量小

❌ HTTP 解析慢,数据冗余多


🔹 5. 总结

📌 HTTP vs RPC 就像这样:

HTTP 像打电话点外卖 📞 🍔:「喂,我要点个汉堡」,服务员(服务器)听到后才处理订单。

RPC 像在家里让助理做饭 🏠 🍳:「帮我做个汉堡」,助理(远程服务器)直接执行,不需要解释那么多。

💡 什么时候用什么?

前端对后端 API:用 HTTP(REST API)。

微服务内部通信:用 RPC(gRPC、Thrift)。

要求极高性能、低延迟:用 RPC。

要兼容各种客户端(Web、移动端):用 HTTP。

如果你在做微服务,RPC 更快更高效,但如果你要开放 API 给别人用,HTTP 更通用。 🚀

完全正确!你抓住了核心逻辑!🎯

📌 1. Socket 是基于 TCP(或 UDP)的

TCP Socket = 你可以直接发送任意数据(字符串、二进制流等),只要发送端和接收端都理解数据格式即可。

HTTP 是基于 TCP 的协议,它只是在Socket 之上加了一些规则(比如请求头、状态码、内容格式等)。

📌 2. 没有 HTTP,你可以直接用 Socket 发送字符串

比如,服务器和客户端可以直接通过 TCP Socket 发送任意内容:

# 服务器端
import socket

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("0.0.0.0", 12345))
server.listen(1)
conn, addr = server.accept()

data = conn.recv(1024)
print(f"收到: {data.decode()}")  # 这里收到的可以是任何字符串

conn.send(b"Hello, Client!")  # 服务器返回任意内容
conn.close()
server.close()
# 客户端
import socket

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(("127.0.0.1", 12345))

client.send(b"Hello, Server!")  # 发送任意字符串
response = client.recv(1024)
print(f"服务器返回: {response.decode()}")

client.close()

👉 这里没有 HTTP,服务器和客户端只是单纯传输字符串。


📌 3. HTTP 让 Socket 通信更有“规则”

假如你要传输网页内容,HTTP 规范规定了:

请求格式(GET / HTTP/1.1\r\nHost: xxx\r\n\r\n)

响应格式(HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<html>...</html>)

所以 HTTP 让 Web 浏览器、服务器能通用解析数据,而不用每个开发者都自己定义数据格式。


📌 4. 你可以用 Socket 直接发 HTTP 请求

HTTP 只是建立在 Socket 之上的一套规则,所以我们也可以手写 HTTP 请求

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(("www.example.com", 80))

# 发送 HTTP 请求(手写)
http_request = b"GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n"
client.send(http_request)

response = client.recv(4096)
print(response.decode())

client.close()

这个请求的本质就是:

1️⃣ 先用 TCP 连接服务器

2️⃣ 然后通过 Socket 发送 HTTP 请求格式的字符串

3️⃣ 服务器返回 HTTP 响应(HTML 页面)


📌 5. 总结

Socket 是底层通信方式(基于 TCP 或 UDP),可以直接传输字符串

HTTP 只是 Socket 之上定义的一套 Web 传输规则

你可以用 Socket 直接传输数据,也可以用它来传输 HTTP

HTTP 让网页内容的传输变得标准化,所以浏览器能正确解析和渲染网页

🎯 你理解得非常好,继续加油!🔥

给我一个rpc的例子帮助我理解,整个流程rpc的过程,以及包的内容的具体变化情况

好的,让我们通过一个具体的例子,一步步来了解 RPC 的工作流程,以及包的内容如何变化。这里我们假设使用 gRPC,这是现代常用的一种 RPC 框架,它使用 Protobuf 作为消息格式,基于 HTTP/2 进行通信,保证了高效的二进制传输。

📜 例子背景:

假设我们有一个 UserService,客户端需要请求远程服务器获取用户的信息。我们用 gRPC 作为 RPC 框架,Protobuf 作为数据格式。

1. 定义服务接口

首先,我们定义一个简单的服务接口,服务端和客户端都使用相同的接口。

Protobuf 文件 (user_service.proto)

syntax = "proto3";

service UserService {
  // 定义一个获取用户信息的RPC方法
  rpc GetUser (UserRequest) returns (UserResponse);
}

message UserRequest {
  string username = 1;
}

message UserResponse {
  string username = 1;
  string name = 2;
  int32 age = 3;
}

2. 生成代码

通过 protoc(Protobuf 编译器)生成 客户端服务端 代码。这样,客户端和服务端都能使用 GetUser 方法,传输 UserRequest 和 UserResponse 类型的数据。

3. 客户端调用远程服务

客户端代码(Python 示例)

import grpc
import user_service_pb2
import user_service_pb2_grpc

def get_user_info(username):
    channel = grpc.insecure_channel('localhost:50051')
    stub = user_service_pb2_grpc.UserServiceStub(channel)
    request = user_service_pb2.UserRequest(username=username)
    response = stub.GetUser(request)
    return response

# 请求用户信息
user_info = get_user_info("Alice")
print(f"User: {user_info.username}, Name: {user_info.name}, Age: {user_info.age}")

4. 服务端处理请求

服务端代码(Python 示例)

from concurrent import futures
import grpc
import user_service_pb2
import user_service_pb2_grpc

class UserService(user_service_pb2_grpc.UserServiceServicer):
    def GetUser(self, request, context):
        if request.username == "Alice":
            return user_service_pb2.UserResponse(username="Alice", name="Alice Wonderland", age=30)
        else:
            return user_service_pb2.UserResponse(username=request.username, name="Unknown", age=0)

def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    user_service_pb2_grpc.add_UserServiceServicer_to_server(UserService(), server)
    server.add_insecure_port('[::]:50051')
    server.start()
    server.wait_for_termination()

if __name__ == '__main__':
    serve()

5. RPC 调用流程

客户端发起请求:

1. 客户端创建一个 UserRequest 对象,封装了 username=“Alice”

2. 通过 gRPC 通道将这个对象发送给服务器,封装成二进制数据

请求包内容:

• 包含 UserRequest 数据:username="Alice"

• 用 Protobuf 编码,转换成二进制格式。

• 包通过 TCP 连接发送到服务端。

服务端接收并处理请求:

3. 服务端收到请求包,解码 Protobuf 格式,将二进制数据还原为 UserRequest。

4. 服务端执行逻辑:查询数据库或从内存获取用户信息,假设 Alice 存在。

5. 服务端创建一个 UserResponse 对象,填充用户数据:username="Alice", name="Alice Wonderland", age=30。

响应包内容:

• 包含 UserResponse 数据:username="Alice", name="Alice Wonderland", age=30

• 同样用 Protobuf 编码,转换成二进制格式。

6. 服务端通过 TCP 连接将响应包返回给客户端。

客户端收到响应:

7. 客户端收到响应包,解码 Protobuf 格式,将二进制数据还原为 UserResponse。

8. 客户端使用解析后的数据,输出用户信息。

6. 整个包的变化过程:

阶段

内容

编码格式

客户端请求

UserRequest { username: "Alice" }

Protobuf(二进制)

TCP 传输

客户端 → 服务端

服务端处理

查询用户信息,构造 UserResponse

Protobuf(二进制)

服务端响应

UserResponse { username: "Alice", name: "Alice Wonderland", age: 30 }

Protobuf(二进制)

客户端接收

解码后的数据:UserResponse

7. 为什么使用 Protobuf 而不是 JSON 或 XML?

高效:Protobuf 是二进制格式,数据更紧凑,解析更快。

强类型:数据结构有明确的定义(如 username、name、age),减少了错误。

跨语言支持:Protobuf 可以在不同编程语言之间高效地传输数据。

自动生成代码:从 .proto 文件自动生成服务端和客户端代码。


总结:

1. RPC 通过封装在 TCP 上,使用高效的二进制格式(Protobuf),让远程调用像本地调用一样简单。

2. 客户端调用远程服务时,封装的请求数据被发送到服务端,服务端处理后返回结果。

3. 与 HTTP 请求相比,RPC 更专注于 远程函数调用,避免了 HTTP 中复杂的协议头和冗余数据,更高效、更简洁

希望这个例子能帮助你更好地理解 RPC 的工作流程!😊

为什么要有channel和stub,直接调用userrequest不久可以了吗?

你的问题非常棒!💡为什么要有 channel 和 stub,而不能直接创建 UserRequest 就完事?

我们一步步拆解,看看 channel 和 stub 的作用,以及 为什么不能直接调用 UserRequest


🔍 为什么需要 channel?

1. channel 是什么?

channel 是客户端和服务器通信的管道,它相当于:

建立 TCP 连接

管理请求和响应的传输

处理负载均衡、重试、超时等功能

👉 简单来说,channel 就是客户端和服务器对话的“电话线”!📞


2. 如果没有 channel,会发生什么?

如果你只创建 UserRequest,但没有 channel,就像你写了一封信(UserRequest),但是没有邮递员(channel)去送信,你的请求根本不会被服务器收到!

request = user_service_pb2.UserRequest(username="Alice")  # 你只创建了请求
print(request)  # 只是个本地对象,服务器并不知道这个请求

这和普通的 Python 函数调用没有区别,你只是创建了一个数据对象,但 没有发送出去,所以服务器端完全不会知道这个请求。


🔍 为什么需要 stub?

1. stub 是什么?

• stub 是一个代理对象,它用来调用远程服务,就像你本地调用一个函数一样。

• stub 通过 channel 把请求发送到服务器,然后接收服务器的返回值

📞 你可以把 stub 理解为一个“电话客服”

• 你(客户端)不需要关心网络传输的细节,直接告诉客服你的需求。

• 客服(stub)会帮你拨通电话(channel),然后把你的需求传达给公司(服务器)。

• 公司(服务器)处理后,通过客服(stub)告诉你答案。


2. 如果没有 stub,会发生什么?

假设你没有 stub,只创建了 UserRequest,但你还是想要发给服务器:

request = user_service_pb2.UserRequest(username="Alice")
channel = grpc.insecure_channel('localhost:50051')

# 没有 stub,如何发送 request?你会发现你无法直接发送

这就像你有了电话线(channel),但你不知道拨号方式(stub),无法让服务器理解你的请求!

👉 stub 其实是 UserService 这个远程服务的“客户端代理”,它知道:

如何把 UserRequest 发送到服务器

如何接收 UserResponse 并解析

如何处理错误(如网络超时、服务器崩溃等)


🌟 整体流程:

💡 带着“打电话”的比喻来看代码,你会更容易理解:

def get_user_info(username):
    # 1️⃣ 拨号 -> 建立通信管道
    channel = grpc.insecure_channel('localhost:50051')

    # 2️⃣ 找客服 -> 让 stub 代理你和服务器对话
    stub = user_service_pb2_grpc.UserServiceStub(channel)

    # 3️⃣ 写信 -> 创建请求对象
    request = user_service_pb2.UserRequest(username=username)

    # 4️⃣ 交给客服 -> 让 stub 发送请求,等待服务器的返回
    response = stub.GetUser(request)

    # 5️⃣ 得到服务器回复
    return response

✅ 你再对照一下打电话的比喻:

步骤

代码

类比

拨号

channel = grpc.insecure_channel('localhost:50051')

连接服务器,相当于拿起电话 📞

找客服

stub = user_service_pb2_grpc.UserServiceStub(channel)

创建代理,相当于拨通客服 👩‍💼

写信

request = user_service_pb2.UserRequest(username="Alice")

创建请求,相当于告诉客服你想查谁的信息

交给客服

response = stub.GetUser(request)

让 stub 发送请求,相当于客服去查数据库

收到回复

return response

收到数据,相当于客服告诉你查询结果


❌ 为什么不能直接调用 UserRequest?

如果你只写:

request = user_service_pb2.UserRequest(username="Alice")

你只是创建了一个普通的 Python 对象,它不会自动发给服务器。你还需要:

1. 通过 channel 连接服务器

2. 通过 stub 调用远程函数

3. 服务器才能收到请求、处理、返回数据


🎯 总结

✅ channel 是“电话线”,负责和服务器建立通信。

✅ stub 是“客服”,帮你把请求发到远程服务器,并拿到结果。

✅ UserRequest 只是请求内容,它自己不会发给服务器,必须通过 stub 才能真正发送

这样设计的好处:

• 你可以像调用本地函数一样调用远程服务!

• 你不需要手写复杂的网络代码,RPC 框架会自动处理底层细节。

希望这样解释后,你会觉得 channel 和 stub 是不可或缺的部分,而不是多余的设计!😆🎉


http://www.kler.cn/a/589938.html

相关文章:

  • 图论part3|101.孤岛的总面积、沉没孤岛、417. 太平洋大西洋水流问题
  • Vue3项目匹配PC端和移动端---一套组件
  • MATLAB语言的编程竞赛
  • 沉浸式vr大空间打造,打造超真实的虚拟体验
  • 【教学类-43-25】20240311 数独3宫格的所有可能(图片版 12套样式,空1格-空8格,每套510张,共6120小图)
  • 配置 VSCode 的 C# 开发环境
  • Matlab 基于专家pid控制的时滞系统
  • Tree of Thought Prompting(思维树提示)
  • 如何在 K8s 内部实现安全的网络隔离?
  • 掌握Python项目的依赖管理:利用`venv`与`conda`高效创建虚拟环境
  • 深度解析ECharts.js:构建现代化数据可视化的利器
  • c++图论(一)之图论的起源和图的概念
  • 【MySQL】MySQL审计工具Audit Plugin安装使用
  • 工作记录 2017-01-25
  • 树莓派上的 TensorFlow Lite:从零开始的摄像头图像识别
  • python-数据结构汇总,树图、代码讲解(字符串、数组、字典、集合、元组)
  • 5分钟快速申请一个EDU教育邮箱
  • Qt选择文件路径,并写入文件
  • 华为hcia——Datacom实验指南——Ping和Tracert的工作原理
  • 【自学笔记】Solidity基础知识点总览-持续更新