分布式文件系统平台化API协议设计文档 - shadowofs/RestAPI GitHub Wiki

Revision History

版本 描述 日期 修改人
v0.9 REST API初稿 2014/3/21 佘影
v1.0 流式写入初稿 2014/3/21 童锁
v1.1 评审修订 2014/3/25 佘影
v1.2 更新PATCH 2014/4/8 佘影
v1.3 修正后缀 2014/5/6 佘影
v1.4 去除Location,List方法增加参数仅返回文件名 2014/6/16 佘影
v1.5 还原Location,修改Stream协议描述,增加Stream协议的读操作 2014/6/30 佘影
v1.6 增加checksum和recover两种方法 2014/6/30 佘影
v1.7 loc方法兼容社区 2014/9/10 佘影
v1.8 支持hardlink 2014/9/12 佘影

Motivation

当前API过于底层,导致Client端需要处理各种异常,Client被迫纠缠于繁冗的异常处理逻辑中。系统只提供了java的客户端,非java用户只能通过shell或者内嵌jvm的方式来使用,使用起来非常不方便,比较好的方法是实现一个非java客户端,但是现阶段由于实现难度过大,可能性几乎为0。

为了以后方便提供非java版的客户端,以及更遥远的支持公有云的目标,因此需要有一套比较开放的协议。比较好的选择是提供HTTP+JSON的RESTFUL API,HTTP协议已经比较成熟,用得很广,JSON同样,用HTTP+JSON前期测试和开放都很方便。但仅仅是REST API是不够的,REST方式写数据要么是整个文件一次传输,要么是拆成很多小的package,但是前一种方案无法满足错误恢复的需求,后一种方案又不能保证吞吐,因此还需要支持流式写数据。

Terminology

Name Description
REST 含状态传输(英文:Representational State Transfer,简称REST)通常基于使用HTTP,URI,和XML以及HTML这些现有的广泛流行的协议和标准。REST风格中,资源是由URI来指定,对资源的操作包括获取、创建、修改和删除资源,这些操作正好对应HTTP协议提供的GET、POST、PUT和DELETE方法。
MPA 元数据代理(Meta Proxy Adapter)完成Client的元数据操作请求
DPA 数据代理(Data Proxy Adapter)完成Client的流式数据读写请求,通常与Client部署在同节点,Client也可以指定数据代理

Architecture

平台化API从架构上分为两层,元数据代理和数据代理。元数据代理为当前系统的Adapter角色。数据代理又分为Http协议数据代理和流式协议数据代理,Http协议代理为集群的DataNode,Client访问MPA的时候,如果是读写请求,会被重定向到某个DN来完成读写请求;流式协议的代理跟随Client部署在同节点,之所以采用这个架构主要是考虑以下几点:

  • 如果将两个代理合二为一,都放在Client端,那么如果Client ls一个超大的目录,可能会导致代理内存飙升
  • 之所以选择Adapter作为元数据代理是由于Adapter都是Master机器,内存大,并且当前CPU也比较闲
  • Http协议代理与流式协议数据代理分开主要考虑到Http协议尽量保证用户能够直接用,比如wget能够直接使用,如果还需要再在本地部署一个数据代理就很不方便了
  • 流式读写主要满足高吞吐和容错的读写需求,将流式读写数据代理放在Client端,Client可以做成请求应答的模式,实现简单不容易出错,写入由于是本地socket不走网卡,所以性能能够保证

Data Validation

集群内部存储的数据每512字节都会有4字节的校验数据,每14天集群会对所有数据块的校验数据进行比对,发现有corrupt的文件会自动进行数据恢复。另外,在集群内部的数据传输都会在接受端做数据校验,例如Proxy在读取DN的数据时,会经过校验后再返回给Client,如果发现不一致会自动换到下一个副本,对Client透明。除非所有副本校验都失败,会报错给Client。

所以,理论上Client可以无需对数据进行二次校验(除非是本机数据代理到Client的网络出错,但几率相比数据节点磁盘故障的要小很多)。一期暂时先不提供数据校验的接口,后续有需要再考虑。

Charset

请求及返回结果都使用 UTF-8 字符集进行编码。

REST API

本节包含HTTP REST API的介绍,通过调用REST的API,可以完整地实现以前FileSystem包含的接口。

下面的例子实现了从集群中删除一个文件的操作。

DELETE /restfs/v1/testFile HTTP/1.1
Host: szwg-ecomon-hdfs.dmop.baidu.com:54310
Date: Tue Mar 18 15:05:04 CST 2014
x-baidu-ugi: <Ugi>
x-bce-request-id: <requestID> 

目前支持方法和操作类型说明如下:

Method Name Description
PUT 修改资源属性
POST 创建资源或者追加写入
DELETE 删除资源
GET 获取资源

Operations

一期API实现了以下操作:

Common Request Headers

下面的表格描述了REST API各类请求可能用到的header。

Header Name Description Example Required
Host 请求服务的URI,一期暂时为当前各集群的地址 Host: szwg-ecomon-hdfs.dmop.baidu.com:54310 必选
Date 请求提交时候请求端的时间 Date: Tue Mar 18 15:10:22 CST 2014 可选
Content-Length 请求body的byte长度(不包括请求头部),参考RFC 2616 Content-Length: 1024 请求携带body的请求为必须
x-baidu-ugi 用户访问集群时所使用的用户名和密码 x-baidu-ugi: eky,123456 必选
x-baidu-credential 使用新门神登陆之后的认证信息,Server端会使用公钥来解密这个票据,得到用户对应的角色 参见 Authentication 可选
x-bce-request-id 所有请求都应该唯一地对应一个ID,可用于问题定位、性能分析等等多个场景。requestId使用UUID version 4,暂时由各服务自行生成,后续考虑统一由BFE生成。 x-bce-request-id: 9899dc5a-c5c7-4175-b851-0eef65cb6543 必选
x-baidu-excluded-node 选择DPA时,excluded的节点集合,用逗号分隔 10.220.30.43,10.220.30.45 可选

