• 基于 Thrift + Laravel RPC 调用实现


    项目初始化

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

    laravel new thrift
    

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

    namespace php App.Thrift.OrgThrift

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

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

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

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

     

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

    composer require apache/thrift
    

      

    编写服务端代码

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

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

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

    php artisan make:command RpcServerStart
    

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

    <?php
    namespace AppConsoleCommands;
    
    use AppServicesServerOrgService;
    use AppThriftOrgThriftOrgThriftProcessor;
    use IlluminateConsoleCommand;
    use ThriftExceptionTException;
    use ThriftFactoryTBinaryProtocolFactory;
    use ThriftFactoryTTransportFactory;
    use ThriftServerTServerSocket;
    use ThriftServerTSimpleServer;
    use ThriftTMultiplexedProcessor;
    
    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 AppConsoleCommandsRpcServerStart;
    
    protected $commands = [
        RpcServerStart::class,
    ];
    

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

    编写客户端代码

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

    namespace php App.Thrift.OrgThrift

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

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

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

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

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

    <?php
    namespace AppServicesClient;
    
    use AppThriftOrgThriftOrgThriftClient;
    use ThriftProtocolTMultiplexedProtocol;
    use ThriftExceptionTException;
    use ThriftProtocolTBinaryProtocol;
    use ThriftTransportTBufferedTransport;
    use ThriftTransportTSocket;
    
    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 AppServicesClientOrgService;
    
    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
    

      

  • 相关阅读:
    emergency mode(紧急模式)问题处理方法
    NFS简介与安装
    NACOS动态配置
    Mysql应用日志时间与系统时间相差八小时
    SQL*LOADER错误总结
    设置SQL*Plus运行环境
    对象切片
    编译原理:代码优化
    编译原理:运行时机制
    编译原理:剖析python编译阶段
  • 原文地址:https://www.cnblogs.com/blog-dyn/p/13094917.html
Copyright © 2020-2023  润新知