介绍

Yar 是一个 RPC 框架,它提供了一种简单易用的方式来在 PHP 应用程序之间进行通信,同时它还提供了对远程服务进行多个调用的能力。

特征

  • 快速、简单
  • 并发 RPC 调用
  • 支持多种数据打包器(php、json、msgpack 内置)
  • 支持多种传输协议(http、https、TCP)
  • 详细的调试信息

扩展地址如以下,截止到(2022.09.10):

文档 Star 数量 说明
laruence/yar https://github.com/laruence/yar/blob/master/README.md 1.4k 鸟哥提供

安装

安装yar

Yar 是一个 PECL 扩展,可以简单地通过以下方式安装:
pecl install yar

在 Linux 中编译 Yar

1
2
3
$ /path/to/phpize
$ ./configure --with-php-config=/path/to/php-config/
$ make && make install

可用的配置说明

1
2
3
--with-curl=DIR
--enable(disable)-msgpack
--enable(disable)-epoll (require Yar 2.1.2)

使用 msgpack 安装 Yar

1.为 PHP 扩展安装 msgpack:
pecl install msgpack
或者对于 ubuntu 用户
apt-get install msgpack-php
或者,可以在此处获取 github 源:[https ://github.com/msgpack/msgpack-php](https ://github.com/msgpack/msgpack-php)

2.配置:

1
2
3
$phpize
$configure --with-php-config=/path/to/php-config/ --enable-msgpack
$make && make install

集成代码

查看源码

服务器端

设置 Yar HTTP RPC 服务器非常容易:

文件位置:common/rpc/YarServer.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
<?php

namespace app\common\rpc;

use Exception;

/**
* YarServer
*/
class YarServer
{

/**
* ip
* @var string[]
*/
private $ipArr = ['172.24.0.1'];

/**
* 密码
* @var string
*/
private $password = 'shershon-rpc-token';

/**
* 有效时间
* @var int
*/
private $activeTime = 1440;

public function server($params)
{
try {
$rpcToken = $params['rpc_token'] ?? '';
$data = $this->rpcDecode($rpcToken);
if (!$this->auth($data)) {
throw new Exception('认证失败');
}
$server = new \Yar_Server(new $data['class']());
$server->handle();
exit();
} catch (Exception $e) {
return ['code' => -1, 'msg' => $e->getMessage(), 'data' => []];
}
}

/**
* 权限认证
*
* @param $param
* @return bool
*/
public function auth($param)
{
if (!$param) {
return false;
}
//验证IP
/*if (!in_array(Yii::$app->request->userIP, $this->ipArr)) {
return false;
}*/
//有效时间
if ((time() - $param['time']) > $this->activeTime) {
return false;
}
//验证密码
if ($param['password'] !== $this->password) {
return false;
}
if (empty($param['class'])) {
return false;
}
return true;
}

/**
* 解密
*
* @param $str
* @return array|mixed
*/
public function rpcDecode($str)
{
if ($str) {
return json_decode(base64_decode($str), true);
}
return [];
}
}

客户端

PHP 客户端调用远程 RPC 非常简单:

文件位置:common/rpc/YarApi.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?php

namespace app\common\rpc;

/**
* Yar rpc client
*/
class YarApi
{
/**
* 密码
* @var string
*/
private $password = 'shershon-rpc-token';

public function api(array $condition)
{
$defult = [
'url' => 'http://yii-api.shershon.top/index.php?r=yar/rpc-server', //服务器URL
'class' => '', //class名称
];
$condition = array_merge($defult, $condition);

$data = [];
$data['time'] = time();
$data['password'] = $this->password;
$data['class'] = $condition['class'];

return new \Yar_Client("{$condition['url']}&rpc_token={$this->rpcEncode($data)}");
}

/**
* 加密
*
* @param array $data
* @return string
*/
private function rpcEncode(array $data)
{
return base64_encode(json_encode($data));
}
}

添加模型方法

添加模型方法,PHP客户端可以在远程调用:

文件位置:models/User.php

1
2
3
4
public function selAll()
{
return self::$users;
}

简单使用

本地启动Yii Server

项目根目录下执行php yii serve --port=8888

创建测试路由

文件位置:controllers/YarController.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?php

namespace app\controllers;

use app\common\rpc\YarServer;
use Yii;
use yii\web\Controller;
use app\common\rpc\YarApi;

class YarController extends Controller
{
/**
* 关闭csrf
* @var bool
*/
public $enableCsrfValidation = false;

public function actionRpcCall()
{
$condition = ['class' => '\app\models\User'];
$yar = new YarApi();
$client = $yar->api($condition);
$response = [
'code' => 200,
'msg' => 'success',
'data' => $client->selAll()
];
return $this->asJson($response);
}

public function actionRpcServer()
{
$params = Yii::$app->request->get();
$yarServer = new YarServer();
$response = $yarServer->server($params);
return $this->asJson($response);
}
}

请求实例

1
2
➜  yii-api-template git:(master) curl http://localhost:8888/index.php\?r\=yar/rpc-call
{"code":200,"msg":"success","data":{"100":{"id":"100","username":"admin","password":"admin","authKey":"test100key","accessToken":"100-token"},"101":{"id":"101","username":"demo","password":"demo","authKey":"test101key","accessToken":"101-token"}}}