Common Response Headers

下面的表格描述了响应中包含的header。

Header Name Description Example
Content-Length 响应body的长度(bytes),如果未携带表示Chunked传输模式 Content-Length: 0
Content-MD5 请求文件资源的MD5值,参考RFC 2616,在调用获取资源Checksum时会返回此Header Content-MD5: fb817de5edfb53e6b7a7bf043c2ae6f5
Content-Type 响应的MIME类型 Content-Type: application/json
Date Server响应请求的时间 Date: Tue Mar 18 15:10:22 CST 2014
Location 读写请求数据代理所在的URI,响应Http协议的数据读写请求 Location: http://10.215.139.31:7001
Transfer-Encoding 设置为chunked表示响应长度不确定,通过http chunk传输协议确定长度,参加Chunked Transfer Coding Transfer-Encoding: chunked
x-bce-request-id 所有请求都应该唯一地对应一个ID,可用于问题定位、性能分析等等多个场景。requestId使用UUID version 4,暂时由各服务自行生成,后续考虑统一由BFE生成。 x-bce-request-id: 9899dc5a-c5c7-4175-b851-0eef65cb6543

URI Suffix

Http Get方法表示获取一个资源,我们使用Get方法来实现获取资源的属性(Get Attributes)、内容(Get Content)、位置(Get Location)以及列举资源操作(Get Listing)。三种语义通过URI后缀来区分,默认的语义为Get Content,各后缀名和意义如下表:

Operation Suffix Description
Get Attributes attr 获取资源的属性信息
Get Content content 获取资源的内容,对目录调用Get Content会返回异常,错误码为Conflict(该方法只在数据代理上支持)
Get Listing list 对目标资源执行ls操作,语义同linux文件系统,即对于目录返回所有child的属性信息,对于文件则返回目标资源的属性信息
Get Location loc 获取资源的位置信息,对于目录返回所有child的位置,对于文件则返回目标资源的位置
Get Checksum checksum 获取资源的checksum,仅对文件有效

后缀与Path通过冒号(:)分隔,请求格式如下:

GET /restfs/v1/<Path>:<Suffix> HTTP/1.1
Host : <Host>:<Port>
x-baidu-ugi	: <ugi>
x-bce-request-id: <requestID> 

URI后缀默认为content,因此获取资源内容时可以省略。

Error Responses

调用接口出错后,将不会返回结果数据。调用方可根据错误码和错误信息来定位错误原因。 当调用出错时,HTTP 请求返回一个 4xx 或 5xx 的 HTTP 状态码,返回的消息体中是具体的错误代码及错误信息和requestId。

例如:

HTTP/1.1 404 Not Found
Date: Wed, 12 Oct 2009 17:50:00 GMT 
Content-Type: application/json
Content-Length: 104
x-bce-request-id: 9899dc5a-c5c7-4175-b851-0eef65cb6543 

{
	"requestId"		: "9899dc5a-c5c7-4175-b851-0eef65cb6543",
	"code"    		: "NoSuchObject",
	"message"      	: "File does not exist: /nonExist"
}

下表列出了所有errorCode和其含义:

Error Code Description HTTP Status Code
BadDigest 请求MD5与内容不匹配 400 Bad Request
Conflict 语义冲突 409 Conflict
EOF truncate操作越过文件末尾 400 Bad Request
IncompleteBody 请求长度与HTTP头部指定的Content-Length不匹配 400 Bad Request
InsufficientStorage 超quota 507 Insufficient Storage
InternalError 服务器内部错误,包括读到坏块,服务不可用等 500 Internal Server Error
InvalidArgument 非法参数 400 Bad Request
InvalidConnectionID ConnectionID不存在 400 Bad Request
InvalidRange Range越界或参数不合法 416 Requested Range Not Satisfiable
InvalidURI 无法解析URI 400 Bad Request
MethodNotAllowed 不支持该方法 405 Method Not Allowed
MissingContentLength 请求需要指定Content-Length 411 Length Required
MissingSecurityElement 请求未发送UGI 400 Bad Request
NonAuthorized 用户权限验证失败 403 Forbidden
NoSuchObject 找不到请求的对象 404 Not Found
SlowDown 降低请求频度 503 Slow Down

Authentication

一期需要支持两种方式的认证,Hadoop Ugi和Giano,传输采用明文方式(内网环境可以不用考虑被监听)。Ugi验证需要在Header中指定x-baidu-ugi,Giano方式需要在Header中指定指定x-baidu-credential,两种方式二选一。每个请求都需要附带验证信息,这样做的好处是可以做到请求无状态。

使用ugi方式来验证需要附带x-baidu-ugi头部信息,请求语法如下:

DELETE /restfs/v1/testFile HTTP/1.1
Host: szwg-ecomon-hdfs.dmop.baidu.com:54310
x-baidu-ugi: eky,123456
x-bce-request-id: <requestID> 

使用ugi方式来验证需要附带x-baidu-ugi头部信息,请求语法如下:

