前期准备:
yum -y update
wget http://mirrors.cnnic.cn/apache/thrift/0.9.0/thrift-0.9.0.tar.gz
yum -y groupinstall "Development Tools"
wget http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz
tar xvf autoconf-2.69.tar.gz
cd autoconf-2.69
./configure --prefix=/usr
make && make install
wget http://ftp.gnu.org/gnu/automake/automake-1.14.tar.gz
tar xvf automake-1.14.tar.gz
cd automake-1.14
./configure --prefix=/usr
make && make install
wget http://ftp.gnu.org/gnu/bison/bison-2.5.1.tar.gz
tar xvf bison-2.5.1.tar.gz
cd bison-2.5.1
./bootstrap.sh
./configure --prefix=/usr
make && make install
yum -y install libevent-devel zlib-devel openssl-devel
复制代码
thrift安装包:
wget https://mirrors.cnnic.cn/apache/thrift/0.9.3/thrift-0.9.3.tar.gz
./configure && sudo make && sudo make install
复制代码
启动
/usr/server/php7/bin/php start.php start
关闭
/usr/server/php7/bin/php start.php stop
复制代码
下面我们实际创建个例子
1.第一步模仿下官方例子,自己建一个thift协议
namespace php Services.UserInfo
service UserInfo
{
string sayHello(1:string name);
i32 getMyScore(1:string age)
}
复制代码
命名空间第一个语言名,后面为生成的命名空间名称。 此处实现了两个方法:一个返回字符串类型 第二个返回int32类型 他们均接受一个字符串参数
2.生成代码文件
thrift -gen php:server UserInfo.thrift
复制代码
3.在当前目录下的 gen-php/Services应该生成了个UserInfo的文件夹。
UserInfo此为命名空间目录,下面的文件夹共有两个文件。
- Types.php 2. UserInfo.php
- 将生成的文件目录UserInfo 复制到 workerman 下面的Applications/ThriftRpc/Services/下
cp ./UserInfo /data/www/xxx/workerman-thrift/Applications/ThriftRpc -r
- 在复制过来的UserInfo里面新建 UserInfoHandler.php 文件, 实现UserInfoIf的接口,这些接口是我们在UserInfo.thrift中定义的。
<?php
namespace Services\UserInfo;
class UserInfoHandler implements UserInfoIf
{
public function sayHello($name)
{
//mysql查询
return ["123","456"];
}
public function getMyScore($age)
{
return 5;
}
}
复制代码
如果你的返回值类型并不是thrift文件定义的那样,将会被强制转义并在后台报一条错误。 必须以Handler结尾的文件类名
6.绑定端口提供服务
$worker = new ThriftWorker('tcp://0.0.0.0:9093');
$worker->name = 'UserInfo'; //设置进程名称
$worker->count = 2; //开启两个进程提供
$worker->class = 'UserInfo'; //要提供的服务名称
复制代码
- 启动服务
/usr/server/php7/bin/php start.php start 启动
/usr/server/php7/bin/php start.php stop 停止
/usr/server/php7/bin/php start.php restart 重启
/usr/server/php7/bin/php start.php reload 平滑重启
复制代码
注意启动后查看 进程名称是否存在,listen中tcp列表 是否有我们新增的端口 相应的process数量对应我们刚才设置的count属性。
服务简单的运行起来了,下面我们看下客户端
1.首先我们引入ThriftClient.php
require "/data/www/xxx/workerman-thrift/Applications/ThriftRpc/Clients/ThriftClient.php";
use ThriftClient\ThriftClient;
复制代码
它会自动帮我们引入我们需要的类
- 注册我们提供的服务地址
thriftClient::config(
array(
'HelloWorld' => array(
'addresses' => array(
'127.0.0.1:9090',
//'127.0.0.2:9191',
),
'thrift_protocol' => 'TBinaryProtocol',//不配置默认是TBinaryProtocol,对应服务端HelloWorld.conf配置中的thrift_protocol
'thrift_transport' => 'TBufferedTransport',//不配置默认是TBufferedTransport,对应服务端HelloWorld.conf配置中的thrift_transport
),
'UserInfo' => array(
'addresses' => array(
'127.0.0.1:9093'
),
),
)
);
复制代码
UserInfo服务是我们新增的服务,address是我们的端口号,是个数组的配置。地址是可以支持多个,进行随机请求处理。
3.获取UserInfo的实例-调用方法
$client = ThriftClient::instance('UserInfo');
$data = $client->getMyScore(12); //同步调用
var_dump($data);
$client->asend_sayHello(12); //异步调用
echo $client->arecv_sayHello(12); //接收
复制代码
注意 异步调用和接收值的传参数必须一致,否则无法定位到该接收哪个值。
更多的thrift语法使用:
1基本类型
bool: 布尔值 (true or false), one byte
byte: 有符号字节
i16: 16位有符号整型
i32: 32位有符号整型
i64: 64位有符号整型
double: 64位浮点型
string: Encoding agnostic text or binary string
复制代码
- php中获取数据库中查询的一维数组返回回来:
map<string,string> getMyScore(1:i32 age)
复制代码
返回值为key和value均强制转换为为string.
- 定义返回一个二维数组类型
list<map<string,string>> getMyScore(1:i32 age)
复制代码
注意list结构其实对应php的0,1,2,3有序下标。
return [
'data'=>["name" => "小明", "age" => 18, "is_open" => true],
'common' => [
'uid' => 12,
],
];
复制代码
返回结果:
array (
0 =>
array (
'name' => '小明',
'age' => '18',
'is_open' => '1',
),
1 =>
array (
'uid' => '12',
),
)
复制代码
结构体
map<string,map<string,string>> getMyScore(1:i32 age)
复制代码
返回值
array (
'data' =>
array (
'name' => '小明',
'age' => '18',
'is_open' => 'true',
),
'uid' =>
array (
0 => '1',
1 => '2',
2 => '3',
3 => '4',
4 => '5',
),
)
复制代码
结构体
map<string,map<string,string>> getMyScore(1:i32 age)
复制代码
返回值:
array (
'data' =>
array (
'name' => '小明',
'age' => '18',
'is_open' => 'true',
),
'uid' =>
array (
0 => '1',
1 => '2',
2 => '3',
3 => '4',
4 => '5',
),
)
复制代码
如何为自己的应用程序拓展model层等
$loader = new ThriftClassLoader();
$loader->registerNamespace('Thrift', THRIFT_ROOT.'/Lib');
$loader->registerNamespace('Service', THRIFT_ROOT);
$loader->registerNamespace('Model', THRIFT_ROOT.'/Model');
$loader->register();
复制代码
workerman-thrift/Applications/ThriftRpc/ThriftWorker.php:22 注册Model到命名空间中
log文件地址
/data/www/xxx/workerman-thrift/vendor/workerman/workerman.log
复制代码
thrift实际部署工作流
thrift区分客户端和服务端
#!/bin/sh
cd `dirname $0`
for name in `ls ./thrift`
do
thrift -gen php:server ./thrift/$name
cp ./gen-php/Services/* ../Applications/ThriftRpc/Services/ -r
/usr/server/php7/bin/php ../start.php restart -d
done
复制代码
在服务器端的脚本,扫描文件生成,复制到业务目录里,然后重启workerman 但是客户端需要用到生成的文件XXService/XXService.php,整个工作流目前怎么管理还不知道,希望有耐心看到这里的读者给我些思路。 目前用的手动创建目录复制。
客户端调用实例:
require "./Clients/ThriftClient.php";
use ThriftClient\ThriftClient;
thriftClient::config(
array(
'PayService' => array(
'addresses' => array(
'127.0.0.1:9090',
//'127.0.0.2:9191',
),
'thrift_protocol' => 'TBinaryProtocol',//不配置默认是TBinaryProtocol,对应服务端HelloWorld.conf配置中的thrift_protocol
'thrift_transport' => 'TBufferedTransport',//不配置默认是TBufferedTransport,对应服务端HelloWorld.conf配置中的thrift_transport
),
)
);
$client = ThriftClient::instance('PayService');
//获取详情
//var_export($client->xxxxx('1144778255615962','26'));
var_export($client->xxxxxx(12312));
复制代码
使用composer安装客户端
composer.json
{
"name":"thrift client",
"require":{
"cto/thrift_client":"dev-master"
},
"repositories":{
"cto/thrift_client":{
"type":"git",
"url":"https://github.com/chinawangyu/thriftClient.git"
}
},
"autoload":{
"psr-4": {
"ThriftClient\\": "vendor/cto/thrift_client"
}
}
}
复制代码
require加载进来的名字 repositories仓库地址
workerman运行:
/usr/server/php7/bin/php start.php status
查看运行状态
复制代码
监控workerman运行
http://127.0.0.1:55757/ 需要额外配置 Applications/Statistics/Lib/Cache.php
public static $ServerIpList = array('127.0.0.1');
复制代码