mirror of
https://gitee.com/ShopeX/OMS
synced 2026-03-22 18:35:35 +08:00
182 lines
4.9 KiB
Plaintext
182 lines
4.9 KiB
Plaintext
系统之间的互联
|
||
since : %%date(%Y-%m-%d) $Rev$
|
||
|
||
%!target:html
|
||
%!postproc(tex): '\.gif' '.eps'
|
||
%!preproc(html): '\.dot' '.gif'
|
||
%!preproc(tex): '\.dot' '.pdf'
|
||
%!encoding:utf-8
|
||
|
||
=远端通信的类型=
|
||
|
||
- web访问回调,用来定位某一具体注册到``api.``的service
|
||
- 远端过程调用 rpc, 就是我们刚才讲的``ecos-rpc``
|
||
- 信息广播, ``ecos-rpc``的一个特殊实例,
|
||
对外来说,就是向矩阵发送事件消息
|
||
|
||
|
||
=调用方式=
|
||
|
||
==ECOS-RPC节点==
|
||
|
||
指所有满足ecos-rpc通信协议的web站点。每个节点的信息包含两个主要部分。
|
||
- 站点的url
|
||
- rpc入口的url路径
|
||
|
||
|
||
所有符合ecos-rpc协议的web站点,根目录下都有一个``rpc.txt``,暂时内容只有一行:
|
||
```
|
||
handle: api_path
|
||
```
|
||
这个就是指,rpc的入口地址。
|
||
|
||
将站点的url和入口地址拼接在一起就是api的绝对访问地址。 例如站点是:``http://www.example.com``
|
||
|
||
访问``http://www.example.com/rpc.txt``,内容如下:
|
||
```
|
||
handle: index.php/api/
|
||
```
|
||
拼接在一起:
|
||
```
|
||
http://www.example.com/index.php/api
|
||
```
|
||
|
||
|
||
==服务端==
|
||
|
||
所有对外提供改的服务,或者说可被外部调用的api对象。都是注册好的service。
|
||
特别的是,这些service必须以"``api.``"开头
|
||
|
||
**app/abc/lib/rpc/hello.php**
|
||
```
|
||
<?php
|
||
class abc_rpc_hello{
|
||
|
||
public function world(){
|
||
...
|
||
}
|
||
|
||
public function earth(){
|
||
...
|
||
}
|
||
|
||
public function moon(){
|
||
...
|
||
}
|
||
|
||
}
|
||
```
|
||
|
||
注册这个服务。**app/abc/services.xml**
|
||
```
|
||
<services>
|
||
<service id="api.abc.hello">
|
||
<class>abc_rpc_hello</class>
|
||
</service>
|
||
</services>
|
||
```
|
||
|
||
==客户端==
|
||
|
||
调用都是依附在某一APP上执行的,因此要从APP上做入A,
|
||
调用的时候不需要添加``api.``, 直接写刚才定义的service名+method
|
||
```
|
||
$params = array(
|
||
'a'=>'b',
|
||
'b'=>'c'
|
||
);
|
||
|
||
$result = app::get('base')->remote(5)->call('server.time');
|
||
```
|
||
|
||
当执行成功后,会自动实例化并调用``dev_sandbox_finish::test()``处理返回的结果。
|
||
因为网络和远端系统的复杂性,不能保证在远端系统的执行时间一定满足用户体验的要求。
|
||
所以在调用时可以设置一个过期时间。
|
||
|
||
调用该对象的方法:
|
||
```
|
||
app::get('base')->remote(5)->set_timeout(1)->call('server.time');
|
||
```
|
||
|
||
当超过过期时间后,请求会自动转为异步交互,对象会自动返回``false``。
|
||
此时可以通过检查对象的``status``状态来判断刚才请求的结果。
|
||
|
||
```
|
||
$remote_hello_object = app::get('base')->remote(5)->set_timeout(1);
|
||
$result = $remote_hello_object->call('server.time',$params);
|
||
|
||
switch($remote_hello_object->status){
|
||
|
||
case RPC_RST_RUNNING:
|
||
//请求正在远端运行,完成后将自动结果回调。
|
||
...
|
||
break;
|
||
|
||
case RPC_RST_FINISH:
|
||
//请求正常完成, 并且已经完成结果回调。
|
||
break;
|
||
|
||
case RPC_RST_ERROR:
|
||
//请求执行出错
|
||
print_r($remote_hello_object->error);
|
||
break;
|
||
}
|
||
```
|
||
|
||
如果一段代码一定要在完成之后执行,那么我们就将其设置为``callback``方法。
|
||
``callback``方法会在同步或异步模式**一定**执行。
|
||
|
||
|
||
=协议=
|
||
|
||
我们设计了一个基于http扩展的,可协商的,rpc调用方式。可以同时实现阻塞和非阻塞两种调用方法。
|
||
|
||
==消息头==
|
||
|
||
需要用到的http header
|
||
|| Header | Description | Example |
|
||
| Connection | 复用标准设计,表达连接时间 | Connection:30 |
|
||
| Callback | 扩展。用在超时/非阻塞情况下:得到结果后将使用json-rpc请求该地址 | Callback: http://www.example.com/Api?action_id=123 |
|
||
|
||
- 普通的浏览器请求,通常会阻塞直到结果返回。
|
||
- 请求包含Connection头,服务器将:
|
||
|
||
当有结果时,保存在结果k-v引擎里。 如果请求包含Callback
|
||
主动回调请求Callback,客户端发送成功消息后,服务器端删除process_id的。k
|
||
|
||
客户端每隔一段时间向服务器提交process_id检查是否成功完成,
|
||
|
||
消息体采用json-rpc格式
|
||
|
||
|
||
== Request==
|
||
|
||
使用JSON格式对以下结构进行封装
|
||
|
||
method - 字符串格式, 表示请求的方法名
|
||
params - 请求的的参数。数组格式
|
||
id - request id。这可以是任何类型。用于区隔同一个客户端的多个请求
|
||
|
||
==Response==
|
||
|
||
请求的结果有三种情况。
|
||
<-- { "running": 123} //123号进程仍然在执行,未得到结果。
|
||
|
||
...1分钟之后...
|
||
|
||
--> { "checkprocess": 1}
|
||
<-- { "result": "Hello JSON-RPC", "error": null, "id": 1}
|
||
```
|
||
|
||
当超时发生时,客户端和服务器端都可以主动断开连接。需要注意的是:当客户端通过代理服务器连接时。由**请求端主动断开连接**的事件并不会传递到**真实服务器**。
|
||
此时的连接是这样:
|
||
|
||
```
|
||
client --- 8< --- proxy <--------> server
|
||
```
|
||
|
||
因此,服务器端不能仅凭连接来判断是否变更为异步请求。
|
||
实际判断条件为。
|
||
|
||
- 存在超时时间,并且已经超时,
|