microse/microse-swoole
Composer 安装命令:
composer require microse/microse-swoole
包简介
Micro Remote Object Serving Engine based on swoole
README 文档
README
Microse (stands for Micro Remote Object Serving Engine) is a light-weight engine that provides applications the ability to serve modules as RPC services, whether in another process or in another machine.
This is the PHP version of the microse implementation based on Swoole. For API reference, please check the API documentation, or the Protocol Reference.
Other implementations:
- microse-node Node.js implementation
- microse-py python implementation
Install
composer require microse/microse-swoole
Peel The Onion
In order to use microse, one must create a root ModuleProxyApp instance, so
other files can use it as a root proxy and access its sub-modules.
Example
// src/app.php require __DIR__ . "/../vendor/autoload.php"; use Microse\ModuleProxyApp; // Create an abstract class to be used for IDE intellisense: abstract class AppInstance extends ModuleProxyApp { } // Create the instance amd add type annotation: /** @var AppInstance */ $app = new ModuleProxyApp("App");
In other files, just define a class with the same name as the filename, so that
another file can access it directly via the $app instance.
// src/Bootstrap.php namespace App; class Bootstrap { public function init(): void { // ... } }
Don't forget to augment types in the AppInstance class if you need IDE typing
support:
use App\Bootstrap; abstract class AppInstance extends ModuleProxyApp { public Bootstrap $Bootstrap; }
And other files can access to the module as a property:
// src/index.php include_once __DIR__ . "/app.php"; // Accessing the module as a singleton and calling its function directly. $app->Bootstrap->init();
Remote Service
The above example accesses the module and calls the function in the current process, but we can do more, we can serve the module as a remote service, and calls its functions as remote procedures.
Example
For example, if I want to serve a user service in a different process, I just have to do this:
// src/Services/User.py namespace App\Services; class User { private $users = [ ["firstName" => "David", "lastName" => "Wood"] ] public function getFullName(string $firstName): string { foreach ($this->users as $user) { if ($user["firstName"] === $firstName) { return $firstName . " " . $user["lastName"]; } } } } // src/app.php use App\Services\User; abstract class AppInstance extends ModuleProxyApp { public Services $Services; } abstract class Services { public User $User; }
// src/server.php include_once __DIR__ . "/app.php"; go(function () { global $app; $server = $app->serve("ws://localhost:4000"); // Register the service, no need to include class file or set properties, // modules can be accessed directly. $server->register($app->Services->User); echo "Server started!\n"; });
Just try php server.php and the services will be started immediately.
And in the client-side code, connect to the service before using remote functions.
// client.php include_once __DIR__ . "/app.php"; go(function () { global $app; $client = $app->connect("ws://localhost:4000"); $client->register($app->Services->User); // Accessing the instance in local style but actually calling remote. // Since we're using swoole, this procedure is actually asynchronous. $fullName = $app->Services->User->getFullName("David"); echo $fullName . "\n"; // David Wood });
NOTE: to ship a service in multiple server nodes, just create and connect to multiple channels, and register the service to each of them, when calling remote functions, microse will automatically calculate routes and redirect traffics to them.
NOTE: RPC calling will serialize (via JSON) all input and output data, those data that cannot be serialized will be lost during transmission.
Generator Support
When in the need of transferring large data, generator functions could be a great help, unlike general functions, which may block network traffic when transmitting large data since they send the data as a whole, generator functions, on the other hand, will transfer the data piece by piece.
// src/Services/User.php namespace App\Services; class User { private $friends = [ "David" => [ [ "firstName" => "Albert", "lastName" => "Einstein" ], [ "firstName" => "Nicola", "lastName" => "Tesla" ], // ... ], // ... ]; public function getFriendsOf(string $name): \Generator { $friends = @$this->friends[$name]; if ($friends) { foreach ($friends as $friend) { yield $friend["firstName"] => $friend["lastName"]; // NOTE: only PHP supports 'yield $key => $value', if this // function is call from other languages, such as Node.js, // the '$key' will be ignored. } return "These are all friends"; } } }
$generator = $app->Services->User->getFriendsOf("David"); foreach ($generator as $firstName => $lastName) { echo $firstName . " ". $lastName . "\n"; // Albert Einstein // Nicola tesla // ... } // We can get the return value as well: $returns = $generator->getReturn(); // These are all friends
The generator function returns an rpc version of the Generator, so if you want
to send data into the generator, you can use Generator::send() to do so, the
value passed to the method will be delivered to the remote instance as well.
Life Cycle Support
Since swoole already handles asynchronous operations under the hood, so
lifecycle support is done by the original __construct and __destruct methods,
and there is no need for any extra efforts.
Standalone Client
Microse also provides a way to be running as a client-only application, in this case the client will not actually load any modules since there are no such files, instead, it just map the module names so you can use them as usual.
In the following example, we assume that $app->services->user service is
served by a Node.js program, and we can use it in our PHP program as usual.
use Microse\ModuleProxyApp; /** @var AppInstance */ $app = new ModuleProxyApp("app", false); // pass the second argument false go(function () use ($app) { $client = $app->connect("ws://localhost:4000"); $client->register($app->services->user); $fullName = $app->services->user->getFullName("David"); echo $fullName . "\n"; // David Wood });
For client-only application, you may need to declare all abstract classes:
abstract class AppInstance extends ModuleProxyApp { public services $services; } abstract class services { public user $user; } // Use 'interface' works as well since 'user' doesn't contain properties. interface user { abstract function getFullName(string $name): string; }
Process Interop
This implementation supports interop in the same process, that means, if it detects that the target remote instance is served in the current process, the function will always be called locally and prevent unnecessary network traffic.
microse/microse-swoole 适用场景与选型建议
microse/microse-swoole 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 5 次下载、GitHub Stars 达 0, 最近一次更新时间为 2020 年 10 月 25 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「rpc」 「micro-service」 「module-proxy」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 microse/microse-swoole 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 microse/microse-swoole 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 microse/microse-swoole 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Microservice RPC through message queues.
Laravel Service Provider for imgproxy: Resize your images instantly and securely
Control Nginx as a reverse proxy through plinker RPC
A API library that make it easy to access the Webuntis JSON RPC 2.0 API
rpc gateway lib
Implementation of Bitclout API interaction through its node
统计信息
- 总下载量: 5
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 6
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2020-10-25