Thrift
Apache Thrift是一个跨语言的服务部署框架,通过一个中间语言(IDL, 接口定义语言)来定义RPC的接口和数据类型,然后通过一个编译器生成不同语言的代码(支持C++,Java,Python,PHP, GO,Javascript,Ruby,Erlang,Perl, Haskell, C#等),并由生成的代码负责RPC协议层和传输层的实现
本文是基于thrift@0.9版本
1、安装
2、使用
2.1 编写IDL文件
现在开始编写一个简单IDL文件goods.thrift
1
2
3
4
5
6
7
|
namespace php Services.Goods
service Goods
{
string getName(1:i64 id);
i16 getId(1:string name);
}
|
2.2 通过生成器生成PHP文件
1
2
3
4
|
# 生成服务端
thrift --gen php:server goods.thrift
# 生成客户端
thrift --gen php goods.thrift
|
生成文件在gen-php目录下面的Services/Goods/(目录与namesapce定义一致),这是个公共文件,服务端和客户端都需要包括它。其中客户端调用的代码(GoodsClient )已经生成好了
目前的目录结构:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
├── gen-php
│ └── Services
│ └── Goods
│ ├── GoodsClient.php
│ └── GoodsIf.php
│ └── GoodsProcessor.php
│ └── Goods_getAllGoods_args.php
│ └── Goods_getAllGoods_result.php
│ └── Goods_getDetail_args.php
│ └── Goods_getDetail_result.php
│ └── Goods_getGname_args.php
│ └── Goods_getGname_result.php
├── goods.thrift
|
2.3 下载Thrift
Thrift的PHP类库在Thrift源码中https://github.com/apache/thrift.
可以将thrift/lib/php/lib/Thrift目录复制到当前目录下载下来。
2.4 将代码继承到thinkphp
服务端-商品服务
目录机构如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
├── application
├── extend
│ └── Thrift # 2.3步下载的Thrift源码
│ └── Services # 2.2 步生成的php代码
│ └── Goods
│ ├── GoodsClient.php
│ └── GoodsIf.php
│ └── GoodsProcessor.php
│ └── Goods_getAllGoods_args.php
│ └── Goods_getAllGoods_result.php
│ └── Goods_getDetail_args.php
│ └── Goods_getDetail_result.php
│ └── Goods_getGname_args.php
│ └── Goods_getGname_result.php
|
GoodsHandler.php 需要实现接口GoodsIf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
<?php
namespace app\services\controller;
use Services\Goods\GoodsIf;
class GoodsHandler implements GoodsIf {
/**
* @param string $id
* @return string
*/
public function getGname($id){
return '商品名称';
}
/**
* @param string $name
* @return string
*/
public function getId($name){
return 1;
}
}
|
服务端代码Rpcservice.php,使用command来进行启动
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
|
<?php
namespace app\common\command;
use app\common\command\Common;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use Thrift\ClassLoader\ThriftClassLoader;
use Thrift\Exception\TException;
use Thrift\Factory\TTransportFactory;
use Thrift\Factory\TBinaryProtocolFactory;
use Thrift\Server\TServerSocket;
use Thrift\Server\TSimpleServer;
use app\services\controller\GoodsHandler;
use Services\Goods\GoodsProcessor;
class Rpcservice extends Common
{
protected function execute(Input $input, Output $output){
try {
$handler = new GoodsHandler();
$processor = new GoodsProcessor($handler);
$transportFactory = new TTransportFactory();
$protocolFactory = new TBinaryProtocolFactory(true, true);
//作为cli方式运行,监听端口,官方实现
$transport = new TServerSocket('127.0.0.1', 9090);
$server = new TSimpleServer($processor, $transport, $transportFactory, $transportFactory, $protocolFactory, $protocolFactory);
$server->serve();
} catch (TException $tx) {
print 'TException: '.$tx->getMessage()."\n";
}
}
}
|
定义command
1
2
3
|
return [
'rpc_service' => 'app\common\command\Rpcservice', // 启动rpc service
];
|
启动rpc service
客户端-订单服务
目录机构如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
├── application
├── extend
│ └── Thrift # 2.3步下载的Thrift源码
│ └── Services # 2.2 步生成的php代码
│ └── Goods
│ ├── GoodsClient.php
│ └── GoodsIf.php
│ └── GoodsProcessor.php
│ └── Goods_getAllGoods_args.php
│ └── Goods_getAllGoods_result.php
│ └── Goods_getDetail_args.php
│ └── Goods_getDetail_result.php
│ └── Goods_getGname_args.php
│ └── Goods_getGname_result.php
|
GoodsClient.php调用rpc服务
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
|
<?php
namespace app\index\controller;
use Services\Goods\GoodsClient as Client;
use Thrift\Transport\TSocket;
use Thrift\Transport\TBufferedTransport;
use Thrift\Protocol\TBinaryProtocol;
class GoodsClient extends Rpc
{
/**
* @description: 方法描述
* @author liangdong
* @method
* @date 2021/06/29 10:46:50
* +-----------------------------
* @params int name
* @return
*/
public function getAllGoods()
{
try {
//仅在与服务端处于同一输出输出流有用
//使用方式:php Client.php | php Server.php
//$transport = new TBufferedTransport(new TPhpStream(TPhpStream::MODE_R | TPhpStream::MODE_W));
//socket方式连接服务端
//数据传输格式和数据传输方式与服务端一一对应
//如果服务端以http方式提供服务,可以使用THttpClient/TCurlClient数据传输方式
$transport = new TBufferedTransport(new TSocket('192.168.1.4', 9090));
$protocol = new TBinaryProtocol($transport);
$client = new Client($protocol);
$transport->open();
//同步方式进行交互
$recv = $client->getGname(1);
echo $recv." \n";
$transport->close();
} catch (TException $tx) {
print 'TException: '.$tx->getMessage()."\n";
}
}
}
|