DELETE /restfs/v1/testFile HTTP/1.1
Host: szwg-ecomon-hdfs.dmop.baidu.com:54310
x-baidu-credential: CtQCCo8CCiQ2ZDhlMzExYS04YzkyLTQ2MzMtYmI5YS0wM2VjM2ZjYmJlOTkSB0JBQVNfQ0EaLwoJc2hleWluZzAxEg5iYWFzX2FsbF9yb2xlcyISYmFhc19kZWZhdWx0X2dyb3VwIp4BLS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1FWUNRUURLTVh2Vkd2QUdWeXVIMU9sdWh5NWQ3WjQvVzJpcjVNUjhEQnIxWG9LNTVmWC9oWjc4aEZ4cm92djMKMlRMYVkzT3h0OXFiejFNcWU1R0tZMW5xREVZUkFnRUQKLS0tLS1FTkQgUlNBIFBVQkxJQyBLRVktLS0tLQoosMnWzP1RMLCJkurYdhJAlvMQ87dmATCQu71uDmf35b9OYOeZ7kD4TihpjNjA7v0ZI68ABuR4AaaRGWv/U0lddh8CWJSwYp+9yXZExfFGQRJcChgKCXNoZXlpbmcwMRiKrq/8ASDIh+nN/VESQEYLHlXWAtnv+hHJhPfW/an4ezmW9Ng8Fp0ek+kB0IKXKslfJLHBtBObvVqVQqUnWr1oG5CmlnnnJfgFvQ7dX2k=
x-bce-request-id: <requestID> 

Hadoop Ugi为原有的校验方式,Giano校验需要依赖Giano的Library来login生成Credential,具体接口和使用方法请参考Giano

StatFS

StatFS请求由MPA处理,该请求获取当前文件系统的状态信息,包括存储已使用容量和剩余容量大小。

Request Syntax

GET /restfs/v1 HTTP/1.1
Host: <HOST>:<PORT>
x-baidu-ugi: <ugi>
x-bce-request-id: <requestID> 

Request Parameters

该方法没有特殊的parameter。

Request Headers

该方法没有特殊的header。

URI Suffix

该方法不支持URI Suffix。

Response Status Code

HTTP Status Code Description
200 OK 正常响应
403 Forbidden 无访问权限
500 Internal Server Error Server内部错误,异常信息包含在body中

Response Headers

该方法响应没有特殊的header。

Response Body

响应Body为json对象,各字段含义如下:

Name Type Description
used Number 存储系统已使用空间大小(bytes)
avail Number 存储系统剩余空间大小(bytes)
capacity Number 存储系统总容量(bytes)

Examples

如果操作成功,Server可能会返回如下的响应:

HTTP/1.1 200 OK
Date: Wed, 12 Oct 2009 17:50:00 GMT 
Content-Type: application/json
Content-Length: 104
x-bce-request-id: <requestID> 

{
	"used"     : 20524013415132,
	"avail"    : 23881916491780,
	"capacity" : 43668113649217
}

Delete

Delete请求由MPA处理,用于删除用户指定的集群路径的一个资源(文件 or 目录)。

Request Syntax

DELETE /restfs/v1/<PATH> HTTP/1.1
Host: <HOST>:<PORT>
x-baidu-ugi: <ugi>
x-bce-request-id: <requestID> 

Request Parameters

Parameter Name Description Example Default
recursive 是否递归删除文件,如果指定为false,删除一个非空目录时会返回异常,错误码为Conflict true true

Request Headers

该方法没有特殊的header。

URI Suffix

该方法不支持URI Suffix。

Response Status Code

HTTP Status Code Description
204 NoContent 删除成功
404 Not Found 待删除文件不存在
409 Conflict 删除目录非空,且参数recursive指定为false
403 Forbidden 无访问权限
500 Internal Server Error Server内部错误,删除文件/目录失败,错误原因会包括在body中

Response Headers

该方法响应没有特殊的header。

Response Body

该方法响应没有Body。

Examples

例如,要删除hdfs://szwg-ecomon-hdfs.dmop.baidu.com:54310/testFile这个文件的请求:

DELETE /restfs/v1/testFile HTTP/1.1 
Host: szwg-ecomon-hdfs.dmop.baidu.com:54310
x-baidu-ugi: eky,123456
x-bce-request-id: 9899dc5a-c5c7-4175-b851-0eef65cb6543 

删除成功,Server会返回如下的响应:

HTTP/1.1 204 NoContent 
Date: Wed, 12 Oct 2009 17:50:00 GMT 
Content-Length: 0
x-bce-request-id: 9899dc5a-c5c7-4175-b851-0eef65cb6543 

如果删除失败,则Server会根据失败的原因返回不同的状态码。例如,待删除文件不存在会返回:

HTTP/1.1 404 Not Found
Date: Wed, 12 Oct 2009 17:50:00 GMT 
Content-Type: application/json
Content-Length: 104
x-bce-request-id: 9899dc5a-c5c7-4175-b851-0eef65cb6543 

{
	"requestID" : "9899dc5a-c5c7-4175-b851-0eef65cb6543" 
	"code"    	: "NoSuchObject",
	"message"   : "File does not exist: /testFile"
}

Get Content

Get Content请求由MPA转发给DPA处理,用来读取一个文件的内容,如果对一个目录调用Get Content则返回异常,错误码为Conflict。

Request Syntax

GET /restfs/v1/<PATH>[:content] HTTP/1.1
Host: <HOST>:<PORT>
x-baidu-ugi: <ugi>
x-bce-request-id: <requestID> 

Request Parameters

该方法不支持参数设置。

Request Headers

Header Name Description Example Default
Range 用来指定读取的范围 Range: 0-1024 Range: 0-<FILE_LEN>

URI Suffix

请求后缀表示请求期望访问对象的类型,参见URI Suffix。请求资源内容的后缀为content,默认后缀也是content,因此可以设置为content或者不设置。

Response Status Code

HTTP Status Code Description
200 OK 正常返回
404 Not Found 文件不存在
403 Forbidden 无访问权限
409 Conflict Get Content不支持访问目录
500 Internal Server Error Server内部错误,无法获取文件/目录内容,错误原因会包括在body中

Response Headers

Header Name Description Example
Location Http协议数据代理所在的URI Location: http://10.215.139.31:7001

Response Body

Response body为读取文件的内容。

Examples

例如,要获取hdfs://szwg-ecomon-hdfs.dmop.baidu.com:54310/example的内容,Client的提交如下请求到MPA:

