QGrpcClientInterceptor 缓存示例
缓存拦截器
缓存拦截器可以是提高您的 Qt GRPC 连接性能的多用途工具。通过创建一个自定义拦截器,您可以设定缓存行为以满足应用程序的具体要求。
创建缓存拦截器
为了创建缓存拦截器,您需要从 QGrpcClientInterceptor 派生一个子类,并覆盖适当的拦截方法以添加缓存功能。
先决条件
为了确定我们可以处理哪些类型的拦截器,让我们假设我们的 .proto 文件是
syntax = "proto3"; message SimpleStringMessage { string testFieldString = 6; } service TestService { rpc testMethod(SimpleStringMessage) returns (SimpleStringMessage) {} rpc testMethodServerStream(SimpleStringMessage) returns (stream SimpleStringMessage) {} }
我们还将快速确定 MyCacheStorage
API 的样子
insert()
方法,可以向缓存中插入一个新的条目(在我们的情况下,条目将以 QString 存储为)insert_or_append()
方法,类似于insert()
,但是在method
和service
的条目已存在且尚未终结的情况下,它会追加数据 - 这将被用于缓存流式响应。find()
,这个方法可以根据method
和service
关键字找到条目。finalize()
,这个方法将终结缓存中的条目,对于流用例,调用该方法意味着完整的响应已经缓存。
缓存拦截器实现
这里是一个简单的缓存拦截器的示例
class CachingInterceptor : public QGrpcClientInterceptor { protected: void interceptCall(std::shared_ptr<QGrpcChannelOperation> operation, std::shared_ptr<QGrpcCallReply> response, QGrpcInterceptorContinuation<QGrpcCallReply> &continuation) override { // Intercept the response QObject::connect(response.get(), &QGrpcCallReply::finished, this, [operation, response] { SimpleStringMessage mess = response->read<SimpleStringMessage>(); cache.insert(operation->method(), operation->service(), mess.testFieldString()); }); // Deserialize the request SimpleStringMessage deserializedArg; if (!operation->serializer()->deserialize(&deserializedArg, operation->arg())) { qError() << "Deserialization of arg failed."; return; } std::optional<QString> cachedStr = cache.find(operation->method(), operation->service(), deserializedArg); if (cachedStr) { // Serialize cached response SimpleStringMessage val; val.setTestFieldString(cachedStr); const auto serializedValue = operation->serializer()->serialize<SimpleStringMessage>(&val); emit operation->dataReady(serializedValue); emit operation->finished(); // Set server metadata cached field auto metadata = operation->serverMetadata(); metadata.insert({ "cached", "true" }); operation->setServerMetadata(metadata); return; } continuation(std::move(response), operation); } void interceptServerStream(std::shared_ptr<QGrpcChannelOperation> operation, std::shared_ptr<QGrpcServerStream> stream, QGrpcInterceptorContinuation<QGrpcServerStream> &continuation) override { // Intercept the response QObject::connect(stream.get(), &QGrpcServerStream::messageReceived, this, [operation, stream] { SimpleStringMessage mess = stream->read<SimpleStringMessage>(); cache.insert_or_append(operation->method(), operation->service(), mess.testFieldString()); }); QObject::connect(stream.get(), &QGrpcServerStream::finished, this, [operation] { cache.finalize(operation->method(), operation->service()); }); // Deserialize the request SimpleStringMessage deserializedArg; if (!operation->serializer()->deserialize(&deserializedArg, operation->arg())) { qError() << "Deserialization of arg failed."; return; } std::optional<QString> cachedStr = cache.find(operation->method(), operation->service(), deserializedArg); if (cachedStr) { // Serialize cached response SimpleStringMessage val; val.setTestFieldString(cachedStr); const auto serializedValue = operation->serializer()->serialize<SimpleStringMessage>(&val); emit operation->dataReady(serializedValue); emit operation->finished(); // Set server metadata cached field auto metadata = operation->serverMetadata(); metadata.insert({ "cached", "true" }); operation->setServerMetadata(metadata); return; } continuation(std::move(response), operation); } MyCacheStorage<QString> cache; };
缓存拦截器中的 interceptCall()
和 interceptServerStream()
方法都拦截了 Qt GRPC 调用和流,并为响应实现了缓存机制。两者都建立连接来处理传入的消息并尝试反序列化请求参数。两种方法都检查是否有缓存的响应,如果找到,则会进行序列化并发出正确的信号以设置响应数据。如果响应已在缓存中找到,则将服务器元数据键 cached
设置为 true
。
它们之间的主要区别在于它们处理服务器流交互和缓存终结的方式:interceptCall()
主要依赖于响应的完成信号进行缓存,而 interceptServerStream()
使用服务器流的 messageReceived 和 finished 信号的连接,以便全面处理流式交互和缓存终结,这样,只有当整个流都被缓存时,interceptServerStream()
才会返回缓存的响应。
注册缓存拦截器
接下来,您需要将缓存拦截器注册到 QGrpcClientInterceptorManager。这确保了它成为拦截链的一部分。
QGrpcClientInterceptorManager manager; auto cachingInterceptor = std::make_shared<CachingInterceptor>(); manager.registerInterceptor(cachingInterceptor);
© 2024 Qt公司有限公司。本文档中包含的文档贡献归其各自所有者所有。本提供的文档遵守自由软件基金会发布的自由文档许可协议版本1.3的条款。Qt及其相关商标是芬兰的Qt公司及/或其他国家的商标。所有其他商标均为其各自所有者的财产。