RPC 和 序列化

RPC

1 RPC调用流程

1.1 clerk客户端调用远程服务

Clerk::PutAppend()

raftServerRpcUtil::PutAppend() 

raftServerRpcUtil是client与kvserver通信的入口,  包含kvserver功能的一对一映射:Get/PutAppend,通过stub对象——raftKVRpcProctoc::kvServerRpc_Stub *stu进行对应的rpc远程调用。

针对raft节点之间的通信,设计了RaftRpcUtil类型,包含raft节点功能:AppendEntries/ InstallSnapshot/ RequestVote

 kvServerRpc_Stub::PutAppend()

kvServerRpc_Stub 是 kvServerRPC.proto文件编译后生成的存根,用于实现rpc远程调用。

stub使用MprpcChannel作为参数来初始化,因此接下来会调用MprpcChannel::CallMethod():

stub = new raftKVRpcProctoc::kvServerRpc_Stub(new MprpcChannel(ip, port, false));

 MprpcChannel::CallMethod()

MprpcChannel:实现rpc通信的类建立和服务端的连接,发送rpc请求,和接收rpc回复

所有通过stub调用的rpc方法,都会走到MprpcChannel::CallMethod(): 生成rpc请求数据并序列化,使用socket发送请求并接收回复

1.2 kvserver 提供rpc服务

KvServer::KvServer()

构造函数中发布rpc服务类型: 服务的类型有两种,分别是Raft和KvServer

  • class Raft : public raftRpcProctoc::raftRpc
  • class KvServer : raftKVRpcProctoc::kvServerRpc

Raft类型的服务用于raft节点之间相互调用,KvServer类型的服务被client调用

RpcProvider::Run() 启动rpc服务,等待调用。项目中是阻塞等待,同步阻塞模型

RpcProvider::OnMessage()

 已建立连接用户的读写事件回调:调用Callmethod来调用本地的业务

RpcProvider:网络对象类,发布节点能提供的rpc服务,并启动rpc服务(接收连接,接收请求并执行)

service->CallMethod() 

有两种服务类型(Raft和KvServer),根据请求的service的类型,动态调用对应的CallMethod();

client调用 KvServerRpc::CallMethod(),raft节点调用raftRpc::CallMethod()。

KvServerRpc::CallMethod()

 在函数内部,最终调用KvServer本地的方法。

2 rpc基础

2.1 概念

  1. RPC(Remote Procedure Call Protocol) 远程过程调用协议。
  2. RPC是一种通过网络从远程计算机上请求服务,不需要了解底层网络技术的协议。
  3. 远程调用就像调用本地方法一样便捷。

2.2 常用RPC技术或框架

  1. 应用级的服务框架:阿里的 Dubbo/Dubbox、Google gRPC、Spring Boot/Spring Cloud。
  2. 远程通信协议:RMI、Socket、SOAP(HTTP XML)、REST(HTTP JSON)。
  3. 通信框架:MINA 和 Netty

2.3 rpc作用

  • 微服务化:跨平台的服务之间远程调用;
  • 分布式系统架构:分布式服务跨机器进行远程调用;
  • 支持跨语言调用。

2.4 架构

服务注册,就是将提供某个服务的模块信息(通常是这个服务的ip和端口)注册到1个公共的组件上去(注册中心,比如: zookeeper\consul)。

服务发现,就是新注册的这个服务模块能够及时的被其他调用者发现。不管是服务新增和服务删减都能实现自动发现。

一个完整的服务发现中心还需要支持负载均衡容灾处理等功能。

负载均衡:简单数就是将请求分散给各个机器上,维持各个机器的请求的均衡态势。确保不会大量请求都涌入到某几个机器上导致机器过载。

容灾处理:就是及时剔除掉故障的机器。例如某次调用19.4.11.11上的OrderServer出现故障,那么服务中心会将这个地址剔除掉,防止下次再访问到这个有故障的地址。

2.5 rpc调用流程

