RPC与服务的注册发现

文章目录

    • 1. 什么是远程过程调用(RPC)?
    • 2. RPC的流程
    • 3. RPC实践
    • 4. RPC与REST的区别
      • 4.1 RPC与REST的相似之处
      • 4.2 RPC与REST的架构原则
      • 4.3 RPC与REST的主要区别
    • 5. RPC与服务发现
      • 5.1 以zookeeper为服务注册中心
      • 5.2 以etcd为服务注册中心
    • 6. 小结
    • 参考

1. 什么是远程过程调用(RPC)?

在分布式计算中,远程过程调用(RPC)是指计算机程序导致过程(子程序)在不同的地址空间(通常为一个开放网络中的另一台计算机)执行,其编写方式就像是普通(本地)过程调用一样,程序员无需明确编写远程交互的细节。RPC是一种服务器-客户端(Client/Server)模式,经典实现是一个通过发送请求-接受响应进行信息交互的系统。

RPC是一种进程间通信的模式,程序分布在不同的地址空间中。如果在同一主机里,RPC可以通过不同的虚拟地址空间(即使使用相同的物理地址)进行通讯,而在不同主机间,则通过不同的物理地址进行交互。许多技术(通常是不兼容)都是基于这种概念而实现的。

RPC调用本质上是一种协议,允许一台计算机上的程序在另一天计算机上执行代码,而无需程序员明确编写此交互的代码。RPC类似于调用不同系统中可用的函数或方法,因此叫做远程过程调用。

RPC的一个显著特点是它能够掩盖网络接口的复杂性,使得开发人员可以专注于应用程序的功能,而无需深入研究网络协议的复杂性。

2. RPC的流程

  1. 客户端调用客户端stub(client stub),这个调用是在本地,并交调用参数push到栈(stack)中
  2. 客户端stub(client stub)将这些参数包装,并通过系统调用发送到服务端机器。打包的过程叫做marshalling。
  3. 客户端本地操作系统发送信息到服务器(可通过自定义TCP协议或者HTTP传输)
  4. 服务器将信息传送至服务端stub(server stub)
  5. 服务端stub(server stub)解析信息。该过程叫做unmarshalling
  6. 服务端stub(server stub)调用程序,并通过类似的方式返回给客户端

RPC工作流程

3. RPC实践

RPC实践,主要是以gRPC为例进行实践,因为我用的是go语言,所以选择的是grpc-go来进行实践。

gRPC的原理图如下,具体可参考:Introduction to gRPC
gRPC原理图

具体可以参考:gRPC for Go Quick Start

可以直接按照官方文档提供的步骤来,先完成前置条件,安装好protoc-gen-goprogoc-gen-go-grpc即可。

然后编写proto文件

syntax = "proto3";
option go_package="go-study/blogs/grpc_study/helloworld/hello";
option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";

package helloworld;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

使用protoc直接生成对应的pb文件即可,具体的命令:

protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative hello.proto

生成的文件如下:
pb生成文件

最后我们主要使用hello_grpc.pb.go文件里面对应的Client和Server的方法即可。

关于client和server的代码,可以参考:grpc-go examples helloworld

分别运行client和server,当client运行时会发送消息给server,收到消息后,server会处理消息并返回响应。

$ go run .\server.go
2024/07/14 15:42:30 server listening at [::]:50051
2024/07/14 15:42:42 Received: testing

$ go run .\client.go --name=testing
2024/07/14 15:42:42 Greeting: Hello testing

4. RPC与REST的区别

RPC与REST是API设计中的两种不同的架构风格。API则是允许两个软件组件使用一组定义和协议相互通信的机制。软件开发人员使用之前开发的组件或者第三方的组件来执行功能,因此不必从头开始编写所有内容。RPC API允许开发人员在外部服务器中调用远程函数,就好像它们在本地环境一样。

4.1 RPC与REST的相似之处

  • 抽象
    • 虽然网络通信是API的主要目标,但较低级别的通信本身是从API开发人员那里抽象出来的,这使得开发人员可以专注与功能而不是技术实施。
  • 交流
    • REST与RPC均可使用HTTP作为底层数据传输协议,RPC和REST中最常见的消息格式是JSON和XML。
  • 跨语言兼容性
    • 开发人员可以使用任何语言实现RESTful或者RPC API,只要API的网络通信元素符合RESTful或者RPC接口标准,就可以使用任何编程语言编写逻辑代码。

