Rpc服务消费者(Rpc服务调用者)实现思路

Rpc服务消费者(Rpc服务调用者)实现思路

前面几节说到Rpc消费者主要通过UserServiceRPc_Stub这个protobuf帮我们生成的类来实现,上代码回顾一下

class UserServiceRpc_Stub : public UserServiceRpc {public:UserServiceRpc_Stub(::PROTOBUF_NAMESPACE_ID::RpcChannel* channel);UserServiceRpc_Stub(::PROTOBUF_NAMESPACE_ID::RpcChannel* channel,::PROTOBUF_NAMESPACE_ID::Service::ChannelOwnership ownership);~UserServiceRpc_Stub();inline ::PROTOBUF_NAMESPACE_ID::RpcChannel* channel() { return channel_; }// implements UserServiceRpc ------------------------------------------void Login(::PROTOBUF_NAMESPACE_ID::RpcController* controller,const ::fixbug::LoginRequest* request,::fixbug::LoginResponse* response,::google::protobuf::Closure* done);private:::PROTOBUF_NAMESPACE_ID::RpcChannel* channel_;bool owns_channel_;GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UserServiceRpc_Stub);//xxx.pb.cc
void UserServiceRpc_Stub::Login(::PROTOBUF_NAMESPACE_ID::RpcController* controller,const ::fixbug::LoginRequest* request,::fixbug::LoginResponse* response,::google::protobuf::Closure* done) {channel_->CallMethod(descriptor()->method(0),controller, request, response, done);
}
};

UserServiceRpc_Stub可以看做是一个给用户提供rpc远程调用的代理类,这里面有rpcclient和rpcserver约定好的远程方法Login,Login方法是调用了一个channel_的callMethod方法,那么联想到其他服务方法应该也是底层调用了这个函数(底层根据method的索引来区分具体的method),那么这个方法具体如何工作的?这个类需要接受一个RpcChannel类作为参数,看看RpcChannel类:

class PROTOBUF_EXPORT RpcChannel {public:inline RpcChannel() {}virtual ~RpcChannel();virtual void CallMethod(const MethodDescriptor* method,RpcController* controller, const Message* request,Message* response, Closure* done) = 0;private:GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RpcChannel);
};

很简单就是一个抽象类,有个纯虚函数CallMethod需要rpc_stub来实现。要实现rpcService_Stub,显然先需要具体化一个MyRpcChannel类,这个MyRpcChannel类继承自RpcChannel 类,最后通过多态调用在callMethod方法里面完成rpc远程调用的过程。那么具体怎么进行?

void UserServiceRpc_Stub::Login(::PROTOBUF_NAMESPACE_ID::RpcController* controller,const ::fixbug::LoginRequest* request,::fixbug::LoginResponse* response,::google::protobuf::Closure* done) {channel_->CallMethod(descriptor()->method(0),controller, request, response, done);
}

Login方法接收4个参数,第一个controller先不用管,显然第四个参数done也不需要管因为作为rpc消费者不需要在将什么结果反馈给rpc提供者。那么就只需要传递两个参数,request即是rpc_stub封装用户端请求的参数,response即是在远程调用完成之后rpcserver帮rpcclient填写的,然后rpc_stub只需要反序列化出来结果反馈给用户即可,那么基本实现思路就有了:
step1实现MyRpcchannel类,继承自RpcChannel ,并重写其CallMethod方法,CallMethod实现有如下几小步
step1.1:获取具体服务名和方法名以及将用户传入的request序列化,最终封装成一个字符流(header_size + service_name method_name args_size + args_str)

//获取服务名和方法名const google::protobuf::ServiceDescriptor* service = method->service();std::string service_name = service->name();   //service_namestd::string method_name = method->name();     //method_name//获取参数的序列化字符串长度 args_sizestd::string args_str;uint32_t args_size = 0;if(request->SerializeToString(&args_str)){args_size = args_str.size();}else{std::cout << "request serlize error" << std::endl;return;}//定义rpc请求的HeaderRpcHeader rpcHeader;rpcHeader.set_service_name(service_name);rpcHeader.set_method_name(method_name);rpcHeader.set_args_size(args_size);std::string rpc_header_str;uint32_t header_size = 0;if(rpcHeader.SerializeToString(&rpc_header_str)){header_size = rpc_header_str.size();}else{std::cout << "rpcheader_str serlize error" << std::endl;return;}//组织待发送的rpc请求的字符串std::string send_rpc_str;send_rpc_str.insert(0, std::string((char*)&header_size, 4)); // header_sizesend_rpc_str += rpc_header_str; //rpcHeadersend_rpc_str += args_str; //args

