php thrift rpc,Thrift RPC 通信搭建

一、先安装 Thrift 编译工具

MAC 电脑安装执行以下命令

brew install thrift

Linux 环境下安装参考官网

官网地址:http://thrift.apache.org/download

安装完成之后

$ thrift --version

Thrift version 0.10.0

有以上输出说明工具安装成功

二、定义自己的Thrift 返回参数结构体

我这里定义了一个 thriftCommon.thrift 文件 这里我以 lumen框架为例 存放目录为thriftSource/thriftCommon.thrift 内容如下:

namespace php app.Library.Thrift # 指定生成什么语言,生成文件存放的目录

// 返回结构体

struct Response {

1: i32 code; // 返回状态码

2: string msg; // 码字回提示语名

3: string data; // 返回内容

}

// 服务体

service ThriftCommonCallService {

// json 字符串参数 客户端请求方法

Response invokeMethod(1:string params)

}

定义好以上文件之后使用第一步安装好的 thrift 工具来生成相应的文件

$ thrift -r --out ./ --gen php thriftSource/thriftCommon.thrift

执行该命令会在app/Library/Thrift目录生成ThriftCommonCallService.php与Types.php文件,这是客户端文件可以分两个项目部署,也可以在同一个项目部署,我这边因为工作需要独立部署。

三、创建一个新的客户端项目

执行以下创建命令

$ composer create-project laravel/lumen server --prefer-dist "5.5"

把第二步生成的客户端的两个文件拷贝到 app/Library/Thrift目录 如图:

d5eb1603421efab87c673c4b9e222347.png

四、服务端的实现

安装第三方使用包

$ composer require apache/thrift

使用 thrift 命令生成服务端代码

$ thrift -r --out ./ --gen php:server thriftSource/thriftCommon.thrift

执行该命令会在app/Library/Thrift目录生成ThriftCommonCallService.php与Types.php文件 打开 ThriftCommonCallService.php文件我们需要实现里面的接口ThriftCommonCallServiceIf 接下来我们建立实现文件 app/Library/Rpc/Server.php

namespace App\Library\Rpc;

use App\Library\Thrift\ThriftCommonCallServiceIf;

use App\Library\Thrift\Response;

class Server implements ThriftCommonCallServiceIf

