spdk探秘-----RPC

SPDK软件库实现了一个基于JSON-RPC 2.0的服务,以允许外部的管理工具动态地配置基于SPDK软件的服务器应用,或使用监控工具动态地获取SPDK应用的运行状态。目前,JSON-RPC是SPDK软件库中最主要的监控管理工具,SPDK软件库中包含的各个组件均有一些相应的RPC方法供用户调用。未来SPDK软件库会增添更多的RPC方法,来提高管理SPDK各个子系统或模块的灵活性,并减少对静态配置的依赖。

1.RPC

当把整个应用程序散布在互相通信的多个进程中时,一种方式是各个进程可以进行显式的网络编程,通过socket或进程间通信的API来编写交互过程。另一种方式则是使用隐式网络编程,即使用过程调用来完成,这样调用过程中涉及的网络I/O处理或进程间通信的细节,对于开发者而言基本上是透明的,可以省去部分工作量,并提高了开发软件应用的速度。

RPC是指一个应用程序调用不在自己地址空间中的子程序的过程。RPC是一种Client-Server的交互方式,调用发起者为客户端,子程序执行者为Server端,通常通过消息机制完成请求与响应的传递。RPC调用两端的进程既可以处于不同的主机上通过网络来传递消息,也可以在同一主机上通过进程间通信来传递消息。PRC的处理步骤如下。

· 客户端的应用通过RPC接口,写入相关参数。

· 客户端的RPC库将相关参数排列转换为合规的消息,并通过系统调用发出。

· 客户端的操作系统将消息传递到Server端的操作系统。

· Server端的RPC库通过系统调用取出消息,并将消息解析为对应的调用参数。

· Server端的应用通过RPC接口获取到相关参数,并执行对应程序,之后将结果以相反的步骤次序,返回给客户端的应用。

为了提供多样的Server端应用,基于不同服务的实现细节差异,各个RPC系统互不兼容,比如网络文件系统的RPC接口与SUN RPC互不兼容。同时,为了允许不同的客户端访问Server端的应用,实现跨平台服务,目前已有许多标准化的RPC系统出现,比如JSON-RPC协议既可以为Java应用服务,也可以为C、Python等编程语言的应用服务。

2.JSON

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。既易于人阅读和编写,也易于机器解析和生成。JSON包括4个基本类型String、Numbers、Booleans和Null,以及两个结构化类型Objects和Arrays的数据。JSON建立在两个结构上,内容如下。

· 名/值(name/value)对的集合。在各种语言中,名/值对被实现为对象、记录、字典、哈希表或关联数组。

· 有序列表。在大多数语言中,有序列表通常是作为数组、矢量、列表或序列实现的。

这些通用数据结构在几乎所有的现代编程语言中都以不同的形式得到支持。这样一来,编程语言之间的数据交换就可以基于这些数据结构实现了。

典型的JSON语法规则如下。

· JSON名/值对:JSON数据的书写格式是“名/值”对。如,"firstName" : "John"。

· JSON对象:JSON对象在花括号中书写,对象可以包含多个名/值对。如{ "firstName":"John" , "lastName":"Doe" }。

· JSON数组:JSON数组在方括号中书写,数组可以包含多个对象。在下面的例子中,对象 "employees" 是包含3个对象的数组,每个对象代表一条关于某个人(包括姓和名)的记录。spdk探秘-----RPC_第1张图片

3.JSON-RPC

JSON-RPC是RPC的一种规范,一个无状态且轻量级的协议,实现及使用简单。JSON-RPC规范主要定义了一些数据结构及其相关的处理规则,它被允许运行在基于socket、HTTP等许多不同消息传输环境的进程中,并使用JSON作为数据格式。

· JSON-RPC的请求。

发送一个请求对象至服务器端代表一个RPC调用,一个请求对象包含下列成员:jsonrpc,指定JSON-RPC协议版本的字符串,必须准确写为“2.0”;method,包含所要调用方法名称的字符串,以RPC开头的方法名;params,调用方法所需要的结构化参数值,该成员参数可以被省略;id,已建立客户端的唯一标识,值必须包含一个字符串、数值或NULL,如果包含在响应对象,服务器端必须回答相同的值,这个成员用于两个对象之间关联上下文。

