php thrift rpc,基于 Thrift + Laravel 构建微服务(一):RPC 调用实现

基于 Thrift + Laravel 构建微服务(一):RPC 调用实现

由 学院君 创建于1年前, 最后更新于 1年前

版本号 #1

3779 views

1 likes

1 collects

3bf5dd14aecb4c48f54a3691d66a33fa826.jpg

上篇分享我们简单介绍了 Thrift 框架,本周学院君将会花几个篇幅的教程来介绍如何基于 Thrift + Laravel 构建微服务接口。

项目初始化

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

laravel new thrift

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

namespace php App.Thrift.User

// 定义用户接口

service User {

string getInfo(1:i32 id)

}

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

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

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

e577cac28fcdde965b3fc52b9eb92826.png

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

composer require apache/thrift

编写服务端代码

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

098ed633625bfdf0d51753dacb56d83a.png

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

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

php artisan make:command RpcServerStart

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

namespace App\Console\Commands;

use App\Services\Server\UserService;

use App\Thrift\User\UserProcessor;

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 UserProcessor(new UserService());

$tFactory = new TTransportFactory();

$pFactory = new TBinaryProtocolFactory();

$processor = new TMultiplexedProcessor();

// 注册服务

$processor->registerProcessor('UserService', $thriftProcess);

// 监听本地 8888 端口,等待客户端连接请求

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

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

$this->info("服务启动成功[127.0.0.1:8888]!");

$server->serve();

} catch (TException $exception) {

$this->error("服务启动失败!");

}

}

}

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

use App\Console\Commands\RpcServerStart;

protected $commands = [

RpcServerStart::class,

];

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

编写客户端代码

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

namespace App\Services\Client;

use App\Thrift\User\UserClient;

use Thrift\Protocol\TMultiplexedProtocol;

use Thrift\Exception\TException;

use Thrift\Protocol\TBinaryProtocol;

use Thrift\Transport\TBufferedTransport;

use Thrift\Transport\TSocket;

class UserService

{

public function getUserInfo(int $id)

{

try {

// 建立与 RpcServer 的连接

$socket = new TSocket("127.0.0.1", "8888");

$socket->setRecvTimeout(30000); // 超时时间

$socket->setDebug(true);

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

$protocol = new TBinaryProtocol($transport);

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

$client = new UserClient($thriftProtocol);

$transport->open();

$result = $client->getInfo($id);

$transport->close();

return $result;

} catch (TException $TException) {

dd($TException);

}

}

}

同样,为了简化代码和流程,我这里将连接和请求代码写到一起了,如果有多个服务接口,传输层是可以共用的,需要拆分开。这里我们先建立与 RPC 服务器的连接,然后通过调用 App\Thrift\User\UserClient 提供的 getInfo 请求 RPC 服务端 App\Services\Server\UserService 类提供的 getInfo 方法获取用户信息并返回。

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

use App\Services\Client\UserService;

Route::get('/user/{id}', function($id) {

$userService = new UserService();

$user = $userService->getUserInfo($id);

return $user;

});

该路由通过匿名函数定义了路由处理逻辑:调用 App\Services\Client\UserService 的 getUserInfo 方法获取用户信息。需要与传统的 PHP 请求处理区分的是,这个请求底层不是在本地通过内存调用完成的,而是通过 RPC 客户端请求 RPC 服务端接口基于远程服务调用完成的。

测试 RPC 服务调用

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

修改项目根目录下 .env 中的数据库相关配置,运行数据迁移生成 users 表:

php artisan migrate

然后初始化 users 表数据:

4228a753e2cb1a95bf2c4b1b3610616d.png

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

php artisan rpc:start

6774b89181da41f5dd3b3b7179c55907.png

再新开一个终端窗口启动 Laravel 应用(RPC 客户端):

php artisan serve

d0de74f4657a9d1756049ca160c7a976.png

然后就可以在浏览器中访问获取用户信息的路由:

b7c7786cf3155b1cb2929cd0abd1e6f2.png

成功获取到用户记录,说明 RPC 远程服务调用成功。

可以看到,Thrift 只是个 RPC 框架而已,只解决了通信协议和数据传输问题,对于服务治理和容错并没有提供对应的解决方案,需要我们自己去实现,而且基于 PHP 实现的服务器在高并发情况下可能无法满足微服务接口的性能要求,后面我们将从这几个方面来完善这个示例应用。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值