{

/**

* 实现 socket 各个service 之间的转发

* @param string $params

* @return Response

* @throws \Exception

*/

public function invokeMethod($params)

{

// 转换字符串 json

$input = json_decode($params, true);

// 自己可以实现转发的业务逻辑

...

$response = new Response();

$response->code = 200;

$response->msg = '';

$response->data = json_encode($input);

return $response;

}

建立控制器实现服务端 端口启动 app/Http/Controllers/SocketController.php

namespace App\Http\Controllers;

use App\Library\Rpc\Server;

use app\Library\Thrift\Response;

use app\Library\Thrift\ThriftCommonCallServiceProcessor;

use Illuminate\Http\Request;

use Thrift\Exception\TException;

use Thrift\Factory\TBinaryProtocolFactory;

use Thrift\Factory\TTransportFactory;

use Thrift\Server\TServerSocket;

use Thrift\Server\TSimpleServer;

use Thrift\TMultiplexedProcessor;

class SocketController extends Controller

{

/**

* 启动 socket 连接

*/

public function server()

{

try {

$thriftProcessor = new ThriftCommonCallServiceProcessor(new Server());

$tFactory = new TTransportFactory();

$pFactory = new TBinaryProtocolFactory(true, true);

$processor = new TMultiplexedProcessor();

// 注册服务

$processor->registerProcessor('thriftCommonCallService', $thriftProcessor);

// 监听开始

$transport = new TServerSocket('127.0.0.1', 9999);

$server = new TSimpleServer($processor, $transport, $tFactory, $tFactory, $pFactory, $pFactory);

$server->serve();

} catch (TException $te) {

app('log')->error('socket 服务启动失败', ['content' => $te->getMessage()]);

}

}

建立访问路由或php artisan启动命令

// 访问路由

$router->get('/rpc/server', 'SocketController@server');

建立php artisan文件 目录 app/Console/Commands/RpcServer.php

/**

* Created by PhpStorm.

*/

namespace App\Console\Commands;

use App\Http\Controllers\SocketController;

use Illuminate\Console\Command;

class RpcServer extends Command

{

/**

* 控制台命令 signature 的名称。

*

* @var string

*/

protected $signature = 'server:rpc';

/**

* 控制台命令说明。

*

* @var string

*/

protected $description = 'rpc 服务';

protected static $socketController;

/**

* rpcServer constructor.

* @param SocketController $socketController

*/

public function __construct(SocketController $socketController)

{

parent::__construct();

self::$socketController = $socketController;

}

/**

* 执行控制台命令。

*

* @return mixed

*/

public function handle()

{

self::$socketController->server();

}

}

在 app/Console/Kernel.php注册

namespace App\Console;

use Illuminate\Console\Scheduling\Schedule;

use Laravel\Lumen\Console\Kernel as ConsoleKernel;

use App\Console\Commands\RpcServer;

class Kernel extends ConsoleKernel

{

/**

* The Artisan commands provided by your application.

*

* @var array

*/

protected $commands = [

RpcServer::class

];

到此服务端实现已全部完成 接下来实现客户端并成功与服务端通信

五、客户端的实现 (以第三步创建的项目为例继续说明)

安装第三方使用包

$ composer require apache/thrift

建立文件 app/Library/Tools/Socket.php

namespace App\Library\Tools;

use app\Library\Thrift\ThriftCommonCallServiceClient;

use Thrift\Protocol\TBinaryProtocol;

use Thrift\Protocol\TMultiplexedProtocol;

use Thrift\Transport\TBufferedTransport;

use Thrift\Transport\TSocket;

class Socket

{

// 保存对象实例化

private $_instance;

// 保存服务连接池

private static $client = [];

// 配置文件

private $config = [];

private function __construct($type)

{

$config = [

'erp' => [

'host' => env('ERP_RPC_HOST'),

'port' => env('ERP_RPC_PORT')

]

];

$this->config = $config[$type];

}

/**

* 连接服务

* @param string $name 调用的方法名

* @param array $args 1、参数数组 2、具体哪个方法名 3、所属的 Service 名称

* @return bool

*/

public static function __callStatic($name, $args)

{

if (substr($name, 0, 8) != 'SocketTo') {

return false;

}

$type = strtolower(substr($name, 8));

// 实例化操作

if (!isset(self::$client[$type])) {

self::$client[$type] = new self($type);

}

return self::$client[$type]->invoke($args);

}

private function invoke($args)

{

try {

$socket = new TSocket($this->config['host'], $this->config['port']);

$socket->setRecvTimeout(50000);

$socket->setDebug(true);

$transport = new TBufferedTransport($socket, 1024, 1024);

$protocol = new TBinaryProtocol($transport);

$thriftProtocol = new TMultiplexedProtocol($protocol, 'thriftCommonCallService');

$client = new ThriftCommonCallServiceClient($thriftProtocol);

$transport->open();

// 拼装参数与类型

$data = [

'params' => $args[0],

'methodName' => $args[1],

'serviceName' => $args[2]

];

$result = $client->invokeMethod(json_encode($data));

$result->data = json_decode($result->data, true);

$transport->close();

return $result;

} catch (\TException $Te) {

app('log')->error('服务连接失败 ', ['host' => $this->config, 'methodName' => $args[1], 'content' => $Te->getMessage()]);

return ['host' => $this->config, 'methodName' => $args[1], 'content' => $Te->getMessage()];

}

}

}

建立控制器来调用 并配置路由方问

namespace App\Http\Controllers;

use App\Library\Tools\Socket;

use Illuminate\Http\Request;

class ClientController extends Controller

{

public function client(Request $request)

{

return ['code' => 20000, 'data' => ['name' => 'admin', 'roles' => ['admin']]];

//接收参数

$param = $request->input("params");

//调用Service

$data = Socket::SocketToErp($param, 'login', 'LoginService');

return response()->json($data);

}

以上就是实现客户端与服务端通信的内容,如有不懂可留言一块讨论^_^

本作品采用《CC 协议》,转载必须注明作者和本文链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值