基于 Thrift + Laravel RPC 调用实现

项目初始化

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

1

laravel new thrift

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

namespace php App.Thrift.OrgThrift

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

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

1

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

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

 

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

1

composer require apache/thrift

编写服务端代码

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

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

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

1

php artisan make:command RpcServerStart

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

<?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 中注册上述命令类使其生效:

1

2

3

4

5

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 文件生成相关的服务代码:

1

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

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

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

<?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 中注册客户端请求路由:

1

2

3

4

5

6

7

8

use AppServicesClientOrgService;

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

$OrgService = new OrgService();

// dd($userService);

$Org = $OrgService`->routeOrg($id);`

return $Org`;`

});

测试 RPC 服务调用

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

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

1

php artisan rpc:start

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

 然后composer更新:

1

composer dump-autoload

原文地址:https://www.cnblogs.com/hzcya1995/p/13309193.html