mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
495 字
1 分钟
gRPC:高性能 RPC 框架详解
2022-12-25

前言#

gRPC 是 Google 开源的高性能 RPC 框架,基于 HTTP/2 传输层和 Protocol Buffers 序列化协议。本章详解 gRPC 的架构、四种 RPC 类型和实际应用。

一、gRPC 概述#

1.1 核心特性#

特性说明
高性能基于 HTTP/2,多路复用
跨语言12+ 语言支持
紧凑Protocol Buffers 序列化
流式支持服务端/客户端/双向流
生态丰富负载均衡、安全、追踪

1.2 gRPC 架构全景#

graph TB subgraph "应用层" A[Client Code] --> B[Stub] C[Service Impl] --> D[Server] end subgraph "gRPC 层" B --> E[Channel] D --> F[Server Transport] E --> G[Serializer] F --> G G --> H[Flow Control] end subgraph "传输层" H --> I[HTTP/2] I --> J[TLS] end subgraph "网络层" J --> K[TCP] end style A fill:#e1f5fe style C fill:#e1f5fe style I fill:#fff3e0 style J fill:#fce4ec

gRPC 以 HTTP/2 为传输层,继承其二进制分帧、多路复用和流控特性。相比 WebSocket 协议 的双向消息通道,gRPC 提供更强的类型安全和代码生成能力。

1.2 gRPC vs REST#

特性RESTgRPC
协议HTTP/1.1-2HTTP/2
序列化JSON/XMLProtocol Buffers
传输效率
代码生成OpenAPI/Swagger原生 Proto 生成
流式支持SSE/轮询原生支持
浏览器支持原生需要 grpc-web

二、Protocol Buffers#

2.1 定义服务#

syntax = "proto3";
package user;
service UserService {
// unary RPC
rpc GetUser(GetUserRequest) returns (User);
// 服务端流式 RPC
rpc ListUsers(ListRequest) returns (stream User);
// 客户端流式 RPC
rpc CreateUsers(stream CreateRequest) returns (CreateResponse);
// 双向流式 RPC
rpc Chat(stream Message) returns (stream Message);
}
message User {
string id = 1;
string name = 2;
string email = 3;
}

2.2 数据类型映射#

// Proto 类型 -> Python/Go/TypeScript
int32 -> int/number
int64 -> int/Long
float -> float/number
double -> double/number
bool -> bool/boolean
string -> str/string
bytes -> bytes/Uint8Array
repeated -> list/array
map -> dict/object

三、HTTP/2 传输层#

3.1 HTTP/2 特性#

graph TB A["gRPC"] --> B["HTTP/2"] B --> C["多路复用"] B --> D["头部压缩"] B --> E["流控制"] B --> F["二进制帧"] subgraph "二进制帧" G["HEADERS Frame"] H["DATA Frame" ]

3.2 帧格式#

┌─────────────────────────────────────┐
│ Length (24-bit) │
├─────────────────────────────────────┤
│ Type (8-bit) │ Flags (8-bit) │
├─────────────────────────────────────┤
│ Stream ID (31-bit) │
├─────────────────────────────────────┤
│ Payload │
└─────────────────────────────────────┘
# gRPC 帧类型
# 0x00: DATA
# 0x01: HEADERS
# 0x04: RESET_STREAM
# 0x07: GOAWAY

四、RPC 类型#

4.1 四种模式对比#

graph LR subgraph "Unary RPC" A1[Client] -->|Request| B1[Server] B1 -->|Response| A1 end subgraph "Server Streaming" A2[Client] -->|Request| B2[Server] B2 -->|Stream| A2 B2 -->|Stream| A2 B2 -->|Stream| A2 end subgraph "Client Streaming" A3[Client] -->|Stream| B3[Server] A3 -->|Stream| B3 A3 -->|Stream| B3 B3 -->|Response| A3 end subgraph "Bidirectional Streaming" A4[Client] <-->|Stream| B4[Server] end

4.2 Unary RPC(一元 RPC)#

