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库进行序列化

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HarmonyOS NEXT应用开发—图片压缩方案

介绍 图片压缩在应用开发中是一个非常常见的需求,特别是在处理用户上传图片时,需要上传指定大小以内的图片。目前图片压缩支持jpeg、webp、png格式。本例中以jpeg图片为例介绍如何通过packing和scale实现图片压缩到目标大小以内。 效果图预览 使用说明…

Catmull-Rom P5 ThreeJs与前端

文章目录 问题Echarts 3D如何让曲线变得平滑?Echarts 2D图中平滑效果是如何实现的?如何在一个Echarts 3D图中画一个圆圈?如何在Echarts 3D图中画一个立方体? Catmull-Rom插值算法先来回答第二个问题回到第一个问题在Echarts 3D图中…

运维安全管理与审计系统(堡垒机)

一、什么是运维安全管理与审计系统 运维安全管理与审计系统(俗称 “堡垒机”):是采用新一代智能运维技术框架,基于认证、授权、访问、审计的管理流程设计理念,实现对企事业IT中心的网络设备、数据库、安全设备、主机系…

Zustand极简的状态管理工具

介绍 一个小型、快速且可扩展的 Bearbones 状态管理解决方案。 Zustand 有一个基于 hooks 的舒适 API。它不是样板文件或固执己见,但有足够的惯例来明确和类似通量。 zustand官网 zustand使用方法及调试工具的安装使用 安装包 npm install zustand2.创建store仓…

【Unity投屏总结】投屏方案总结

【背景】 想方便自己在VR中工作,打算做一个能够挂多个屏幕的远程控制VR桌面。研究下来发现细分场景有很多,有点鱼和熊掌不可兼得的意味,细分如下。 【投屏场景与解决方案】 希望多人能够同时观看我的屏幕,也就是一屏投多屏&…

K8s的Pod出现Init:ImagePullBackOff问题的解决,(以calico网络插件为例)

问题描述: 对于这类问题的解决思路应该都差不多,本文以calico插件安装为例,发现有个Pod的镜像没有pull成功 第一步:查看这个pod的描述信息 kubectl describe pod calico-node-t9rql -n kube-system从上图发现是docker拉取"…

实体门店运营方案模板与策划技巧:轻松打造高效运营体系

在当今竞争激烈的商业环境中,实体门店的运营如同一场精密谋划的战役,需要精心策划和高效管理才能在市场中崭露头角。作为经营鲜奶吧5年时间的创业者,我深知成功的实体门店背后离不开一套完善的运营方案和策略。 在这篇文章中,我将…

基于java的宠物信息交流平台设计(含源文件)

随着世界经济信息化、全球化的到来和互联网的飞速发展,推动了各行业的改革。若想达到安全,快捷的目的,就需要拥有信息化的组织和管理模式,建立一套合理、动态的、交互友好的、高效的“多鱼”旧物交易平台。当前的信息管理存在工作…

精酿啤酒:一口啤酒,一份享受

在繁华的都市生活中,我们总是匆匆忙忙,追求着各种目标和成就。然而,在这个过程中,我们往往忽略了生活的本质,那就是享受。而Fendi Club 啤酒,正是为那些追求品质生活的都市精英们量身打造的。 Fendi Club啤…

Java多线程自定义线程池——线程池的七大参数和四大拒绝策略

线程池 2.1 线程池思想 我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统…

Claude3介绍

英文介绍链接:Introducing the next generation of Claude \ Anthropic Anthropic这家由OpenAI分裂出去的兄弟公司,悄无声息地、低调地将Claude3推出了 免费版claude 3 sonnet使用网站(国内镜像站):Claude 3 AI&…

106 基于消息队列来做 mysql 大数据表数据的遍历处理

前言 最近有这样的一个需求, 我们存在一张 很大的 mysql 数据表, 数据量大概是在 六百万左右 然后 需要获取所有的记录, 将数据传输到 es 中 然后 当时 我就写了一个脚本来读取 这张大表, 然后 分页获取数据, 然后 按页进行数据处理 转换到 es 但是存在的问题是, 前面 还…

【Micropython ESP32】pwm脉宽调制技术

文章目录 前言一、PWM脉宽调制技术介绍二、machine.PWM 类2.1 machine.PWM 类的构造对象2.2 PWM 对象初始化2.3 关闭PWM设备2.4 设置pwm的周期2.5 设置占空比 三、pwm示例代码总结 前言 在嵌入式系统和物联网应用中,控制电机、LED灯和其他设备的亮度或速度是常见的…

汽车电子零部件(8):T_Box

前言: 网联汽车(Connected Vehicles ,CV)是一个广泛的概念,四个主要的CV线程已发展起来:互联、自主、共享和电动。这些应用于包括CV在内的垂直领域:汽车、通信、互联网和共享手机服务。中国汽车工程师学会(SAEC)提倡将车载ADAS(高级驾驶员辅助系统)与通信技术相结合…

基于单片机的模糊PID炉温控制系统设计

摘 要 电热炉是在工业热处理的生产中广泛使用的一种设备,电热炉的温度控制系统存在时变性,非线性,滞后性等特征,难以用常规PID的控制器对系统达到很好的控制效果。当控温精度的要求高时,使用传统的控制理论方法难以达…

医药工厂5G智能制造数字孪生可视化平台,推进医药企业数字化转型

医药工厂5G智能制造数字孪生可视化平台,推进医药企业数字化转型。随着科技的不断发展,数字化转型已成为医药企业不可或缺的一部分。5G智能制造医药工厂数字孪生可视化平台作为数字化转型的重要工具,正在逐步改变医药企业的生产方式和管理模式…

信息论相关知识简单整理

信息论相关知识 互信息 互信息(Mutual Information)是信息论里一种有用的信息度量,它可以看成是一个随机变量中包含的关于另一个随机变量的信息量,或者说是一个随机变量由于已知另一个随机变量而减少的不肯定性。 设两个随机变量(X,Y)的联合…

嵌入式驱动学习第四周——platform总线

前言 platform是Linux内核抽象出来的软件代码,用于设备与驱动的连接,设备与驱动通过总线进行匹配;匹配成功后会执行驱动中的probe函数,在probe函数中可以获取到设备的信息; 嵌入式驱动学习专栏将详细记录博主学习驱动的…

3月份后半月比赛总结

VCTF web hackjs 就直接给了源码审计 const express require(express) const fs require(fs) var bodyParser require(body-parser); const app express() app.use(bodyParser.urlencoded({extended: true })); app.use(bodyParser.json());app.post(/plz, (req, res) …

VR历史建筑漫游介绍|虚拟现实体验店|VR设备购买

VR历史建筑漫游是一种利用虚拟现实技术,让用户可以身临其境地参观和探索历史建筑的体验。通过VR头显和相关设备,用户可以在虚拟环境中自由移动和互动,感受历史建筑的真实氛围和文化内涵。 在VR历史建筑漫游中,您可以选择不同的历史…