4.2 RPC与REST的架构原则

在RPC中,客户端在服务器上进行远程函数(也称为方法或过程)调用,通常在调用期间会向服务器传递一个或者多个数据值。

而REST客户端则是请求服务器针对服务器特定资源执行操作,操作仅限于创建、读取、更新和删除,并以HTTP动词或者HTTP方法的形式传达。

RPC侧重函数或操作,而REST侧重于资源或对象。

RPC原则:

  • 远程调用
    • RPC调用是由客户端对远程服务器上的函数进行的,就像该函数是在本地调用到客户端一样
  • 传递参数
    • 客户端通常向服务器函数发送参数,与本地函数大致相同
  • 存根(stub)
    • 函数存根同时存在于客户端和服务器上,在客户端上,它进行函数调用,在服务器上,它调用实际函数。(这个在hello world的实践处也可以看到,对于Client发送请求,进行的是定义好的pb函数的调用,而服务端启动的时候,是注册了服务的方法,而这个方法就是实际函数。)

REST原则

  • 客户端-服务器
    • REST的客户端与服务器架构将两者分离开来,即将客户端和服务器视为独立系统
  • 无状态
    • 服务器不会保留两次客户端请求之间的客户端记录
  • 可缓存
    • 客户端或者中间件系统可能会根据客户端是否指定了可以缓存的响应来缓存服务器响应
  • 分层系统
    • 中间系统可以存在于客户端与服务器之间,而客户端与服务器对中间系统无感知,像是它们之间连在一起一样
  • 统一接口
    • 客户端和服务器通过一组标准化指令和消息收发格式与REST API通信

4.3 RPC与REST的主要区别

  • 开发时间
    • RPC与REST诞生时间不同
  • 操作格式
    • REST拥有一套标准化服务器操作,但RPC API没有,某些RPC实施为标准化操作提供了框架
  • 数据传递格式
    • REST可在统一API内传递任何数据格式和多种格式的数据,RPC API的数据格式则由服务器选择,在实施过程中是固定的。
  • 状态
    • REST系统始终是无状态的,但RPC系统可以有状态,也可以无状态,具体取决于设计

当下REST API已经成为了主流,因为它更易于开发人员理解和实施,但RPC并没有消失,依然会在适合的应用场景中使用(如gRPC,允许客户端与服务器之间流式通信,而非请求和相应数据交换模式)。

5. RPC与服务发现

为了高可用,在生产环境中服务提供方都是以集群的方式对外提供服务,集群里面的这些IP随时会发生变化,此时我们需要能够实时获取对应服务节点,而这个获取的过程我们称作“服务发现”。

5.1 以zookeeper为服务注册中心

类似于Dubbo,采用的是以Zookeeper作为服务注册中心,注册中心在RPC场景下负责保存服务端应用的信息,服务端注册接口信息和自身地址到注册中心,客户端从注册中心读取和订阅需要调用的地址列表,框架如图所示:

Dubbo的注册中心示意图

5.2 以etcd为服务注册中心

在etcd中,etcd提供了一个gRPC解析器来支持备用名称系统,该系统从etcd获取端点以发现gRPC服务,底层基于监听以服务名称为前缀的秘钥更新机制实现。

具体实现则是通过etcd提供的etcdnaming的能力实现获取对应的grpc resolver,从而获取到对应的存储在etcd的服务器信息,从而获取到服务器的请求地址。

import (
	"go.etcd.io/etcd/client/v3"
	etcdnaming "go.etcd.io/etcd/client/v3/naming/resolver"

	"google.golang.org/grpc"
)

func main() {
	cli, err := clientv3.NewFromURL("http://localhost:2379")
	if err != nil {
		// ...
	}
	builder, err := etcdnaming.NewBuilder(cli)
	if err != nil {
		// ...
	}
	conn, gerr := grpc.Dial("my-service", grpc.WithResolvers(builder), grpc.WithBlock(), ...)
}

而对应的管理服务端点以及添加/删除服务端点则是通过操作etcd来实现。

添加端点

ETCDCTL_API=3 etcdctl put my-service/1.2.3.4 '{"Addr":"1.2.3.4","Metadata":"..."}'

删除端点

ETCDCTL_API=3 etcdctl del my-service/1.2.3.4

使用租约注册端点

使用租约注册端点可以确保如果主机无法保持活动心跳(例如,机器发生故障),它将从服务中删除。

lease=`ETCDCTL_API=3 etcdctl lease grant 5 | cut -f2 -d' '`
ETCDCTL_API=3 etcdctl put --lease=$lease my-service/1.2.3.4 '{"Addr":"1.2.3.4","Metadata":"..."}'
ETCDCTL_API=3 etcdctl lease keep-alive $lease

通过etcd加持gRPC可以实现RPC服务的注册发现,从而使得服务在保证高可用的情况下,RPC服务请求调用也能顺利完成。

6. 小结

很早之前就接触过RPC,也接触过服务的注册与发现,最早是学习Java的时候接触的Dubbo,工作后转到了Go,最近是看到了有etcd+gRPC的使用,带着看一看的想法就把RPC顺带着给一起复习下了。
在当下的分布式系统的情况下,RPC服务基本都需要考虑高可用,所以注册中心就成为了必须要解决的一个问题。

参考

  • Remote procedure call
  • 服务注册发现
  • RPC与REST的区别
  • gRPC命名和发现 - etcd

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

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

相关文章

大语言模型诞生过程剖析

过程图如下 📚 第一步:海量文本的无监督学习 得到基座大模型🎉 🔍 原料:首先,我们需要海量的文本数据,这些数据可以来自互联网上的各种语料库,包括书籍、新闻、科学论文、社交媒体帖…

<数据集>光伏板缺陷检测数据集<目标检测>

数据集格式:VOCYOLO格式 图片数量:2400张 标注数量(xml文件个数):2400 标注数量(txt文件个数):2400 标注类别数:4 标注类别名称:[Crack,Grid,Spot] 序号类别名称图片数框数1Crack8688922Grid8248843S…

全栈智能家居系统设计方案:STM32+Linux+多协议(MQTT、Zigbee、Z-Wave)通信+云平台集成

1. 项目概述 随着物联网技术的快速发展,智能家居系统正在成为现代生活中不可或缺的一部分。本文介绍了一个基于STM32微控制器和Linux系统的智能家居解决方案,涵盖了硬件设计、软件架构、通信协议以及云平台集成等方面。 该系统具有以下特点: 采用STM32作为终端设备的控制核心…

springboot3——项目部署

springboot的项目开发完了,怎么样把他放到服务器上或者生产环境上让他运行起来跑起来。就要牵扯到项目部署,打包的方式了。 springboot支持jar和war: 打jar包:默认方式,项目开发完打个jar包,通过命令把jar包起起来就…

汇川ST 实现分拣

//初始化 IF init FALSE THEN// 初始化init : 1 ;//45 Y数组 BOOL[8] [OFF发料Y OFF分拣Y OFF送料Y OFF取料Y OFF摆取Y OFF摆放Y OFF升降Y OFF夹料Y] [OFF发料Y OFF分拣Y OFF送料Y OFF取料Y OFF摆取Y OFF摆放Y OFF升降Y OFF夹料Y] 不保持 私有 Y0(*Y数组[0] BOOL OFF 发料…

MySQL 中的几种锁

MySQL 中的锁 #按锁粒度如何划分? 按锁粒度划分的话,MySQL 的锁有: 表锁:开销小,加锁快;锁定力度大,发生锁冲突概率高,并发度最低;不会出现死锁。行锁:开销大,加锁慢…

unity宏编译版本

在写c程序的时候我们通常可以用不同的宏定义来控制不同版本的编译内容,最近有个需求就是根据需要编译一个完全体验版本,就想到了用vs的那套方法。经过研究发现unity也有类似的控制方法。 注意这里设置完后要点击右下的应用,我起先就没有设置…

7/13 - 7/15

vo.setId(rs.getLong("id"))什么意思? vo.setId(rs.getLong("id")); 这行代码是在Java中使用ResultSet对象(通常用于从数据库中检索数据)获取一个名为"id"的列,并将其作为long类型设置为一个对象…

深度学习基础:Numpy 数组包

数组基础 在使用导入 Numpy 时,通常给其一个别名 “np”,即 import numpy as np 。 数据类型 整数类型数组与浮点类型数组 为了克服列表的缺点,一个 Numpy 数组只容纳一种数据类型,以节约内存。为方便起见,可将 Nu…

简洁实用的原创度检测工具AntiPlagiarism NET 4.132

AntiPlagiarism NET是一个适用于Windows的程序,它允许您检查文本的唯一性和从不同Internet来源借用的存在。使用AntiPlagiarism NET,您可以: 将程序用于不同的目的该程序适用于学生、教师、记者、文案作者和其他需要检查其文本或其他作者文本…

FPGA 项目菜单功能比较

为了帮助您更好地理解每个FPGA功能模块的实用场合、区别和特点,以下是详细的比较: 功能模块实用场合区别特点FPGA I/O自动控制系统、数据采集系统直接与FPGA板卡上的物理端口交互,配置和使用外部I/O设备灵活配置输入输出端口,支持…

开放式蓝牙耳机哪家强?五款值得入手的款式推荐!

当前,耳机技术迎来颠覆性飞跃,开放式蓝牙耳机横空出世,以其卓越的音质体验与无可比拟的听力保护优势,重塑了耳机行业的标准。其非入耳设计,既保证了音质的纯粹传达,又有效避免了长时间佩戴对耳朵的潜在伤害…

板级调试小助手(2)ZYNQ自定义IP核构建属于自己的DDS外设

一、前言 在上期文章中讲述了小助手的系统结构和原理。在PYNQ的框架开发中,我们一般可以将PL端当做PS端的一个外设,通过读写寄存器的方式来操作外设的功能,就类似于在开发ARM和DSP中操作外设一样,不同时的是,我们可以通…

AIGC率超标?掌握论文去AI痕迹的高效策略

随着 AI 技术迅猛发展,各种AI辅助论文写作的工具层出不穷! 为了防止有人利用AI工具进行论文代写,在最新的学位法中已经明确规定“已经获得学位者,在获得该学位过程中如有人工智能代写等学术不端行为,经学位评定委员会…

智慧公厕系统实现人性化与节能化的完美结合

在当今社会,科技的飞速发展正不断改变着我们的生活方式,公厕也不例外。智慧公厕系统的出现,不仅提升了人们的使用体验,更实现了人性化与节能化的完美结合,为城市公共服务带来了全新的变革。 一、人性化,是智…

清朝嘉庆二十五年(1820年)地图数据

我们在《中国历史行政区划连续变化数据》一文中,为你分享了中国历史行政区划连续变化地图数据。 现在再为你分享清朝嘉庆二十五年(1820年)的地图数据,该数据对于研究历史的朋友应该比较有用,请在文末查看领取方式。 …

SpringBoot实战:多表联查

1. 保存和更新公寓信息 请求数据的结构 Schema(description "公寓信息") Data public class ApartmentSubmitVo extends ApartmentInfo {Schema(description"公寓配套id")private List<Long> facilityInfoIds;Schema(description"公寓标签i…

深度学习概览

引言 深度学习的定义与背景 深度学习是机器学习的一个子领域&#xff0c;涉及使用多层神经网络分析和学习复杂的数据模式。深度学习的基础可以追溯到20世纪80年代&#xff0c;但真正的发展和广泛应用是在21世纪初。计算能力的提升和大数据的可用性使得深度学习在许多领域取得…

platformIO STM32 upload-“Failed to init device.”问题解决

因为发现自己的32板子有带自动下载功能&#xff0c;platformIO也支持串口下载&#xff0c;但一直提示这个问题 问题情况 问题解决 把BOOT0接3.3V&#xff0c;BOOT1接GND&#xff0c;再点击下载(之后接回去复位也可以显示) 这是我从一个有相同问题的人从他尝试过的解决方案中…

SadTalker数字人服务器部署

一、单独SadTalker部署 git clone https://github.com/OpenTalker/SadTalker.gitcd SadTalker conda create -n sadtalker python3.8conda activate sadtalkerpip install torch1.12.1cu113 torchvision0.13.1cu113 torchaudio0.12.1 --extra-index-url https://download.pyto…