GET /restfs/v1/example HTTP/1.1
Host: szwg-ecomon-hdfs.dmop.baidu.com:54310
x-baidu-ugi: eky,123456
x-bce-request-id: 9899dc5a-c5c7-4175-b851-0eef65cb6543

MPA响应307 TEMPORARY_REDIRECT将请求重定向到某个DN节点,由其代理执行:

HTTP/1.1 307 TEMPORARY_REDIRECT
Date: Wed, 12 Oct 2009 17:50:00 GMT
Location: http://<DATAPROXY>:<PORT>
Content-Length: 0

Client遵从重定向,获取的数据响应如下:

HTTP/1.1 200 OK
Date: Wed, 12 Oct 2009 17:50:00 GMT
Content-Type: application/octet-stream
Content_Length: 10
x-bce-request-id: 9899dc5a-c5c7-4175-b851-0eef65cb6543

Hello, eky!

Locate Resource

Locate Resource请求由MPA处理,用来获取资源的所有副本位置,如果资源为文件,返回的结果为该文件的所有block的副本位置;如果资源为目录,返回的结果为目录包含的一级文件的所有block的副本位置。

Request

请求格式如下:

Get /restfs/v1/<PATH>:loc HTTP/1.1
Host: <HOST>:<PORT>
x-baidu-ugi: <ugi>
x-bce-request-id: <requestID> 

Request Parameters

该方法没有特殊的Parameter。

Request Headers

该方法没有特殊的Header。

URI Suffix

URI后缀表示请求期望访问对象的类型,参见URI Suffix。请求获取资源的副本位置操作需要显示指定URI后缀为loc。

Response Status Code

HTTP Status Code Description
200 OK 正常响应
403 Forbidden 无访问权限
404 Not Found 资源不存在
500 Internal Server Error Server内部错误,异常信息包含在body中

Response Headers

该方法响应没有特殊的header。

Response Body

Server响应的body为json对象,每个数组成员为路径下的文件所包含所有块的副本信息,json对象各包含的字段和解释如下:

Name Type Description
basedir String 父目录绝对路径
children Array 父目录包含的所有子节点信息
atime Number 资源的访问时间,自1970年1月1日0时起的毫秒数,目录的atime为0
bsize Number 资源的块大小,目录的块大小为0
group String 资源的组名称
len Number 资源的大小,目录大小为0
mtime Number 资源的修改时间,自1970年1月1日0时起的毫秒数
owner String 资源的所有者
name String 资源的名字(不包含路径信息)
perm String 资源的权限信息,包含所有者权限、同组权限和其他权限,用9个字符的字符串表示,例如:"rwxr-xr-x"
repl Number 资源的副本数,目录的副本数表示该目录的直接child的默认副本
type String 表示资源是目录还是文件,取值为[FILE, DIRECTORY]
chunks Array 文件包含的所有块信息

Example

如果资源是一个文件,那么返回的结果是:

HTTP/1.1 200 OK
Date: Wed, 12 Oct 2009 17:50:00 GMT 
Content-Type: application/json
Transfer-Encoding: chunked
x-bce-request-id: 9899dc5a-c5c7-4175-b851-0eef65cb6543

{
	"basedir"	:	<parentDir>,
	"children"	:		
	[
		{
			"name"      	: "aFile",
			"atime"      	: 1320173277227,
			"bsize"       	: 268435456,
			"group"   		: "eky",
			"len"          	: 268435456,
			"mtime"			: 1320173277227,
			"owner"   		: "eky",
			"perm"     		: "r--------",
			"repl"   		: 3,
			"type"     		: "FILE" 
			"chunks"		:
			[
				[
					"10.215.139.31","10.215.139.32","10.215.139.33"
				],
				...
			]
		}
	]
}

如果访问的资源是目录,children字段会包含该目录下所有子文件的块信息:

HTTP/1.1 200 OK
Date: Wed, 12 Oct 2009 17:50:00 GMT 
Content-Type: application/json
Transfer-Encoding: chunked
x-bce-request-id: 9899dc5a-c5c7-4175-b851-0eef65cb6543

{
	"basedir"	:	<parentDir>,
	"children"	:	
	[
		{
			"name"      	: "aFile",
			"atime"      	: 1320173277227,
			"bsize"       	: 268435456,
			"group"   		: "eky",
			"len"          	: 268435456,
			"mtime"			: 1320173277227,
			"owner"   		: "eky",
			"perm"     		: "r--------",
			"repl"   		: 3,
			"type"     		: "FILE" 
			"chunks"		:
			[
				[
					"10.215.139.31","10.215.139.32","10.215.139.33"
				],
				...
			]
		},
		{
			"name"      	: "aDirectory",
			"atime"      	: 1320173277227,
			"bsize"       	: 268435456,
			"group"   		: "eky",
			"len"          	: 0,
			"mtime"			: 1320173277227,
			"owner"   		: "eky",
			"perm"     		: "r--------",
			"repl"   		: 3,
			"type"     		: "Directory" 
			"chunks"		: []
		},
		...
	]
}

Get Attributes

Get Attributes请求由MPA处理,用来获取一个资源(目录 or 文件)的属性信息。

Request

GET /restfs/v1/<PATH>:attr HTTP/1.1
Host: <HOST>:<PORT>
x-baidu-ugi: <ugi>
x-bce-request-id: <requestID>

Request Parameters

该方法不支持参数设置。

Request Headers

该方法无特殊头部。

URI Suffix

请求后缀表示请求期望访问对象的类型,参见URI Suffix。请求资源属性的后缀为attr,必须显示在URI中指定。

Response Status Code

HTTP Status Code Description
200 OK 正常返回
404 Not Found 文件/目录不存在
403 Forbidden 无访问权限
500 Internal Server Error Server内部错误,无法获取文件/目录的属性,错误信息会包括在body中

Response Headers

该方法响应没有特殊的header。

Response Body

