RPC与服务的注册发现

news2024/11/13 10:06:11

文章目录

    • 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

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

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

相关文章

MybatisPlus(MP)基础知识

MP BaseMapper 为了简化单表CRUD,MybatisPlus提供了一个基础的BaseMapper接口,其中已经实现了单表的CRUD,因此我们自定义的Mapper只要实现了这个BaseMapper,就无需自己实现单表CRUD了。 package com.itheima.mp.mapper;import …

基于javaScript的冒泡排序

目录 一.前言 二.设计思路和原理 三.源代码展示 四. 案例运行结果 一.前言 冒泡排序简而言之,就是一种算法,能够把一系列的数据按照一定的顺序进行排列显示(从小到大或从大到小)。例如能够将数组[5,4,3,2,1]中的元素按照从小到…

优选算法之双指针(上)

目录 双指针(利用数组下标来充当指针): 一、移动零 1.题目链接:283.移动零 2.题目描述: 3.解法(快排的思想:数组划分区间 - 数组分两块) 🌴算法思路: …

2024.7.14周报

目录 摘要 ABSTRACT 一、文献阅读 一、题目 二、摘要 三、文献解读 一、Introduction 二、KINN框架 三、主要结果 四、Conclusion 二、KAN 一、KAN与MLP区别 二、KAN网络解析 三、激活函数参数化(B-splines) 三、网络架构代码 摘要 本周…

Vue1-Vue核心

目录 Vue简介 官网 介绍与描述 Vue的特点 与其它 JS 框架的关联 Vue周边库 初识Vue Vue模板语法 数据绑定 el与data的两种写法 MVVM模型 数据代理 回顾Object.defineProperty方法 何为数据代理 Vue中的数据代理 数据代理图示 事件处理 事件的基本使用 事件修…

【Python 项目】类鸟群:仿真鸟群

类鸟群:仿真鸟群 仔细观察一群鸟或一群鱼,你会发现,虽然群体由个体生物组成,但该群体作为一个整体似乎有它自己的生命。鸟群中的鸟在移动、飞越和绕过障碍物时,彼此之间相互定位。受到打扰或惊吓时会破坏编队&#xf…

数据库管理-第218期 服务器内存(20240711)

数据库管理218期 2024-07-11 数据库管理-第218期 服务器内存(20240711)1 内存2 ECC内存3 原理3.1 多副本传输3.2 纠错码3.3 汉明码 总结 数据库管理-第218期 服务器内存(20240711) 作者:胖头鱼的鱼缸(尹海文…

TCP三次握手四次挥手原理

学习视频:TCP三次握手四次挥手 TCP报文格式 源端口号和目的端口号:同IP数据报中的源IP与目的IP唯一确定一条TCP连接 序号seq(4字节32位):用来标识TCP发端向TCP收端发送的数据字节流 确认序号(4字节32位)&a…

5.SpringBoot核心源码-启动类源码分析

目录 概述技巧spring boot 如何启动应用程序run方法里面核心逻辑 SpringApplicaiton.run(xxx.class,args)结束 概述 SpringBoot核心源码-启动类源码分析 技巧 如何给外部源码加注释,想要在源码中添加自己的注释,会弹出 file is read only,代…

光电门与电压放大器做电磁感应定律验证实验

根据上述原理可知,实验需要测量的量有两个:挡光时间间隔和挡光时的电压平均值。挡光时间可通过Arduino的数字输入端口采集光电门信号并计算得到,电压值可以通过Arduino的模拟信号输入端口采集。但是由于Arduino的模拟信号输入端只能精确到5mV…

【微信小程序开发】如何定义公共的js函数,其它页面可以调用

在微信小程序开发中,可以通过以下步骤定义和使用公共的 JS 函数,使得其它页面可以调用: 1. 创建一个公共的 JS 文件:在项目的 utils 目录下创建一个 JS 文件,例如 utils/util.js。 2. 定义公共函数:在 uti…

【Python从入门到进阶】60、Pandas中DataFrame对象的操作(一)

接上篇《59、Pandas库中Series对象的操作(二)》 上一篇我们讲解了Series对象的运算、函数应用、时间序列操作,以及Series的案例实践。本篇我们来讲解Pandas中DataFrame对象的操作。 一、DataFrame对象的基本概念及特点 在Pandas库中,DataFrame是一种非…

基于Python+Django+MySQL的心理咨询预约系统

心理咨询预约系统 DjangoMySQL 基于PythonDjangoMySQL的心理咨询预约系统 项目主要依赖Django3.2,MySQL 支持随机验证码生成与登录验证 简介 基于PythonDjangoMySQL的心理咨询预约系统通过连接数据库获取数据,登录新增随机数字验证码验证。具体可以看…

网络请求优化:如何让你的API飞起来

网络请求优化:如何让你的API飞起来 亲爱的开发者朋友们,你是否曾经遇到过这样的场景:用户疯狂点击刷新按钮,你的服务器却像老年人散步一样慢吞吞地响应。或者,你的应用像个贪吃蛇,疯狂吞噬用户的流量包。如果你对这些情况再熟悉不过,那么恭喜你,你正需要…

【Linux】进程间通信(IPC)——匿名管道

目录 为什么要进行进程间通信? 匿名管道的具体实现 pipe创建内存级文件形成管道 pipe的简单使用 匿名管道的四种情况和五种特性 四种情况 五种特性 PIPE_BUF 命令行管道 | 功能代码:创建进程池 为什么要进行进程间通信? 1.数据传输&…

1.27、基于径向基神经网络的曲线拟合(matlab)

1、基于径向基神经网络的曲线拟合简介及原理 1)原理简介 基于径向基神经网络(Radial Basis Function Neural Network, RBFNN)的曲线拟合是一种常用的非线性拟合方法,通过在输入空间中使用径向基函数对数据进行处理,实现对非线性关系的拟合。 RBFNN的基本原理是将输入空…

opencascade AIS_InteractiveContext源码学习8 trihedron display attributes

AIS_InteractiveContext 前言 交互上下文(Interactive Context)允许您在一个或多个视图器中管理交互对象的图形行为和选择。类方法使这一操作非常透明。需要记住的是,对于已经被交互上下文识别的交互对象,必须使用上下文方法进行…

Hash表(C++)

本篇将会开始介绍有关于 unordered_map 和 unordered_set 的底层原理,其中底层实现其实就是我们的 Hash 表,本篇将会讲解两种 Hash 表,其中一种为开放定址法,另一种为 hash 桶,在unordered_map 和 unordered_set 的底层…

【Git从入门到精通】——Git常用命令总结

🎼个人主页:【Y小夜】 😎作者简介:一位双非学校的大二学生,编程爱好者, 专注于基础和实战分享,欢迎私信咨询! 🎆入门专栏:🎇【MySQL&#xff0…

火星全球彩色影像图介绍(中分辨率相机)

一、数据基本信息 该数据是利用天问一号轨道器中分辨率相机获取的影像经光度校正、几何校正、全球制图等制作而成的全火星地图数据DOM,每个数据包含一个tif数据文件。该影像图分辨率为76米。 任务型号:天问一号 搭载平台:环绕器 数据获…