RPC 怎么用

SimpleMaxR Lv2

RPC 与 HTTP 的区别

在微服务架构中,RPC(远程过程调用)和 HTTP 是两种常见的通信协议,它们在接口定义和使用方式上有显著差异。

接口定义与约束

RPC 通过 Proto 文件(Protocol Buffers)严格约束接口行为。在 Proto 文件中,开发者可以精确定义:

  • 接口的参数类型和结构
  • 返回值的具体格式
  • 方法的命名规范

相比之下,HTTP 协议本身对接口行为没有强制性约束。服务提供方和调用方需要:

  • 自行约定接口规范
  • 手动实现错误处理逻辑
  • 维护接口文档和通信协议

RPC 实现:以 Go 语言 gRPC 为例

服务端实现步骤

  1. 定义 Protobuf 服务接口
1
2
3
4
service OrderService {
rpc CreateOrder(CreateOrderRequest) returns (CreateOrderResponse) {}
rpc GetOrder(GetOrderRequest) returns (GetOrderResponse) {}
}
  1. 实现服务接口
1
2
3
4
5
6
7
8
9
10
11
12
type OrdersGrpcHandler struct {
orderService types.OrderService
}

func (h OrdersGrpcHandler) CreateOrder(ctx context.Context, req *orders.CreateOrderRequest) (*orders.CreateOrderResponse, error) {
// 业务逻辑实现
order, err := h.orderService.Create(req)
if err != nil {
return nil, status.Errorf(codes.Internal, "创建订单失败: %v", err)
}
return &orders.CreateOrderResponse{OrderId: order.ID}, nil
}
  1. 注册 gRPC 服务
1
2
3
4
5
6
func NewGrpcOrdersService(grpcServer *grpc.Server, orderService types.OrderService) {
handler := &OrdersGrpcHandler{
orderService: orderService,
}
orders.RegisterOrderServiceServer(grpcServer, handler)
}
  1. 启动 gRPC 服务器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
func (s *gRPCServer) Run() error {
listener, err := net.Listen("tcp", s.addr)
if err != nil {
return fmt.Errorf("监听失败: %v", err)
}

grpcServer := grpc.NewServer()
orderService := service.NewOrderService()

NewGrpcOrdersService(grpcServer, orderService)

log.Printf("gRPC 服务器启动,监听地址:%s", s.addr)
return grpcServer.Serve(listener)
}

客户端实现步骤

  1. 创建 gRPC 连接
1
2
3
4
5
6
7
8
9
10
11
func NewGRPCClient(addr string) (*grpc.ClientConn, error) {
conn, err := grpc.Dial(addr,
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithBlock(),
grpc.WithTimeout(5*time.Second),
)
if err != nil {
return nil, fmt.Errorf("连接服务器失败: %v", err)
}
return conn, nil
}
  1. 调用远程方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
func (s *httpServer) createOrder() error {
conn, err := NewGRPCClient(":9000")
if err != nil {
return err
}
defer conn.Close()

client := orders.NewOrderServiceClient(conn)

resp, err := client.CreateOrder(context.Background(), &orders.CreateOrderRequest{
CustomerId: "001",
ProductId: "001",
Quantity: 1,
})
if err != nil {
return fmt.Errorf("创建订单失败: %v", err)
}

log.Printf("订单创建成功,订单ID:%s", resp.OrderId)
return nil
}

RPC 的关键优势

  1. 强类型接口:通过 Proto 文件定义严格的接口契约
  2. 高性能:使用二进制传输,通信开销低
  3. 跨语言支持:可以生成多种编程语言的客户端和服务端代码
  4. 内置服务发现和负载均衡
  • Title: RPC 怎么用
  • Author: SimpleMaxR
  • Created at : 2024-12-05 13:40:06
  • Updated at : 2025-02-11 12:15:45
  • Link: https://www.hgzre.tech/2024/12/05/RPC-怎么用/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments