gRPC 四模式之 一元RPC模式

简介: gRPC 四模式之 一元RPC模式

一元RPC模式

一元 RPC 模式也被称为简单 RPC 模式。在该模式中,当客户端调用服务器端的远程方法时,客户端发送请求至服务器端并获得一个响应,与响应一起发送的还有状态细节以及 trailer 元数据(这部分不是默认发送的,需要自己实现)


[[Pasted image 20231115104223.png]]

使用场景

单次通讯,传输数据包的时候,返回收到应答。

在一元RPC模式中,状态细节和trailer元数据并不是默认就有的,它们是由服务器端根据需要添加的。状态细节通常包含了关于RPC调用的状态信息,例如是否成功,如果失败了具体是什么原因等。而trailer元数据则是一些额外的信息,例如调用的时间,服务器的处理时间等。

具体来说,状态细节和trailer元数据的形式取决于你使用的RPC框架和编程语言。在gRPC中,状态细节和trailer元数据通常以键值对的形式存在,键和值都是字符串。例如,你可能会看到这样的状态细节:{"status": "success"},或者这样的trailer元数据:{"processing-time": "123ms"}。


请注意,这只是一个例子,实际的状态细节和trailer元数据会根据你的应用需求和服务器的实现来定。

在gRPC中,服务器可以通过grpc::ServerContext对象来设置trailer元数据。这些元数据在RPC调用结束时发送给客户端。以下是一个C++的示例,展示了如何设置和发送trailer元数据:

#include <grpcpp/grpcpp.h>
#include "your_service.grpc.pb.h"  // 替换为你的服务的protobuf头文件

class YourServiceImpl final : public YourService::Service {
  grpc::Status YourMethod(grpc::ServerContext* context, const YourRequest* request,
                          YourResponse* reply) override {
    // 处理你的方法逻辑...

    // 在RPC调用结束时,设置trailer元数据
    context->AddTrailingMetadata("processing-time", "123ms");

    return grpc::Status::OK;
  }
};

在这个例子中,服务器在处理完YourMethod方法后,通过AddTrailingMetadata方法添加了一个名为"processing-time"的trailer元数据,值为"123ms"。这个元数据会在RPC调用结束时发送给客户端。

至于状态细节,它通常包含在返回的grpc::Status对象中。例如,如果你的方法出现了错误,你可以返回一个包含错误信息的grpc::Status对象:

return grpc::Status(grpc::StatusCode::INTERNAL, "An internal error occurred");

在这个例子中,服务器返回了一个状态码为INTERNALgrpc::Status对象,状态细节为"An internal error occurred"。这个状态细节会被发送给客户端,客户端可以通过检查返回的grpc::Status对象来获取这个信息。

在服务端返回时,设置多个状态和元数据

在gRPC中,你可以通过多次调用AddTrailingMetadata方法来添加多个trailer元数据。每次调用都会添加一个新的键值对。例如:

std::string status_detail = R"({
  "error": "An internal error occurred",
  "error_code": 123,
  "error_info": "Some additional info"
})";
return grpc::Status(grpc::StatusCode::INTERNAL, status_detail);

在这个例子中,服务器添加了三个trailer元数据:“processing-time”,“server-id"和"timestamp”。


至于状态细节,gRPC的grpc::Status对象只支持设置一个状态细节。如果你需要传递多个状态信息,你可以将它们编码为一个字符串,例如JSON格式的字符串,然后设置为状态细节。例如:

std::string status_detail = R"({
  "error": "An internal error occurred",
  "error_code": 123,
  "error_info": "Some additional info"
})";
return grpc::Status(grpc::StatusCode::INTERNAL, status_detail);

在这个例子中,服务器将多个状态信息编码为一个JSON格式的字符串,然后设置为状态细节。客户端可以解析这个字符串来获取这些状态信息。

客户端接取trailer元数据

客户端可以接收到服务端发送的trailer元数据和状态细节,并根据需要进行处理。

在gRPC中,客户端可以通过grpc::ClientContext对象来获取trailer元数据。例如:

grpc::ClientContext context;
YourResponse response;
grpc::Status status = stub->YourMethod(&context, request, &response);

if (!status.ok()) {
  std::cout << "RPC failed with code " << status.error_code()
            << ", message: " << status.error_message() << std::endl;

  // 获取trailer元数据
  auto trailers = context.GetServerTrailingMetadata();
  for (const auto& kv : trailers) {
    std::cout << "Trailer key: " << kv.first << ", value: " << kv.second << std::endl;
  }
}

在这个例子中,客户端首先调用YourMethod方法并获取返回的grpc::Status对象。如果RPC调用失败,客户端会打印出错误信息,然后通过GetServerTrailingMetadata方法获取trailer元数据并打印出来。

至于状态细节,客户端可以通过grpc::Status对象的error_message方法来获取。例如:

std::cout << "Status detail: " << status.error_message() << std::endl;

在这个例子中,客户端打印出了状态细节。如果状态细节是一个编码的字符串,例如JSON格式的字符串,客户端可以解析这个字符串来获取状态信息。


客户端发送 header 元数据、状态细节

在gRPC中,客户端也可以设置和发送header元数据和状态细节。这可以通过grpc::ClientContext对象来实现。

首先,客户端可以通过AddMetadata方法来设置header元数据:

grpc::ClientContext context;
context.AddMetadata("client-id", "client-001");
context.AddMetadata("timestamp", "2022-01-01T00:00:00Z");