Get Attributes方法的响应为Json对象,该对象包括的字段名和各字段的解释如下:

Name Type Description
atime Number 资源的访问时间,自1970年1月1日0时起的毫秒数,目录的atime为0
bsize Number 资源的块大小,目录的块大小为0
group String 资源的组名称
len Number 资源的大小,目录大小为0
mtime Number 资源的修改时间,自1970年1月1日0时起的毫秒数
owner String 资源的所有者
name String 资源的名字(不包含路径信息)
perm String 资源的权限信息,包含所有者权限、同组权限和其他权限,用9个字符的字符串表示,例如:"rwxr-xr-x"
repl Number 资源的副本数,目录的副本数表示该目录的直接child的默认副本
type String 表示资源是目录还是文件,取值为[FILE, DIRECTORY]

Examples

例如,下面的请求获取了hdfs://szwg-ecomon-hdfs.dmop.baidu.com:54310/example的属性信息:

GET /restfs/v1/example:attr HTTP/1.1
Host: szwg-ecomon-hdfs.dmop.baidu.com:54310
x-baidu-ugi: eky,123456
x-bce-request-id: 9899dc5a-c5c7-4175-b851-0eef65cb6543

MPA会以json格式返回文件/目录的属性信息:

HTTP/1.1 200 OK
Date: Wed, 12 Oct 2009 17:50:00 GMT
Content-Type: application/json
Content-Length: 140
x-bce-request-id: 9899dc5a-c5c7-4175-b851-0eef65cb6543

{
	"atime"      	: 0,
	"bsize"       	: 0,
	"group"   		: "eky",
	"len"          	: 0,
	"mtime"			: 1320173277227,
	"owner"   		: "eky",
	"name"      	: "example",
	"perm"     		: "r--------",
	"repl"   		: 3,
	"type"     		: "DIRECTORY" 
}

Get Listing

Get Listing请求由MPA处理,语义同linux shell中的ls,对于目录返回一个该目录所有child属性信息,对于文件则是返回该文件的属性信息。考虑到在表达单个文件和包含单个文件的目录时存在歧义,所以增加了一个basedir的字段,用来表述返回对象的公共父节点绝对路径。

Request

GET /restfs/v1/<PATH>:list HTTP/1.1
Host: <HOST>:<PORT>
x-baidu-ugi: <ugi>
x-bce-request-id: <requestID>

Request Parameters

Parameter Name Description Example Default
details 是否显示所有属性,默认为false,仅显示资源名称 true false

Request Headers

该方法没有特殊的Header。

URI Suffix

请求后缀表示请求期望访问对象的类型,参见URI Suffix。Get Listing方法的后缀为list,必须显示在URI中指定。

Response Status Code

HTTP Status Code Description
200 OK 正常返回
404 Not Found 目录不存在
403 Forbidden 无访问权限
500 Internal Server Error Server内部错误,无法获取文件/目录的属性,错误信息会包括在body中

Response Headers

该方法响应没有特殊的header。

Response Body

Get Listing方法的响应结果为json对象,所有字段的解释如下:

Name Type Description
basedir String 父目录绝对路径
children Array 父目录包含的所有子节点信息
atime Number 资源的访问时间,自1970年1月1日0时起的毫秒数,目录的atime为0
bsize Number 资源的块大小,目录的块大小为0
group String 资源的组名称
len Number 资源的大小,目录大小为0
mtime Number 资源的修改时间,自1970年1月1日0时起的毫秒数
owner String 资源的所有者
name String 资源的名字(不包含路径信息)
perm String 资源的权限信息,包含所有者权限、同组权限和其他权限,用9个字符的字符串表示,例如:"rwxr-xr-x"
repl Number 资源的副本数,目录的副本数表示该目录的直接child的默认副本
type String 表示资源是目录还是文件,取值为[FILE, DIRECTORY]

Examples

默认不指定details为true的情况下,MPA的响应类似于:

HTTP/1.1 200 OK
Date: Wed, 12 Oct 2009 17:50:00 GMT
Content-Type: application/json
Transfer-Encoding: chunked
x-bce-request-id: 9899dc5a-c5c7-4175-b851-0eef65cb6543

{
	"basedir"	:	"/example",
	"children"	:
	[
		{
			"name"      	: "aDirectory",
			"type"     		: "DIRECTORY" 
		},
		{
			"name"      	: "aFile",
			"type"     		: "FILE" 
		},
		...
	]	
}

当用户指定了details为true时,MPA返回的结果会包含完整的信息:

HTTP/1.1 200 OK
Date: Wed, 12 Oct 2009 17:50:00 GMT
Content-Type: application/json
Transfer-Encoding: chunked
x-bce-request-id: 9899dc5a-c5c7-4175-b851-0eef65cb6543

{
	"basedir"	:	"/example",
	"children"	:
	[
		{
			"atime"      	: 0,
			"bsize"       	: 0,
			"group"   		: "eky",
			"len"          	: 0,
			"mtime"			: 1320173277227,
			"owner"   		: "eky",
			"name"      	: "aDirectory",
			"perm"     		: "r--------",
			"repl"   		: 3,
			"type"     		: "DIRECTORY" 
		},
		{
			"atime"      	: 1320173277227,
			"bsize"       	: 268435456,
			"group"   		: "eky",
			"len"          	: 10,
			"mtime"			: 1320173277227,
			"owner"   		: "eky",
			"name"      	: "aFile",
			"perm"     		: "r--------",
			"repl"   		: 3,
			"type"     		: "FILE" 
		},
		...
	]
}

Set Attribute/Path

Set Attribute请求由MPA处理,用来更改一个文件/目录的属性信息。包括文件副本,文件长度截断,或者将已有的文件/目录重命名到新的路径下。目前暂时仅支持一个请求修改一个属性信息。

Request