2.6 重要组成 

客户端:调用方

客户端存根:client stub,保存服务端地址信息,将客户端的请求方法、参数序列化,通过网络发送给服务端。

服务端存根:server stub,接收请求,反序列化,调用本地服务

服务端:服务提供者

网络传输:tcp或http

2.7 基础功能

2.7.1 服务寻址

rpc所有函数都有一个自己的ID,在所有进程中都唯一。客户端远程调用,必须附上这个ID.

客户端查一下映射表,找出对应ID,服务端根据对应的ID提供服务。

Call ID映射表一般是哈希表。

2.7.2 序列化和反序列化

概念

  1. 序列化:将消息对象转换为二进制流。
  2. 反序列化:将二进制流转换为消息对象。

必要性

  • 本地函数调用:只需要将数据压入栈中,然后让函数去栈中读取数据。
  • 远程调用:无法通过栈传递参数。需要客户端将请求序列化,传送给服务端。

序列化的优势

  • 二进制字节流便于网络传输
  • 可跨平台、跨语言。

2.7.3 网络传输

基于TCP

通过socket连接发送序列化的调用接口名称、方法名称和参数等。

基于HTTP

客户端发送GET/PUT/POST/DELETE请求给服务端

服务端根据不同的请求参数和请求url进行方法调用,返回结果

对比

基于TCP更灵活,可减少网络开销,性能高。但实现复杂;

HTTP已经实现序列化,但http传输效率比tcp低。

2.8 服务治理

2.8.1 负载均衡

本项目实现的rpc没有做负载均衡,因为当前是Read Log模式,读写请求都是直接发送给leader。后面如果优化为从follower读,可能用得到负载均衡。

  1. 轮询算法(Round Robin):轮询算法是最简单的负载均衡算法之一,它按照请求的顺序依次将每个请求分配到不同的服务器上。当有新的请求到来时,负载均衡器会依次将请求发送到不同的服务器,直到所有的服务器都被轮询过一遍,然后再从头开始。
  2. 最小连接数算法(Least Connections):最小连接数算法会将新的请求分配到当前连接数最少的服务器上,以确保各服务器的负载尽可能均衡。这种算法考虑了服务器的负载情况,优先将请求发送到负载较低的服务器上。
  3. 最少响应时间算法(Least Response Time):最少响应时间算法会将请求发送到响应时间最短的服务器上,以保证响应时间的最小化。这种算法通常需要负载均衡器记录每个服务器的响应时间,并动态调整请求的分配策略。
  4. 哈希算法(Hashing):哈希算法根据请求的某些属性(如客户端IP地址、URL等)计算哈希值,并将请求发送到对应哈希值的服务器上。这种算法能够确保相同请求始终被发送到同一台服务器上,适用于需要保持会话一致性的场景。
  5. 加权轮询算法(Weighted Round Robin):加权轮询算法在轮询算法的基础上引入了权重的概念,不同的服务器具有不同的权重值。根据权重值的不同,负载均衡器会调整请求的分配比例,以实现负载均衡。
  6. 拓展:hash环也是一种重要的负载均衡算法,也可以提及。

3 本项目rpc

本项目实现的rpc比较简单,采用的是同步阻塞模式。