sequenceDiagram participant C as Client participant S as Server C->>S: GETUSER REQUEST Note over S: 处理请求 S->>C: USER RESPONSE
# Python 服务端
class UserServicer(user_pb2_grpc.UserServiceServicer):
def GetUser(self, request, context):
return user_pb2.User(
id=request.id,
name="张三",
email="zhangsan@example.com"
)

4.3 服务端流式 RPC#

# 服务端流
def ListUsers(self, request, context):
users = db.query_users(limit=request.limit)
for user in users:
yield user # 流式返回

4.3 客户端流式 RPC#

# 客户端流
def CreateUsers(self, request_iterator, context):
created = []
for request in request_iterator:
user = db.create(request)
created.append(user)
return CreateResponse(users=created)

4.4 双向流式 RPC#

# 双向流
async def Chat(self, request_iterator, context):
async for message in request_iterator:
reply = await process_message(message)
yield reply

五、元数据和拦截器#

5.1 元数据#

# 客户端发送元数据
metadata = [("authorization", "Bearer token")]
response = stub.GetUser(request, metadata=metadata)
# 服务端读取元数据
def GetUser(self, request, context):
token = context.invocation_metadata()
auth = dict(token).get("authorization")
if not auth:
context.abort(grpc.StatusCode.UNAUTHENTICATED)

5.2 拦截器#

# 服务端拦截器
class AuthInterceptor(grpc.ServerInterceptor):
def intercept_service(self, continuation, handler_call_details):
meta = dict(handler_call_details.invocation_metadata)
if not meta.get("authorization"):
return grpc.unary_unary_rpc_method_handler(
lambda *args: context.abort(grpc.StatusCode.UNAUTHENTICATED)
)
return continuation(handler_call_details)

六、错误处理#

6.1 状态码#

状态码说明
OK成功
INVALID_ARGUMENT参数错误
NOT_FOUND资源不存在
UNAUTHENTICATED未认证
PERMISSION_DENIED无权限
RESOURCE_EXHAUSTED资源耗尽
INTERNAL内部错误

6.2 错误传播#

# 服务端返回错误
context.abort(grpc.StatusCode.NOT_FOUND, "User not found")
# 客户端捕获
try:
response = stub.GetUser(request)
except grpc.RpcError as e:
print(f"错误: {e.code()} - {e.details()}")

七、gRPC-Web#

7.1 架构#

graph LR A["Browser"] --> B["gRPC-Web Proxy"] B --> C["gRPC Backend"] subgraph "协议转换" B --> D["HTTP/1.1"] B --> E["HTTP/2"] end

7.2 客户端示例#

import { grpc } from "@improbable-eng/grpc-web";
// 使用 grpc-web 调用
const client = grpc.invoke(UserService.GetUser, {
request: request,
host: "https://api.example.com",
onMessage: user => {
console.log(user);
},
onEnd: (code, message) => {},
});

八、安全#

8.1 TLS 传输加密#

# 服务端配置
server:
credentials: grpc.ssl_server_credentials(
server_cert,
server_key
)

8.2 认证#

# JWT 认证
class JWTInterceptor(grpc.ServerInterceptor):
def intercept_service(self, continuation, details):
meta = dict(details.invocation_metadata())
token = meta.get("authorization", "").replace("Bearer ", "")
if verify_jwt(token):
return continuation(details)
return lambda *args: abort(UNAUTHENTICATED)

九、负载均衡#

9.1 客户端负载均衡#

# gRPC 负载均衡策略
channel = grpc.insecure_channel(
"lb:///user-service",
options=[
("grpc.load_balancing_policy", "round_robin")
]
)

9.2 服务端负载均衡#

graph TB A["Client"] --> B["Load Balancer"] B --> C["Server 1"] B --> D["Server 2"] B --> E["Server 3"]

十、总结#

gRPC 以 HTTP/2 为传输层、Protocol Buffers 为序列化协议,提供了高性能、跨语言的 RPC 能力。掌握四种 RPC 类型、元数据处理和拦截器机制,是构建微服务通信层的关键技能。

支持与分享

如果这篇文章对你有帮助,欢迎支持作者或分享给更多人

gRPC:高性能 RPC 框架详解
https://blog.souloss.com/posts/web/grpc-protocol/
作者
Souloss
发布于
2022-12-25
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

相关文章 智能推荐