PUT /restfs/v1/<PATH> HTTP/1.1
Host: <HOST>:<PORT>
x-baidu-ugi: <ugi>
x-bce-request-id: <requestID>

Request Parameters

Parameter Name Description Example Default
permission 文件/目录的访问权限,3位8进制的数 755 <CURRENT_PERMISSION>
replication 文件/目录的副本数,可以设置[1,100]的值 3 <CURRENT_REPLICATION>
mtime 文件/目录的修改时间 1320173277227 <CURRENT_MTIME>
atime 文件的访问时间(目录不记录访问时间) 1320173277227 <CURRENT_ATIME>
owner 文件的所有者,只有root权限才能做修改操作 eky <CURRENT_OWNER>
group 资源的组名称,只有root权限才能做修改操作 eky <CURRENT_GROUP>
path 文件的路径,设置该参数表示将文件/目录重命名到新的路径下 /dstPath <CURRENT_PATH>
length 文件的长度,截断文件到指定长度,如果长度为负值,则表示对文件做recover操作 0 <CURRENT_LEN>

Request Headers

该方法没有特殊的Header。

URI Suffix

该方法不支持URI Suffix。

Response Status Code

HTTP Status Code Description
200 OK 正常返回
400 Bad Request 请求参数错误,例如截断长度越界
404 Not Found 文件/目录不存在
403 Forbidden 无访问权限
500 Internal Server Error Server内部错误,无法设置文件/目录的属性,错误原因会包括在body中

Response Headers

该方法响应没有特殊的header。

Response Body

该方法响应没有Body。

Example

下面的请求设置文件/example的副本为20:

PUT /restfs/v1/example?replication=20 HTTP/1.1
Host: szwg-ecomon-hdfs.dmop.baidu.com:54310
x-baidu-ugi: eky,123456
x-bce-request-id: 9899dc5a-c5c7-4175-b851-0eef65cb6543

Client收到的响应格式如下:

HTTP/1.1 200 OK
Date: Wed, 12 Oct 2009 17:50:00 GMT
Content-Length: 0
x-bce-request-id: 9899dc5a-c5c7-4175-b851-0eef65cb6543

通过path参数可以将指定路径下的文件/目录重命名到新的路径下,例如:

PUT /restfs/example?path=/destPath HTTP/1.1
Host: szwg-ecomon-hdfs.dmop.baidu.com:54310
x-baidu-ugi: eky,123456
x-bce-request-id: 9899dc5a-c5c7-4175-b851-0eef65cb6543

Create File/Directory

Create分为创建文件和创建目录,通过URI的格式来区别两种操作,以非/结尾的URI表示创建文件,以/结尾的URI表示创建目录。创建文件/目录需要对该目录的写权限,如果收到创建成功的响应,那么该文件可以确保已经成功创建,否则会收到响应的报错信息。创建文件包括创建通常文件和创建hardlink,通过是否有参数linkTarget来区分。

对于创建文件的Case,参数append为true表示追加写入,append为false且overwrite为true表示覆盖已有文件。另外创建文件/目录时,可以通过参数指定文件/目录的属性。

创建文件分为两个步骤,创建文件的元数据,和实际的数据写入。元数据请求发给MPA,MPA完成原数据操作后会响应201 Created,将请求重定向到某个DN完成剩余的数据协议。如果采用Http协议写入,Client可以遵从MPA的重定向,将携带数据的请求发给DN完成数据写入。Client也可以采用流式协议来写入,完成元数据创建后,同本地数据代理完成剩余的数据写入工作,参见Stream协议。Client可以根据需求自行选择合适的写入模式。

创建目录请求直接由MPA完成,并响应成功或失败。

Request

POST /restfs/v1/<PATH> HTTP/1.1
Host: <HOST>:<PORT>
x-baidu-ugi: <UGI>
x-bce-request-id: <requestID>

Request Parameters

Parameter Name Description Default
append 是否追加写入,设置为true表示追加写入 false
overwrite 写入文件时是否覆盖已有文件 true
permission 文件/目录的访问权限,3位8进制的数 755
replication 文件/目录的副本数,可以设置[1,100]的值 3
linktarget 创建hardlink的target文件,该参数具有最高优先级,指定之后创建的hardlink文a件的所有属性和target null
blocksize 文件的块大小 268435456

Request Headers

该方法不支持特殊的header。

Response Status Code

HTTP Status Code Description
200 OK 正常返回
403 Forbidden 无访问权限
409 Conflict 指定路径上已存在文件/目录
500 Internal Server Error Server内部错误,创建文件/目录,错误原因会包括在body中

Response Headers

Header Name Description Example
Location Http协议数据代理所在的URI Location: http://10.215.139.31:7001

Response Body

该方法响应没有Body。

Examples

