在 如何设计 RPC 接口 中讲到一个观点:
资源在用户侧以 hyper media 存在;资源流到服务中以对象来组织;资源落到存储里就变成了
id
+content
。索引content
的 id,一般又以单个
和集合
的形态存在,具体到数据库中,id 以 聚簇索引存在,content 以聚簇索引叶节点存在越来越多的产品按照先获取
id
再读取content
来访问资源
在REST论文中也有类似的描述:
REST 对于信息的核心抽象是资源。任何能够被命名的信息都能够作为一个资源。资源 r 是一个随时间变化的成员函数 m*r(t),该函数将时间 t 映射到等价的一个实体或值的集合,集合中的值可能是资源的表述* 和/或 资源的标识符。
其中包含了以下层面的意思:
- 服务是围绕资源建立的,服务存在的价值是对资源更新和组织
- 每种资源必须依靠 id 标志,内容本身只是为了最终呈现,作为资源的识别, id 才至关重要
- ID 又以
单个
和集合
形态存在,“集合” 是一种特殊的资源,包含相同类型的子资源列表
一般的应用中,通常使用资源唯一 ID 标识资源。ID 生成一般依赖数据库递增,或者 分布式ID生成服务。但在大型系统中,一般有很多资源,在使用资源ID标识资源时,通常需要使用特定于资源的元组来标识资源,例如:<群ID、消息ID> 或<公众号ID,消息ID,文章位置>。这会带来以下问题:
- 使用者必须记忆匿名元组、顺序
- 元组通常难以传递
- 通用服务不理解专用的元组
- 专用元组限制了 API 设计的灵活性
针对以上问题,一般来说可以将元组利用一定的机制进行拼接组装,生成一个唯一的ID。最常见的例子是微信公众平台的OpenID:
OpenID = WechatID (用户微信号) & APPID (公众平台ID)(两个数据加密得到的字符串)
然而特定的拼接方式仍然没有解决理解、通用性问题
理解和通用性问题,其实有比较通用的解决方案。既以名称-值
对的形式,建立自描述(self-descriptive)的标识符。语言描述可能比较难以理解,那么还是以微信公众平台OpenID为例,如果标志符以下面形式组织将会更容易理解:
wechatid=XXX&appid=XXX(加密得到的字符串)
但是以上组织方式引入了一个新的问题,到底该把哪些数据作为生成标识符的一部分呢?答案就是:集合(依据就是开头的片段)。资源可以由 集合 ID
和 资源 ID
组成;如果资源包含子资源,则子资源可以由 父资源
后跟 子资源的 ID
。
示例 1:存储服务具有一组 buckets
,其中每个存储分区都有一组 objects
:
API 服务名称 | 集合 ID | 资源 ID | 集合 ID | 资源 ID |
//storage.googleapis.com | /buckets | /bucket-id | /objects | /object-id |
示例 2:电子邮件服务具有一组 users
。每个用户都有一个 settings
子资源,而 settings
子资源拥有包括 customFrom
在内的许多其他子资源:
API 服务名称 | 集合 ID | 资源 ID | 资源 ID | 资源 ID |
//mail.googleapis.com | /users | /name@example.com | /settings | /customFrom |
本文作者 : cyningsun
本文地址 : https://www.cyningsun.com/08-09-2020/resouce-id-design.html
版权声明 :本博客所有文章除特别声明外,均采用 CC BY-NC-ND 3.0 CN 许可协议。转载请注明出处!