think-swoole扩展实现在传统php-fpm环境调用rpc服务

官方项目地址https://github.com/top-think/think-swoole

tp官方的think-swoole扩展提供了一个rpc服务和客户端,但是他的rpc客户端只能在swoole的环境下运行

但是swoole官方是提供了同步客户端/swoole/client的,如果把框架的client更换成官方的同步client,应该就能实现在传统的fpm环境中调用swoole环境下的rpc。

<?php
namespace appservice;
use Exception;
use Generator;
use SwooleClient;
use SwooleCoroutine;
use thinkhelperArr;
use thinkService;
use thinkswooleexceptionRpcClientException;
use thinkswoolePool;
use thinkswoolerpcclientConnector;
use thinkswoolerpcclientGateway;
use thinkswoolerpcclientProxy;
use thinkswoolerpcJsonParser;
use thinkswoolerpcPacker;
use Throwable;
class SwooleRpcServiceLoad extends Service
{
 public $rpcServices = [];
 /**
 * 注册服务 * * @return mixed
 */ public function register()
 { if (php_sapi_name() == 'fpm-fcgi') {
 if (file_exists($rpc = $this->app->getBasePath() . 'rpc.php')) {
 $this->rpcServices = (array)include $rpc;
 }
 } } /**
 * 执行服务 * * @return mixed
 */ public function boot()
 { if (!empty($clients = config('swoole.rpc.client')) && $this->rpcServices) {
 try {
 foreach ($this->rpcServices as $name => $abstracts) {
 $parserClass = config("swoole.rpc.client.{$name}.parser", JsonParser::class);
 $parser = $this->app->make($parserClass);
 $gateway = new Gateway($this->createRpcConnector($name), $parser);
 foreach ($abstracts as $abstract) {
 $this->app->bind($abstract, function () use ($gateway, $name, $abstract) {
 return $this->app->invokeClass(Proxy::getClassName($name, $abstract), [$gateway]);
 });
 }
 } } catch (Exception | Throwable $e) {
 } } } protected function createRpcConnector($name)
 { return new class($name) implements Connector {
 public $name;
 public function __construct($name)
 { $this->name = $name;
 }
 public function sendAndRecv($data)
 { if (!$data instanceof Generator) {
 $data = [$data];
 }
 $config = config('swoole.rpc.client.' . $this->name);
 $client = new Client(SWOOLE_SOCK_TCP);
 $host = Arr::pull($config, 'host');
 $port = Arr::pull($config, 'port');
 $timeout = Arr::pull($config, 'timeout', 5);
 $client->set([
 'open_length_check' => true,
 'package_length_type' => Packer::HEADER_PACK,
 'package_length_offset' => 0,
 'package_body_offset' => 8,
 ]);
 $client->connect($host, $port, $timeout);
 try {
 foreach ($data as $string) {
 if (!$client->send($string)) {
 $this->onError($client);
 }
 } $response = $client->recv();
 if ($response === false || empty($response)) {
 $this->onError($client);
 }
 return $response;
 } finally {
 $client->close();
 }
 } protected function onError(Client $client)
 { $client->close();
 throw new RpcClientException(swoole_strerror($client->errCode), $client->errCode);
 }
 };
 }
}

把上面这个服务在thinkphp框架中注册,就可以实现在fpm环境下调用think-swoole的rpc。
原理就是检测当前是否在fpm环境,是的话手动注册rpc服务,官方的扩展是要使用php think swoole start命令启动时,才能在代码中访问rpc接口的,注册了这个服务以后,就可以在fpm环境下使用了,并且不影响其他功能。

区别:
1官方扩展使用的是连接池,这里去掉了。
2官方扩展使用的是协程客户端,这里使用的是同步客户端

用法:
跟官方一致

阅读 107

推荐阅读