凤凰架构 —— 访问远程服务
RPC
“为了让计算机像调用本地方法一样调用远程方法”
这是RPC最原始的定义,于是可以从调用本地方法的思路上来分析RPC
调用的时候 需要知道入参 方法 返回结果
本质上和RPC上是一样的 即 发什么 发给谁 得到什么的问题
原文中采用了这样的例子
1 |
|
如上是一个调用时的minimal的情景
通讯
在实际的RPC中 还需要考虑如 怎么发 什么形式发 的问题
这个问题同样可以类比到本地方法调用中 ———— 所想要调用的方法不是本地的方法
此时就需要使用到一些 IPC(进程间通信)的方法
例如老生常谈的 pipe go-channel MQ sharedMemory socket 信号量 条件变量等等等等方法
而对于RPC 指的是多台机器上的请求响应 所以多数方案是不太可行的(或者说 是有着更优的方案)
将RPC在找方法时的各个环节都总结下 本质上就是如下问题:
- 如何表示数据 数据是否需要进行处理?怎么样的处理?
- 如何传递数据 使用什么协议?有什么特性?
- 如何确定方法 对传递时方法签名的一个跨语言,一致性抽象
对于上面的每个问题 业界较为成熟的协议中都给出了对应的解决方案 分别可以对应着
- Java序列化流 PB json
- grpc http
- pb所提供的抽象
历程
在不断的发展中 人们对于RPC原来所持的观念最早可以理解为单一整体 其中包含的功能全,多,完整,支持多种情况
但是这样的兼容性发展不可避免的就是带来整个协议的庞大 以及其中携带信息的大量冗余 带来了数据存取、传输效率的低下
所以在此之上 人们针对各种情况 将统一的RPC修改成为了分裂的RPC
其功能不再是一体式 而是朝着配置化和插件化方向进行发展 对于一些完善的RPC框架 可以根据当前的具体情景 来选择最适用的协议 数据表示方式等
REST设计风格
表征状态转移 ———— REST的设计理念
表征:信息与用户交互时的表示形式。可以理解成对单个元素 的不同表现形式 例如说是本文的md格式 导出后的pdf 以及同样内容的txt格式 表征上都是一样的(表现形式不同 本质相同的资源)
那么如何理解他这里的这一句话呢 可以结合REST的这一些特点:
无状态:
REST的请求是一次性的 可能会携带应用的状态 但是他本质上是无状态的
无状态指的是不具有类似权限机制 认证机制等状态
换句话来说 是通过多次REST的无状态请求 修改程序某部分当前的状态
面向资源编程:
这特点本质上也是无状态的一种体现。指将当前业务再度抽象,从实体为起点,服务行为为终点进行考虑。而避免直接从服务行为来进行思考。
引用原文的例子:
譬如,几乎每个系统都有的登录和注销功能,如果你理解成登录对应于 login()服务,注销对应于 logout()服务这样两个独立服务,这是“符合人类思维”的;如果你理解成登录是 PUT Session,注销是 DELETE Session,这样你只需要设计一种“Session 资源”即可满足需求,甚至以后对 Session 的其他需求,如查询登陆用户的信息,就是 GET Session 而已,其他操作如修改用户信息等都可以被这同一套设计囊括在内,这便是“抽象程度更高”带来的好处。
个人理解这个设计和ddd有点像 在领域驱动设计当中 我门需要将各个元素分割为实体 聚合根 等层次之后 在此之上在考虑用户用例和领域方法
而常规的MVC架构本质上就是从行为来进行考虑 所以也带来了所谓的“贫血症”等问题
回归正题 结合这两个设计 可以得到rest的本质设计思路就是将整个服务作为一个整体的状态机进行思考
注意:这里的状态机与上方的无状态并不矛盾 上方所说的无状态是指每次REST请求中 不包含其本身的状态信息
而作为整体状态机思考则是代表 通过一次次无状态的请求 让程序无负担的从一个状态直接切换到另一个状态
ps
总体上来看 也可以看到rest本身和rpc是有某些相似之处的
虽然两者的设计目标不一致 且两者所处的层次结构也不完全一致
但是两者的设计哲学 还是有几分相似的