step1.2:连接远程rpcServer服务器(可以是不同机器上的不同进程,也可以是在不同的机器上)
connect to rpcServer
step1.2:将封装的rpc字符流通过socket发送给RpcServer(远程rpc调用请求)
send----->send_rpc_str
step1.3:阻塞等待rpcServer的响应,并将响应饭序列化出来给用户端。
recv------>recv_buf

//反序列化rpc调用的响应数据std::string response_str(recv_buf, 0, recv_size);if(!response->ParseFromString(response_str)){std::cout<< "parse error ! response_str:" << response_str << std::endl;return;}

step2:用户创建UserServiceRpc_Stub类对象,并将MyRpcchannel实例对象传入进行构造。最后通过UserServiceRpc_Stub对象实例调用对应的rpc服务。(实际调用的就是上述实现的CallMethod方法)

	fixbug::UserServiceRpc_Stub stub(new MyRpcChannel());//rpc方法的请求参数fixbug::LoginRequest request;request.set_name("zhang san");request.set_pwd("123");//rpc方法的响应,同步的rpc调用过程fixbug::LoginResponse response;stub.Login(nullptr, &request, &response, nullptr);   //RpcChannel-->Rpchannel::callMethod 集中来做所有rpc方法调用的参数序列化和网络发送

step3:处理阻塞的响应消息response做相应的业务处理。

 //一次rpc调用完成,读调用的结果if(0 == response.result().errcode()){std::cout << "rpc login response success: " << response.success() << std::endl;}else{std::cout << "rpc login error msg : " << response.result().errmsg() << std::endl;}

至此RpcConsumer基本实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/16952.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

langchain-ChatGLM源码阅读:webui.py

样式定制 使用gradio设置页面的视觉组件和交互逻辑 import gradio as gr import shutilfrom chains.local_doc_qa import LocalDocQA from configs.model_config import * import nltk import models.shared as shared from models.loader.args import parser from models.load…

Android Layout大点兵

原文链接 Android Layout大点兵 智能手机催生了移动互联时代&#xff0c;现如今移动应用越来越成为最为核心的终端。而GUI页面是移动互联终端的标配&#xff0c;做好一个GUI页面&#xff0c;是非常重要的&#xff0c;能极大的提升用户体验和用户满意度。安桌生态&#xff0c;自…

【转】ECC加密算法简介

原文链接&#xff1a;https://blog.csdn.net/xuanli4845/article/details/115907886 ECC全称为“Ellipse Curve Ctyptography”&#xff0c;是一种基于椭圆曲线数学的公开密钥加密算法。椭圆曲线在密码学中的使用是在1985年由Neal Koblitz和Victor Miller分别独立提出的。 与…

kotlin 编写一个简单的天气预报app(五)增加forcast接口并显示

参考资料 OpenWeatherMap提供了一个/forecast接口&#xff0c;用于获取未来几天的天气预报。你可以使用HTTP GET请求访问该接口&#xff0c;并根据你所在的城市或地理坐标获取相应的天气数据。 以下是一个示例请求的URL和一些常用的参数&#xff1a; URL: http://api.openwe…

Flink(二十二)Flink 的table api与sql之创建表的DDL

Flink 系列文章 Flink&#xff08;一&#xff09;1.12.7或1.13.5详细介绍及本地安装部署、验证 Flink&#xff08;二&#xff09;1.13.5二种部署方式(Standalone、Standalone HA )、四种提交任务方式&#xff08;前两种及session和per-job&#xff09;验证详细步骤 Flink&…

K8s安全配置:CIS基准与kube-bench工具

01、概述 K8s集群往往会因为配置不当导致存在入侵风险&#xff0c;如K8S组件的未授权访问、容器逃逸和横向攻击等。为了保护K8s集群的安全&#xff0c;我们必须仔细检查安全配置。 CIS Kubernetes基准提供了集群安全配置的最佳实践&#xff0c;主要聚焦在两个方面&#xff1a;主…

Greeplum以每日一个区间,批量创建多个分区

目录 一、需求分析 二、实施流程 2.1、创建以日期分区的临时表 2.2、循环创建每日的分区 2.3、单语句新增分区 2.4、删除特定分区 三、其他 一、需求分析 如标题所示&#xff0c;现在需要建一张临时表来存储每日增量的流水数据。存储周期为近两年&#xff0c;其中日增量约10…

【解析】对比学习和孪生网络的关系

文章目录 区别联系具体概念孪生网络&#xff08;Siamese Networks&#xff09;对比学习&#xff08;Contrastive Learning&#xff09; 总结 区别 孪生网络是一种特定的神经网络结构&#xff1b;对比学习是一种学习策略&#xff0c;它试图让模型学习如何区分正样本对&#xff…

C语言指针进阶-2