Create操作分为创建文件和创建目录,通过URI的格式来区别两种操作,以/结尾表示目录。

  1. 创建文件需要先向元数据代理提交一个不带数据的POST请求来创建文件的INODE,创建文件/example的INODE请求如下:

     POST /restfs/v1/example HTTP/1.1
     Host: szwg-ecomon-hdfs.dmop.baidu.com:54310
     x-baidu-ugi: eky,123456
     x-bce-request-id: 9899dc5a-c5c7-4175-b851-0eef65cb6543
    

    返回的响应格式如下:

     HTTP/1.1 201 Created
     Date: Wed, 12 Oct 2009 17:50:00 GMT
     Content-Length: 0
     Location: http://10.215.139.31:7001
     x-bce-request-id: 9899dc5a-c5c7-4175-b851-0eef65cb6543
    

    Location表示Http协议数据代理的URI,ClienT再提交另一个携带写入数据的HTTP请求到Location指定的数据代理:

     POST /restfs/v1/<PATH> HTTP/1.1
     Host: <LOCAL_HOST>:7001
     Content-Length: 11434
     Content-Type: text/plain 
     x-baidu-ugi: eky,123456
     x-bce-request-id: 9899dc5a-c5c7-4175-b851-0eef65cb6543
    
     [11434 bytes of object data]
    

    写入完成请求方会接受到201 Created的响应:

     HTTP/1.1 200 OK
     Date: Wed, 12 Oct 2009 17:50:00 GMT
     Content-Length: 0
     x-bce-request-id: 9899dc5a-c5c7-4175-b851-0eef65cb6543
    
  2. 创建目录/example/的请求如下:

     POST /restfs/v1/example/ HTTP/1.1
     Host: szwg-ecomon-hdfs.dmop.baidu.com:54310
     x-baidu-ugi: eky,123456
     x-bce-request-id: 9899dc5a-c5c7-4175-b851-0eef65cb6543
    

    Client收到的请求格式如下:

     HTTP/1.1 201 Created
     Date: Wed, 12 Oct 2009 17:50:00 GMT
     Content-Length: 0
     x-bce-request-id: 9899dc5a-c5c7-4175-b851-0eef65cb6543
    
  3. 创建hardlink的/hardlink/的请求如下:

     POST /restfs/v1/hardlink HTTP/1.1
     Host: szwg-ecomon-hdfs.dmop.baidu.com:54310
     x-baidu-ugi: eky,123456
     x-bce-request-id: 9899dc5a-c5c7-4175-b851-0eef65cb6543
    

    Client收到的请求格式如下:

     HTTP/1.1 201 Created
     Date: Wed, 12 Oct 2009 17:50:00 GMT
     Content-Length: 0
     x-bce-request-id: 9899dc5a-c5c7-4175-b851-0eef65cb6543
    

Checksum

Checksum请求由MPA处理,用来获取一个文件的md5值,对目录调用checksum方法会返回Conflict.

Request

GET /restfs/v1/<PATH>:checksum HTTP/1.1
Host: <HOST>:<PORT>
x-baidu-ugi: <ugi>
x-bce-request-id: <requestID>

Request Parameters

该方法不支持参数设置。

Request Headers

该方法没有特殊的Header。

URI Suffix

请求后缀表示请求期望获取对象的md5值,参见URI Suffix。请求资源属性的后缀为checksum,必须显示在URI中指定。

Response Status Code

HTTP Status Code Description
200 OK 正常返回
400 Bad Request 请求参数错误
404 Not Found 文件/目录不存在
403 Forbidden 无访问权限
409 Conflict 无法对目录类型资源获取checksum
500 Internal Server Error Server内部错误,无法设置文件/目录的属性,错误原因会包括在body中

Response Headers

该方法响应没有特殊的header。

Response Body

该方法响应没有Body。

Example

下面的请求设置文件/example的副本为20:

PUT /restfs/v1/example:checksum HTTP/1.1
Host: szwg-ecomon-hdfs.dmop.baidu.com:54310
x-baidu-ugi: eky,123456
x-bce-request-id: 9899dc5a-c5c7-4175-b851-0eef65cb6543

Client收到的响应格式如下:

HTTP/1.1 200 OK
Date: Wed, 12 Oct 2009 17:50:00 GMT
Content-Length: 0
Content-MD5: fb817de5edfb53e6b7a7bf043c2ae6f5
x-bce-request-id: 9899dc5a-c5c7-4175-b851-0eef65cb6543

Stream

相对于Http协议而言,流式协议可以既满足错误恢复的需求,又保证吞吐,适用于对性能要求比较高的情况。流式协议的数据代理部署在Client本地,这样Client可以简单地实现成请求应答的形式,因为本地socket不走网卡,所以性能能够保证。

Stream协议目前只支持数据流,Client通过Socket向本地数据代理建立连接,通信包由 headerbody 组成。 元数据操作需要先向MPA发送请求,因此写入的流程如下图:

Stream协议除了写入,还支持读和恢复写两种操作。这三种操作无需访问MPA,直接向本地的DPA发起Connect请求,在Op中指明即可。

Message Syntax

STRM
<HEADER-LEN>
<HEADER>
<BODY-LEN>
<BODY>

放问的请求和应答都是以上面的格式来发送,各字段解释如下:

STRM			:	4 bytes magic header
<HEADER-LEN>	:	4 bytes int
<HEADER>		:	total length is <HEADER-LEN>
<BODY-LEN>		:	4 bytes int
<BODY>			:	<BODY-LEN> bits of data

Header Syntax

<HEADER>		:	n * <HEADER-LINE>
<HEADER-LINE>	:	<key>=<value>LF
LF				:	\n
<key>,<value>	:	any bytes of data

Connect

Stream协议进行读写,Client需要先创建连接,参数必须要指明RequestID,用来区别不同的请求。Connect的响应中会包含ConnectionID,后续所有的请求都需要包含Connect请求响应中相同的ConnectID,否则会报错。

创建连接请求必须以字符串STREAM开头,用于标识STREAM协议。创建连接的请求语法如下:

Request Header Syntax

Op=[OPEN_WRITE|OPEN_READ|OPEN_RECOVER]LF
Host=<scheme>://<host>:<port>LF
Path=<path>LF
[Ugi=<user>:<pwd>LF |
Credential=<signatureValue>LF]
[Offset=<offset>LF]
RequestID=<requestID>LF
[BufferSize=<bufferSize>LF]
$<user.conf.name>=<value>LF

参数含义如下表:

Name Description Required
OP 操作类型,OPEN_WRITE表示写入,OPEN_READ表示读取,OPEN_RECOVER表示恢复写入失败 必须
RequestID RequestID唯一地对应了一个请求,可用于问题定位、性能分析等等多个场景。requestId使用UUID version 4,暂时由Client自行生成,后续考虑统一由BFE生成。 必须
Offset 恢复写入失败的truncate长度,没有设置默认truncate到上一次的sync点 非必须
Host 访问的集群,例如hdfs://szwg-dmop-ecomon.szwg01:54310 必须
Path 操作路径 必须
Ugi 用户权限信息,与Credential二选一 非必须
Credential 使用新门神登陆之后的认证信息,Server端会使用公钥来解密这个票据,得到用户对应的角色,参见 Authentication 非必须
$<user.conf.name> 用户自定义参数,$开头用于区分内建参数,例如写入慢节点配置,例如$dfs.client.slow.write.limit=1 非必须

