基于 Thrift + Laravel RPC 调用实现

Posted 佚小名

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于 Thrift + Laravel RPC 调用实现相关的知识,希望对你有一定的参考价值。

项目初始化

为此,我们先初始化一个新的 Laravel 应用 thrift

laravel new thrift

 在 thrift 项目根目录下新增一个 thrift 子目录,然后在该子目录下创建 Thrift IDL 文件 org.thrift,用于定义和用户相关的服务接口(语言为 php,命名空间为 App\\Thrift\\Org):

namespace php App.Thrift.OrgThrift

service OrgThrift {
string routeRequest(1:i32 request)
}

 接着在项目根目录下运行如下命令,根据上述 IDL 文件生成相关的服务代码:

thrift -r --gen php:server -out ./ thrift/org.thrift

 这样就会在 App\\Thrift\\OrgThrift命名空间下生成对应的服务代码:

 

然后通过 Composer 安装 Thrift PHP 依赖包:

composer require apache/thrift

  

编写服务端代码

 接下来,我们就可以编写服务端代码了,在 app 目录下新建一个 Services/Server 子目录,然后在该目录下创建服务接口类OrgService,该类实现自 App\\Thrift\\org\\OrgIf 接口:

 

 

 

在服务接口实现中,我们通过传入参数查询数据库并返回对应的记录,这里为了简化逻辑,我们直接返回,将参数校验、缓存优化、异常处理通通省略。

接下来,我们来编写服务端启动命令类,在 Laravel 框架中,这可以通过 Artisan 控制台来完成,首先创建命令类:

php artisan make:command RpcServerStart

  该命令会在 app/Console/Commands 目录下生成 RpcServerStart.php,我们编写 RpcServerStart 命令类代码如下:

 

<?php
namespace App\\Console\\Commands;

use App\\Services\\Server\\OrgService;
use App\\Thrift\\OrgThrift\\OrgThriftProcessor;
use Illuminate\\Console\\Command;
use Thrift\\Exception\\TException;
use Thrift\\Factory\\TBinaryProtocolFactory;
use Thrift\\Factory\\TTransportFactory;
use Thrift\\Server\\TServerSocket;
use Thrift\\Server\\TSimpleServer;
use Thrift\\TMultiplexedProcessor;

class RpcServerStart extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = \'rpc:start\';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = \'Start Thrift RPC Server\';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        try {
            $thriftProcess = new OrgThriftProcessor(new OrgService());
            $tFactory = new TTransportFactory();
            $pFactory = new TBinaryProtocolFactory();
            $processor = new TMultiplexedProcessor();
            // 注册服务
            $processor->registerProcessor(\'OrgService\', $thriftProcess);
            // 监听本地 8888 端口,等待客户端连接请求
            $transport = new TServerSocket(\'127.0.0.1\', 8001);
            $server = new TSimpleServer($processor, $transport, $tFactory, $tFactory, $pFactory, $pFactory);
            $this->info("Server Start [127.0.0.1:8001]!");
            $server->serve();
        } catch (TException $exception) {
            $this->error("服务启动失败!");
        }
    }
}

  

  别忘了在 app/Console/Kernel.php 中注册上述命令类使其生效:

use App\\Console\\Commands\\RpcServerStart;

protected $commands = [
    RpcServerStart::class,
];

  这样,服务端接口和启动命令都已经完成了,接下来我们继续编写客户端建立连接和请求通信代码。

编写客户端代码

在 客户端(client) 项目根目录下新增一个 thrift 子目录,然后在该子目录下创建 Thrift IDL 文件 org.thrift,用于定义和用户相关的服务接口(语言为 PHP,命名空间为 App\\Thrift\\Org):

namespace php App.Thrift.OrgThrift

service OrgThrift {
string routeRequest(1:i32 request)
}

 接着在项目根目录下运行如下命令,根据上述 IDL 文件生成相关的服务代码:

thrift -r --gen php -out ./ thrift/org.thrift

这样就会在 App\\Thrift\\OrgThrift命名空间下生成对应的服务代码:

 

 

 

这个客户端并不是前端、移动端,而是相对于 RPC 服务器的 RPC 客户端,我们在 app/Services/Client 目录下创建 OrgService.php,用于存放 RPC 客户端连接与请求服务接口方法:

<?php
namespace App\\Services\\Client;

use App\\Thrift\\OrgThrift\\OrgThriftClient;
use Thrift\\Protocol\\TMultiplexedProtocol;
use Thrift\\Exception\\TException;
use Thrift\\Protocol\\TBinaryProtocol;
use Thrift\\Transport\\TBufferedTransport;
use Thrift\\Transport\\TSocket;

class OrgService
{
    public function routeOrg()
    {
        $request=\\Request::all();
        try {
            // 建立与 RpcServer 的连接
            $socket = new TSocket("127.0.0.1", "8001");
            $socket->setRecvTimeout(30000);  // 超时时间
            $socket->setDebug(true);
            $transport = new TBufferedTransport($socket, 1024, 1024);
            $protocol = new TBinaryProtocol($transport);
            $thriftProtocol = new TMultiplexedProtocol($protocol, \'OrgService\');
            $client = new OrgThriftClient($thriftProtocol);
            $transport->open();
            $result = $client->routeRequest($request);
            $transport->close();
            return $result;
        } catch (TException $TException) {
            dd($TException);
        }
    }
}

 同样,为了简化代码和流程,我这里将连接和请求代码写到一起了,如果有多个服务接口,传输层是可以共用的,需要拆分开。这里我们先建立与 RPC 服务器的连接, 

最后,我们在 routes/web.php 中注册客户端请求路由:

use App\\Services\\Client\\OrgService;

Route::get(\'/org/{id}\', function($id) {
    $OrgService = new OrgService();
    // dd($userService);
    $Org = $OrgService->routeOrg($id);
    return $Org;
});

  

测试 RPC 服务调用

至此,RPC 客户端和服务端代码都已经编写好了,接下来我们来测试这个 RPC 接口调用

接下来,在项目根目录下启动 Thrift RPC 服务端:

php artisan rpc:start

  注意:
1、根目录新建目录需配置composer.json中的psr-4
2、取消http/kernel.php中web中间件内容

 

 然后composer更新:

composer dump-autoload

  

以上是关于基于 Thrift + Laravel RPC 调用实现的主要内容,如果未能解决你的问题,请参考以下文章

RPC 原理以及开源 RPC 协议 thrift 源码解析

RPC框架之Thrift

基于Thrift的跨语言高可用高性能轻量级的RPC框架

VIP_OSP--基于Thrift的RPC框架的基本原理

VIP_OSP--基于Thrift的RPC框架的基本原理

网络RPC通信之Apache Thrift