rpc请求格式:

  1. head_size(4个字节,存储head_str的长度) 
  2. head_str(RpcHeader类型的序列化
  3. args(PutAppendArgs/GetArgs 请求对象的序列化

RpcHeader:

message RpcHeader
{bytes service_name = 1;bytes method_name = 2;uint32 args_size = 3;
}

可以优化的点:

  •         异步rpc
  •         rpc设为长连接还是短连接?长连接考虑设计一个定时器          
  •         负载均衡
  •         服务发现,服务注册

序列化

1 Protobuf

kvServerRPC.proto文件

syntax = "proto3";
package raftKVRpcProctoc; //所在的命名空间
option cc_generic_services = true;  //开启stub服务message GetArgs{bytes Key = 1 ;bytes ClientId = 2 ;int32 RequestId = 3;
}
message GetReply  {bytes Err = 1;bytes Value = 2;
}message PutAppendArgs  {bytes Key = 1;bytes  Value = 2 ;bytes  Op = 3;bytes  ClientId = 4;int32  RequestId = 5;
}
message PutAppendReply  {bytes Err = 1;
}service kvServerRpc
{rpc PutAppend(PutAppendArgs) returns(PutAppendReply);rpc Get (GetArgs) returns (GetReply);
}

.proto文件定义message类型和service类型,编译后,生成.pb.h文件和.pb.cc文件。

.proto文件中定义的message类型可以序列化和反序列化(SerializeToString/ParseFromString).

编译后会生成对应Stub(存根)类型 raftKVRpcProctoc::kvServerRpc_Stub,使用Stub对象可以调用.proto文件中定义的service。

2 boost

快照:kvserver、kvdb和raft节点使用boost库进行序列化

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

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

相关文章

web前端之实现复选功能、repeat

MENU 1、原生实现1.1、html部分1.2、JavaScript部分1.3、css部分1.4、效果图 2、uniApp实现2.1、html部分2.2、JavaScript部分2.3、css部分2.4、效果图 1、原生实现 1.1、html部分 暂时为null,后续会补充。1.2、JavaScript部分 暂时为null,后续会补充…

算法第二十九天-森林中的兔子

森林中的兔子 题目要求 解题思路 重点:某个兔子回答x的时候,那么数组中最多循序x1个同花色的兔子同时回答x 我们可以通过举例子得出一下的规律: 我们统计数组中所有回答x的兔子的数量n: 若n%(x1)0,说明我们此时只需…

Vector[C++]

文章目录 C中的std::vector简介std::vector的特点std::vector的重要接口用法介绍1. 初始化vector 2. 添加元素push_backemplace_back 3. 访问元素operator[]back 4. 修改元素operator 5. 遍历三种,下标,迭代器,范围for 6. 容量和大小sizeempt…

Induction or tail-recursion

选择排序 遍历整个待排序的数组,从第一个元素开始。在未排序的部分中,找到最小(或最大)的元素,并将其与第一个元素交换位置。接着从第二个元素开始,重复步骤2,直到所有元素都被排序 迭代版 递…

Qt实现简单的五子棋程序

Qt五子棋小程序 Qt五子棋演示及源码链接登陆界面单机模式联机模式联网模式参考 Qt五子棋 参考大佬中国象棋程序,使用Qt实现了一个简单的五子棋小程序,包含了单机、联机以及联网三种模式;单机模式下实现了简易的AI;联机模式为PtoP…

OPTIONS请求(跨域预检查)

目录 一、什么是OPTIONS请求?二、简单请求、复杂请求三、特定的请求头、响应头 一、什么是OPTIONS请求? OPTIONS 请求方式是 HTTP 协议中的一种,主要用于 从响应头中获取服务器支持的HTTP请求方式。 OPTIONS 请求方式是 浏览级行为&#xf…

Redis命名设计

可读性和管理性 以项目名为前缀(防止key冲突),用冒号分隔,比如项目名:表名:id zh(知乎):news_data(新闻数据):2(主键id) zh:news_data:2 精简性 key的命名,尽量精简,key的名字长度对内存的占用不可忽视,我们来实际…

网络编程--高并发服务器

这里写目录标题 引入场景 多进程并发服务器二级目录二级目录二级目录 多线程并发服务器二级目录二级目录二级目录 多路IO转接服务器设计思路对比引入 select函数简介参数介绍第一个参数第234参数返回值对于第234参数的应用对于最后一个参数总结 附加操作(附加四个函…

【SRE系列之docker容器】--dockerfile镜像优化

dockerfile镜像优化 1.1 镜像优化方法 系统镜像采用ubuntu或者alpine,会比centos少1G左右编写业务镜像时从官网拉取镜像,其余配置根据业务需求再配置编写dockerfile时把不用的安装包卸载或者删除尽量减少run命令的使用(一个run命令&#xf…

牛客题霸-SQL入门篇(刷题记录二)

本文基于前段时间学习总结的 MySQL 相关的查询语法,在牛客网找了相应的 MySQL 题目进行练习,以便加强对于 MySQL 查询语法的理解和应用。 以下内容是牛客题霸-SQL入门篇剩余的第 21-39 道题目的 SQL 代码答案。 由于涉及到的数据库表较多,因…

链路聚合实验(华为)

思科设备参考:链路聚合实验(思科) 一,技术简介 网络设备的链路聚合技术(Link Aggregation)是一种将多个物理链路捆绑在一起,形成一个逻辑链路的技术。这样做可以增加带宽、提高可靠性和实现负…

(五)OpenOFDM解码

解码 现在我们已经校正了残余 CFO,也校正了通道增益,下一步是将 FFT 输出映射到实际数据位。这是对数据包进行编码的逆过程。 解调:复数到位解交织:对每个 OFDM 符号内的比特进行混洗卷积解码:去除冗余并纠正潜在的位…

C语言学习笔记day8

一维数组冒泡排序法 1. 作用 将乱序的一维数组按照从小到大的顺序排列 2. 原理示意图 3. 代码 #include <stdio.h> #include <stdlib.h> #include <time.h>int main(void) {int a[5] {0};int len sizeof(a) / sizeof(a[0]);int i 0;int j 0;int tmp …

CSS案例-3.背景练习

效果1 用背景加入图标 效果2 将图片设为页面背景,图片主体在中间 效果3 鼠标放到导航栏上会变颜色 知识点 CSS背景 属性 描述 取值 background 复合属性 看独立属性 background-color 背景颜色 <color> background-image 背景图像 none | url background-repeat 背景…

vulhub中GIT-SHELL 沙盒绕过漏洞复现(CVE-2017-8386)

GIT-SHELL 沙盒绕过&#xff08;CVE-2017-8386&#xff09;导致任意文件读取、可能的任意命令执行漏洞。 测试环境 为了不和docker母机的ssh端口冲突&#xff0c;将容器的ssh端口设置成3322。本目录下我生成了一个id_rsa&#xff0c;这是ssh的私钥&#xff0c;连接的时候请指…

算法练习:前缀和

目录 1. 一维前缀和2. 二维前缀和3. 寻找数组中心下标4. 除自身以外数组的乘积5. !和为k的子数字6. !和可被k整除的子数组7. !连续数组8. 矩阵区域和 1. 一维前缀和 题目信息&#xff1a; 题目链接&#xff1a; 一维前缀和思路&#xff1a;求前缀和数组&#xff0c;sum dp[r] …

性能分析调优模型

性能测试除了为获取性能指标外&#xff0c;更多是为了发现性能瓶颈和性能问题&#xff0c;然后针对性能问题和性能瓶颈进行分析和调优。在当今互联网高速发展的时代&#xff0c;结合传统软件系统模型以及互联网网站特征&#xff0c;性能调优的模型可以归纳总结为如图1-5-1所示的…

多线程服务器适用场合

前提 进程”指的是fork(2)系统调用的产物 线程”指的是pthread_create()的产物,因此是宝贵的那种原生线程。而且Pthreads是NPTL的,每个线程由clone(2)产生,对应一个内核的task_struct。 Pthreads是一组线程操作的标准&#xff0c;NPTL是 Native POSIX Thread Library 的缩写&…

【Quixel Mixer】简单介绍

一、下载 官网下载地址&#xff1a;Quixel Mixer - All-in-one texturing & material creation tool 下载好之后双击exe来安装 等待安装完成 下载后打开&#xff0c;新建一个工程和Mix 二、界面介绍 我们先将软件界面分为如下3个部分 1号区域为菜单栏 2号区域介绍 2号…