Connect Operation

OP参数合法值以及解释如下:

Name Descirption
OPEN_WRITE 打开写入流
OPEN_READ 打开读入流
OPEN_RECOVER 写入过程中,Client和代理之间的异常(包括网络异常、代理异常)可能导致写入失败,由Client向DPA发起写入恢复请求,操作成功后可以继续写入。client可设置Offset参数来指定恢复后的长度,如果不指定默认恢复到上一次sync点

Request Body Syntax

Connect请求不包含body,所以为0。

Response Header Syntax

连接建立成功:

Status=${Current_Offset_in_File}LF
ConnectionID=<connectionID>LF
RequestID=<requestID>LF

连接建立失败:

Status=${ErrorCode}LF
RequestID=<requestID>LF
ErrorMessage=${ErrorMessage}LF

各字段含义如下表:

Name Description
Status 操作的状态,成功为当前的Offset,失败为ErrorCode,ErrorCode类型参见Error Responses
RequestID 对应请求中的RequestID。
ConnectionID 对应请求的上下文,后续请求需要携带响应的ConnectionID
ErrorMessage 错误信息

Response Body Syntax

Connect请求的响应不包含body,所以为0。

Write Data

创建连接之后,Client可以发送具体的写入数据和控制指令,请求的语法如下:

Request Header Syntax

OP=<OP>LF
[Offset=<offset>LF]
[Len=<len>LF]
RequestID=<requestID>LF
ConnectionID=<connectionID>LF

参数含义如下表:

Name Description Required
OP 操作类型 必须
Offset 写入的Offset 除OP=WRITE情况时必须
Len 写入的长度,长度和<BODY_LEN>不一致会报错 OP=WRITE情况时必须
RequestID RequestID唯一地对应了一个请求,可用于问题定位、性能分析等等多个场景。requestId使用UUID version 4,暂时由Client自行生成,后续考虑统一由BFE生成。 必须
ConnectionID 创建连接请求响应的ConnectionID,DPA用来查找请求的上下文 必须

Write Operation

OP参数合法值以及解释如下:

Name Descirption
WRITE 写入数据
CLOSE 关闭流
SYNC 将数据从代理的buffer写入到DataNode中,同时最新写入的数据对其他用户可见
FLUSH 将数据从代理的buffer写入到DataNode中,最新写入的数据对其他用户不可见,只用来保证数据不丢,便于写入异常时通过recover恢复
HEARTBEAT Client必须向Server发送心跳,Server一段时间之内(默认1分钟)没有收到client的心跳会认为client已经挂掉,并回收资源

Request Body Syntax

OP为WRITE的情况下可以携带BODY,BODY为写入的内容,<BODY_LEN>为写入长度,其余情况无BODY。

Response Syntax

DPA将数据刷到本地Buffer中之后,DPA会返回一个响应,表示数据写入成功,只要DPA不是异常退出,数据就不会丢失。

另外收到sync/flush写入命令的时候也会返回此响应,对于sync命令来说,DPA会同步收到sync成功的指令再返回;flush指令会等待所有DN ACK之后再响应。

响应语法为:

Status=${Status}LF
RequestID=<requestID>LF
[ErrorMessage=${ErrorMessage}LF]

参数含义如下表:

Name Description Required
Status 返回的状态码,OK表示成功,否则为错误码,错误码参见Error Responses 必须
RequestID 对应于请求携带的RequestID 必须
ErrorMessage 错误码的详细解释· Status不为OK时携带

Read Data

读数据请求,在建立连接时指定Op为OPEN_READ,语法参见Conntect

建立连接后可以进行数据读取,读取的请求需要携带RequestID字段语法如下:

Request Syntax

OP=<OP>LF
[Offset=<offset>LF]
[Len=<len>LF]
[Pread=<true|false>LF]
RequestID=<requestID>LF
ConnectionID=<connectionID>LF

参数含义如下表:

Name Description Required
Offset 读取的Offset OP=READ时必须
Len 读取的长度 OP=READ时必须
RequestID RequestID唯一地对应了一个请求,可用于问题定位、性能分析等等多个场景。requestId使用UUID version 4,暂时由Client自行生成,后续考虑统一由BFE生成。 必须
ConnectionID 创建连接请求响应的ConnectionID,DPA用来查找请求的上下文 必须
Pread Read会修改游标,因此线程不安全,多线程访问同一个文件句柄,可能会数据混乱;Pread不会修改游标,因此线程安全,多线程访问同一个文件句柄,数据不会混乱。不设置的情况下默认为false 非必须

Read Operation

OP参数合法值以及解释如下:

Name Descirption
READ 读取数据
CLOSE 关闭流
SEEK seek到新的position
TELL 返回当前的position
HEARTBEAT Client必须向Server发送心跳,Server一段时间之内(默认1分钟)没有收到client的心跳会认为client已经挂掉,并回收资源

Response Syntax

响应语法为:

Status=${Status}LF
RequestID=<requestID>LF
[Len=<len>LF]
[ErrorMessage=${ErrorMessage}LF]

参数含义如下表:

Name Description Required
Status 返回的状态码,OK表示成功,否则为错误码,错误码参见Error Responses 必须
RequestID 对应于请求携带的RequestID 必须
Len 读取的长度 OP=READ时必须
ErrorMessage 错误码的详细解释 Status不为OK时携带
⚠️ **GitHub.com Fallback** ⚠️