thrift的使用中一般是一个Server对应一个Processor和一个Transport,如果有多个服务的话,那必须要启动多个Server,占用多个端口,这种方式显然不是我们想要的,所以thrift为我们提供了复用端口的方式,通过监听一个端口就可以提供多种服务,这种方式需要用到两个类:TMultiplexedProcessor和TMultiplexedProtocol。
创建 2 个 Laravel 项目,thrift-server (服务端) 和 thrift-client (客户端)
testServer.thrift: namespace php Rpc.Test enum Operation { ADD = 1, SUBTRACT = 2, MULTIPLY = 3, DIVIDE = 4 } exception InvalidOperation { 1: i32 whatOp, 2: string why } service Calculator { double calculate(1:double num1, 2:double num2, 3:Operation op) throws (1:InvalidOperation ouch), string echoString(1: string str) , } service Echo { string echo(1: string str) , }
每个service类对应一种服务,服务类下可有多个方法。
thrift-server根目录生成客户端类命令:
thrift -r --out ./ --gen php thriftSource/testServer.thrift
将生成的Rpc/Test文件夹剪切到thrift-client项目的Rpc目录中
在thrift-server根目录继续生成服务端类:
thrift -r --out ./ --gen php:server thriftSource/testServer.thrift
根目录创建Service目录,存放实现Calculator和Echo类的文件
Service/CalculatorService.php
<?php /** * 实现Calculator服务 */ namespace Service; use RpcTestCalculatorIf; use RpcTestOperation; use RpcTestInvalidOperation; class CalculatorService implements CalculatorIf { /** * @param double $num1 * @param double $num2 * @param int $op * @return double * @throws InvalidOperation */ public function calculate($num1, $num2, $op) { switch ($op) { case Operation::ADD: $val = $num1 + $num2; break; case Operation::SUBTRACT: $val = $num1 - $num2; break; case Operation::MULTIPLY: $val = $num1 * $num2; break; case Operation::DIVIDE: if ($num2 == 0) { $io = new InvalidOperation(); $io->whatOp = $op; $io->why = "Cannot divide by 0"; throw $io; } $val = $num1 / $num2; break; default: $io = new InvalidOperation(); $io->whatOp = $op; $io->why = "Invalid Operation"; throw $io; } return $val; } /** * @param $string */ public function echoString($string) { return $string; } }
Service/EchoService.php:
<?php /** * 实现Echo服务 */ namespace Service; use RpcTestEchoIf; class EchoService implements EchoIf { /** * @param $string */ public function echo($string) { return $string; } } thrift-server服务端控制器: <?php /** * 服务端控制器 */ namespace AppHttpControllers; use RpcTestCalculatorProcessor; use RpcTestEchoProcessor; use ServiceCalculatorService; use ServiceEchoService; use IlluminateHttpRequest; use ThriftProtocolTBinaryProtocol; use ThriftTMultiplexedProcessor; use ThriftTransportTBufferedTransport; use ThriftTransportTPhpStream; use ThriftExceptionTException; class ServerController extends Controller { /** * 多个服务 * @param Request $request */ function handleManyRequest(Request $request) { try{ header('Content-Type', 'application/x-thrift'); // 初始化多个服务提供者handle $calculatorhandler = new CalculatorService(); $echohandler = new EchoService(); $multiplexedProcessor = new TMultiplexedProcessor(); // 创建多个服务Processor $calculatorProcessor = new CalculatorProcessor($calculatorhandler); $echoProcessor = new EchoProcessor($echohandler); // 将服务注册到TMultiplexedProcessor中 $multiplexedProcessor->registerProcessor("calculator", $calculatorProcessor); $multiplexedProcessor->registerProcessor("echo", $echoProcessor); // 初始化数据传输方式transport $transport = new TBufferedTransport(new TPhpStream(TPhpStream::MODE_R | TPhpStream::MODE_W)); // 利用该传输方式初始化数据传输格式protocol $protocol = new TBinaryProtocol($transport, true, true); // 开始服务 $transport->open(); $multiplexedProcessor->process($protocol, $protocol); $transport->close(); } catch (TException $tx) { print 'TException: '.$tx->getMessage()." "; } } }
配置post方式路由
Route::post('/rpc/server', 'ServerController@handleManyRequest');
配置虚拟主机 8081 端口监听thrift-server服务,80端口监听thrift-client服务
thrift-client客户端控制器:
<?php /** * 客户端控制器 */ namespace AppHttpControllers; use RpcTestOperation; use RpcTestCalculatorClient; use RpcTestEchoClient; use IlluminateHttpRequest; use ThriftProtocolTBinaryProtocol; use ThriftProtocolTMultiplexedProtocol; use ThriftTransportTHttpClient; use ThriftTransportTBufferedTransport; use ThriftExceptionTException; class ClientController extends Controller { /** * 多服务 * @param Request $request */ function handleManyRequest(Request $request) { try{ // 定义连接 $socket = new THttpClient('127.0.0.1', 8081, '/rpc/server'); // 创建transport $transport = new TBufferedTransport($socket, 1024, 1024); // 基于Transport创建Protocol $protocol = new TBinaryProtocol($transport); // 创建Client调用服务接口的方法 $calculatorClient = new CalculatorClient(new TMultiplexedProtocol($protocol, "calculator")); $echoClient = new EchoClient(new TMultiplexedProtocol($protocol, "echo")); // 开启 $transport->open(); // 调用接口方法 $sum = $calculatorClient->calculate(1, 2, Operation::ADD); print "calculator service -> calculate function -> 1+2=$sum </br>"; $test = $calculatorClient->echoString('this it test'); print "calculator service -> echoString function -> echoString:$test </br>"; $echoString = $echoClient->echo('echo method'); print "echo service -> echo function -> echo:$echoString "; $transport->close(); } catch (TException $tx) { print 'TException: '.$tx->getMessage()." "; } } }
由此可客户端可调用服务端的方法,实现通讯:
注意:
1、根目录新建目录需配置composer.json中的psr-4
2、取消http/kernel.php中web中间件内容
转载:https://www.jianshu.com/p/99405b3072b1