例如:

spdk探秘-----RPC_第2张图片

· JSON-RPC的响应。

当发起一个RPC调用时,除通知外,服务器端都必须回复响应。响应表示为一个JSON对象,使用以下成员:jsonrpc,指定JSON-RPC协议版本的字符串,必须准确写为“2.0”;result,该成员在响应成功时必须被包含,服务器端中的被调用方法决定了该成员的值;error,该成员在失败时必须被包含,该成员参数值必须为错误对象;id,该成员必须被包含,该成员值必须与请求对象中的id成员值一致。

响应对象必须包含result或error成员,但两个成员不能被同时包含。

例如:

spdk探秘-----RPC_第3张图片

4.SPDK JSON-RPC

使用SPDK库中的RPC需要首先在SPDK的应用启动时使用“-r”参数指定RPC Server的监听地址,默认地址为“/var/tmp/spdk.sock”。使用SPDK提供的客户端命令行工具“scripts/rpc.py”,可以方便地向SPDK Server端发起RPC调用。使用方法如下:

 

其中,“-s”“-p”参数分别指定SPDK RPC Server端的监听地址和端口,“command”“parameters list”分别指定具体的RPC命令和对应的参数。

获取当前SPDK RPC所能支持的command可以通过命令:rpc.py -h

获取command命令所需要的对应参数可以通过命令:rpc.py  -h

例如:

spdk探秘-----RPC_第4张图片

 

执行delete_bdev RPC方法,内容如下:

spdk探秘-----RPC_第5张图片

spdk探秘-----RPC_第6张图片

下面是一个iSCSI Target使用RPC的例子。

· 在iSCSI Target端的操作。

(1)iSCSI Target程序启动以后,创建portal group,内容如下:

创建portal group完成之后,可以使用如下命令查看所创建的portal group的详细信息:

 

(2)创建initiator group,内容如下:

创建initiator group完成之后,可以使用如下命令查看所创建的initiator group的详细信息:

(3)创建nvme bdev,内容如下:

(4)创建target node,内容如下:

(5)若需要为target node添加lun,可以使用如下命令:

· 在Initiator端的操作。

(1)发现iSCSI Target代码如下:

(2)登录iSCSI Target设备代码如下:

(3)使用如下命令,来查看所有发现的块设备:lsblk

(4)退出iSCSI Target设备代码如下:

5.SPDK JSON-RPC运行机制

在启动SPDK的编程框架时,SPDK将会初始化RPC所需的功能。一个RPC专用的socket文件会被创建在相应的路径上,然后SPDK会绑定并监听它。接下来,SPDK会在Master Core的Reactor上为RPC注册一个Poller,此后RPC所有的功能都会在这个Poller里执行,也就是说,所有SPDK的RPC Server端服务是执行在Master Core上的。

当一个SPDK RPC客户端发出RPC调用请求后,RPC Poller在轮询过程中,接受该连接,接下来接收该连接上客户端发出的请求内容,并解析为JSON请求。在SPDK中已经注册的所有RPC方法中通过逐个对比后,找出对应的方法并执行进入。在RPC的方法中,首先将JSON请求解析成函数执行过程中需要的参数,完成相应的功能。在完成功能后,根据需要填写JSON响应,并将它加入发送队列。RPC Poller在轮询过程中,将该JSON响应发送给SPDK RPC客户端。SPDK JSON RPC设计和实现如图所示。

spdk探秘-----RPC_第7张图片

 

SPDK中JSON-RPC所依赖的代码主要分布在以下4个部分。

· lib/jsonrpc:接收发送网络数据,解析和流化JSON请求。

· lib/rpc:将JSON-RPC适配到SPDK编程框架中。

· lib/json:具体的数据流与JSON结构的解析与流化方法。

· _rpc.c:各个组件中以rpc结尾的C文件,如bdev_malloc_rpc.c,定义并注册具体的SPDK RPC方法。

你可能感兴趣的:(存储)