然后,客户端可以通过TryCancel方法来取消RPC调用,并通过set_cancel_message方法来设置状态细节:

context.TryCancel();
context.set_cancel_message("The request was cancelled by the client");

在这个例子中,客户端取消了RPC调用,并设置了状态细节为"The request was cancelled by the client"。


请注意,这只是一个例子,实际的使用方式会根据你的应用需求和gRPC的API来定。在gRPC中,客户端也可以设置和发送header元数据和状态细节。这可以通过grpc::ClientContext对象来实现。


首先,客户端可以通过AddMetadata方法来设置header元数据:

grpc::ClientContext context;
context.AddMetadata("client-id", "client-001");
context.AddMetadata("timestamp", "2022-01-01T00:00:00Z");

在这个例子中,客户端设置了两个header元数据:“client-id"和"timestamp”。

然后,客户端可以通过TryCancel方法来取消RPC调用,并通过set_cancel_message方法来设置状态细节:

context.TryCancel();
context.set_cancel_message("The request was cancelled by the client");

在这个例子中,客户端取消了RPC调用,并设置了状态细节为"The request was cancelled by the client"。

补充:

取消RPC调用通常是因为客户端不再需要RPC的结果,或者因为某些条件已经改变,使得继续等待响应变得没有意义。取消可以用于各种情况,例如:


  1. 超时: 如果一个RPC调用超过了预定的时间还没有响应,客户端可能会选择取消它,以避免无限期地等待。
  2. 用户干预: 如果用户发起了一个操作,然后在操作完成前改变了主意,客户端应用可能需要取消相关的RPC调用。
  3. 资源优化: 如果客户端已经发送了多个RPC调用,但是得到了足够的信息来完成任务,它可能会取消剩余的调用,以节省服务器资源和网络带宽。
  4. 错误恢复: 如果在RPC调用过程中发生了错误,客户端可能会取消该调用,并尝试其他恢复策略。
  5. 依赖关系变化: 如果RPC调用的结果依赖于某些条件,而这些条件在调用过程中发生了变化,客户端可能需要取消调用。

取消RPC调用是异步编程中常见的一种模式,它允许应用程序更有效地管理资源和用户交互。在gRPC中,客户端可以通过调用grpc::ClientContext的TryCancel方法来取消RPC调用。服务端可以通过检查grpc::ServerContext::IsCancelled来响应取消事件,并及时停止处理。


分享一个有趣的 学习链接:https://xxetb.xet.tech/s/HY8za



目录
相关文章
|
9天前
|
存储 C++
gRPC 四模式之 双向流RPC模式
gRPC 四模式之 双向流RPC模式
15 0
|
9天前
|
安全 C++
gRPC 四模式之 客户端流RPC模式
gRPC 四模式之 客户端流RPC模式
12 0
|
9天前
|
C++
gRPC 四模式之 服务器端流RPC模式
gRPC 四模式之 服务器端流RPC模式
16 0
|
2月前
|
负载均衡 Dubbo Java
Dubbo 3.x:探索阿里巴巴的开源RPC框架新技术
随着微服务架构的兴起,远程过程调用(RPC)框架成为了关键组件。Dubbo,作为阿里巴巴的开源RPC框架,已经演进到了3.x版本,带来了许多新特性和技术改进。本文将探讨Dubbo 3.x中的一些最新技术,包括服务注册与发现、负载均衡、服务治理等,并通过代码示例展示其使用方式。
138 9
|
2月前
|
设计模式 负载均衡 网络协议
【分布式技术专题】「分布式技术架构」实践见真知,手把手教你如何实现一个属于自己的RPC框架(架构技术引导篇)
【分布式技术专题】「分布式技术架构」实践见真知,手把手教你如何实现一个属于自己的RPC框架(架构技术引导篇)
88 0
|
10月前
|
消息中间件 负载均衡 Dubbo
如何自己设计一个类似Dubbo的RPC框架?
如何自己设计一个类似Dubbo的RPC框架?
72 0
|
2月前
|
Dubbo Java 应用服务中间件
Rpc编程系列文章第三篇:Hessian RPC一个老的RPC框架
Rpc编程系列文章第三篇:Hessian RPC一个老的RPC框架
|
4天前
|
存储 缓存 Linux
【实战指南】嵌入式RPC框架设计实践:六大核心类构建高效RPC框架
在先前的文章基础上,本文讨论如何通过分层封装提升一个针对嵌入式Linux的RPC框架的易用性。设计包括自动服务注册、高性能通信、泛型序列化和简洁API。框架分为6个关键类:BindingHub、SharedRingBuffer、Parcel、Binder、IBinder和BindInterface。BindingHub负责服务注册,SharedRingBuffer实现高效数据传输,Parcel处理序列化,而Binder和IBinder分别用于服务端和客户端交互。BindInterface提供简单的初始化接口,简化应用集成。测试案例展示了客户端和服务端的交互,验证了RPC功能的有效性。
|
9天前
|
分布式计算 资源调度 网络协议
分布式系统详解--框架(Hadoop--RPC协议)
分布式系统详解--框架(Hadoop--RPC协议)
13 0
|
2月前
|
Dubbo 网络协议 Java
性能基础之常见RPC框架浅析
【4月更文挑战第23天】性能基础之常见RPC框架浅析
62 1
性能基础之常见RPC框架浅析