本篇文章带 1. 数组传参和指针传参 2. 函数指针 3. 函数指针数组 的相关知识详细讲解&#xff01; 如果您觉得文章不错&#xff0c;期待你的一键三连哦&#xff0c;你的鼓励是我创作动力的源泉&#xff0c;让我们一起加油&#xff0c;一起奔跑&#xff0c;让我们顶峰相见&…

(文章复现)梯级水光互补系统最大化可消纳电量期望短期优化调度模型matlab代码

参考文献&#xff1a; [1]罗彬,陈永灿,刘昭伟等.梯级水光互补系统最大化可消纳电量期望短期优化调度模型[J].电力系统自动化,2023,47(10):66-75. 1.基本原理 1.1 目标函数 考虑光伏出力的不确定性&#xff0c;以梯级水光互补系统的可消纳电量期望最大为目标&#xff0c;函数…

kernel32.dll如何修复,快速解决kernel32.dll缺失的方法

Kernel32.dll是Windows操作系统中一个重要的系统文件&#xff0c;对于系统的正常运行至关重要。然而&#xff0c;由于各种原因&#xff0c;用户可能会遇到kernel32.dll文件的缺失问题。今天小编就来给大家详细的介绍一下kernel32.dll这个文件&#xff0c;并且详细的介绍一下ker…

Mybatis映射关系mybatis核心配置文件

目录 1.Mybatis映射关系 1.1一对一映射之resultType 1.2resultMap处理映射关系 2.mybatis核心配置文件 1. properties&#xff08;属性&#xff09; 2. settings&#xff08;设置&#xff09; 3.typeAliases&#xff08;类型别名&#xff09; 4.environments&#xff0…

Iptables

常用名词 容器&#xff1a;存放东西 表(table)&#xff1a;存放链的容器&#xff0c;防火墙的最大概念 链(chain)&#xff1a;存放规则的容器 规则(policy)&#xff1a;准许或拒绝规则 Iptables处理流程 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上…

小程序通过ip+port+路径获取服务器中的图片

配置IIS 首先需要配置IIS。 打开控制面板&#xff0c;接下来的流程按下图所示。 安装好后&#xff0c;按“win”键&#xff0c;搜索IIS 选择一个ip地址&#xff0c;或手动填写&#xff0c;端口号按需更改 填写别名和物理路径&#xff0c;别名就是后续通过url访问物理…

Ubuntu上安装与配置SFTP

目录 一、预装软件 二、创建sftp管理组 三、SSH设置 三、创建用户家目录和设置home权限 四、创建用户并设置上传目录权限控制 五、用户初始化密码 六、说明 需求客户要求与第三方通过sftp交互文件&#xff0c;需要在Linux系统部署sftp服务器。考虑安全&#xff0c;计划对…

代码随想录算法训练营第五十二天 | 300.最长递增子序列、674.最长连续递增序列、718.最长重复子数组

文章目录 一、300.最长递增子序列二、674.最长连续递增序列三、718.最长重复子数组 一、300.最长递增子序列 题目链接 代码如下&#xff1a; class Solution { public:int lengthOfLIS(vector<int>& nums) {if (nums.size() < 1) return nums.size();vector<…

html5播放器视频切换和连续播放的实例

当前播放器实例可以使用changeVid接口切换正在播放的视频。当有多个视频&#xff0c;在上一个视频播放完毕时&#xff0c;自动播放下一个视频时也可采用该处理方式。 const option {vid: 88083abbf5bcf1356e05d39666be527a_8,//autoplay: true,//playsafe: , //PC端播放加密视…

牛客网Verilog刷题——VL41

牛客网Verilog刷题——VL41 题目答案 题目 请设计一个可以实现任意小数分频的时钟分频器&#xff0c;比如说8.7分频的时钟信号&#xff0c;注意rst为低电平复位。提示&#xff1a;其实本质上是一个简单的数学问题&#xff0c;即如何使用最小公倍数得到时钟周期的分别频比。设小…

typescipt学习笔记-常见类型

学习文档&#xff1a; TypeScript 之 Class&#xff08;上&#xff09; (yuque.com) 某个人博客 - 基础类型_TypeScript中文文档 基础类型 - TypeScript 中文手册 TypeScript 基础类型 | 菜鸟教程 (runoob.com) 一、前言 1、ts的作用&#xff1a;静态类型检查、非异常失败、…

数据中台系列2:rabbitMQ 安装使用之 window 篇

RabbitMQ 是一个开源的消息队列系统&#xff0c;是高级消息队列协议&#xff08;AMQP&#xff09;的标准实现&#xff0c;用 erlang 语言开发。 因此安装 RabbitMQ 之前要先安装好 erlang。 1、安装 erlang 到 这里 下载本机能运行的最新版 erlang 安装包。如果本机没有装过 …