butschster / lumen-microservice
此包将帮助您使用Lumen框架作为微服务,无需额外知识即可使用AMQP和JMS序列化器。
Requires
- php: ^7.4
- ext-json: *
- firebase/php-jwt: ^5.2
- illuminate/config: ^7.0|^8.0
- illuminate/console: ^7.0|^8.0
- illuminate/contracts: ^7.0|^8.0
- illuminate/pipeline: ^7.0|^8.0
- illuminate/support: ^7.0|^8.0
- illuminate/validation: ^7.0|^8.0
- jms/serializer: ^3.9
- nunomaduro/collision: ^5.0
- php-amqplib/php-amqplib: ^2.12
- phpdocumentor/reflection-docblock: ^5.2
- psr/log: ^1.1
- react/event-loop: ^1.1
- react/promise: ^2.8
- webmozart/assert: ^1.8
- zircote/swagger-php: ^3.0
Requires (Dev)
- mockery/mockery: ^1.0
- phpunit/phpunit: ^8.0
- symfony/var-dumper: ^5.2
This package is auto-updated.
Last update: 2024-09-20 22:12:58 UTC
README
此包可以帮助您使用Lumen框架或Laravel作为微服务,无需额外知识。只需安装包,创建交换点类,并通过MQ在服务之间交换信息即可。
此包使用 JMS\Serializer 进行消息序列化。
备注:您可以使用此服务进行测试 https://www.cloudamqp.com。他们有一个免费计划。
特性
- 开箱即用,易于使用
- 易于配置
- jms serializer
- 开箱即用MQ
- 经过充分测试
要求
- Lumen或Laravel 7.x至8.x
- PHP 7.4及以上
安装和配置
从命令行运行
composer require butschster/lumen-microservice
注册服务提供者
// bootstrap.php $app->register(Butschster\Exchanger\Providers\ExchangeServiceProvider::class);
将包的 config
目录中的配置文件复制到您的Lumen应用中并注册它们。
$app->configure('amqp'); $app->configure('microservice'); $app->configure('serializer');
向您的 .env 文件中添加变量
MICROSERVICE_NAME=...
MICROSERVICE_VERSION=1.0.0
RABBITMQ_HOST=...
RABBITMQ_USERNAME=...
RABBITMQ_PASSWORD=...
RABBITMQ_VHOST=...
JWT_SECRET=...
在您的应用中创建交换点
此点将用于接收来自其他服务的请求,并发送响应。
namespace App\Exchange\Point; use Butschster\Exchanger\Contracts\Exchange\Point as PointContract; use Psr\Log\LoggerInterface; use Butschster\Exchanger\Contracts\Exchange\IncomingRequest; class Point implements PointContract { public function getName(): string { return 'com.test'; } /** * @subject com.test.action.test */ public function testSubject(IncomingRequest $request, LoggerInterface $logger) { $logger->info( sprintf('info [%s]:', $request->getSubject()), [$request->getBody()] ); // Response $payload = new ...; $request->sendResponse($payload); // or $request->sendEmptyResponse(); // or $request->acknowledge(); } /** * @subject com.test.action.test1 */ public function anotherTestSubject(IncomingRequest $request, LoggerInterface $logger) { $payload = new ...; $request->sendResponse($payload); } }
然后注册此点
use App\Exchange\Point; use Illuminate\Support\ServiceProvider; use Butschster\Exchanger\Contracts\Exchange\Point as PointContract; class AppServiceProvider extends ServiceProvider { public function register() { $this->app->singleton(PointContract::class, Point::class); } }
注册控制台命令
use Butschster\Exchanger\Console\Commands\RunMicroservice; class Kernel extends ConsoleKernel { protected $commands = [ RunMicroservice::class ]; }
发送请求
要从其他服务请求信息,您应使用 ExchangeManager
use Butschster\Exchanger\Contracts\ExchangeManager; class UserController { public function getUser(ExchangeManager $manager, int $userId) { $requestPayload = new GetUserByIdPayload($userId); $request = $manager->request('com.test.action.test', $requestPayload); $user = $request->send(UserPayload::class); // You can set delivery mode to persistent $user = $request->send(UserPayload::class, true); } } // User Request Payload use JMS\Serializer\Annotation\Type; class GetUserByIdPayload implements \Butschster\Exchanger\Contracts\Exchange\Payload { /** @Type("string") */ public string $userId; public function __construct(string $userId) { $this->userId = $userId; } } // User Payload use JMS\Serializer\Annotation\Type; class UserPayload implements \Butschster\Exchanger\Contracts\Exchange\Payload { /** @Type("string") */ public string $id; /** @Type("string") */ public string $username; /** @Type("string") */ public string $email; /** @Type("Carbon\Carbon") */ public \Carbon\Carbon $createdAt; }
广播
如果您想发送事件,应使用 ExchangeManager
的 broadcast
方法
use Illuminate\Http\Request; use Butschster\Exchanger\Contracts\ExchangeManager; class UserController { public function update(ExchangeManager $manager, Request $request, User $user) { $payload = new UserPayload(); $data = $request->validate(...); $user->update($data); $payload->id = $user->id; $payload->username = $user->username; ... $manager->broadcast('com.user.event.updated', $payload); // You can set delivery mode to persistent $manager->broadcast('com.user.event.updated', $payload, true); } }
实体映射
您可以在 serializer.php
配置中配置实体映射。
// serializer.php return [ 'mapping' => [ Domain\User\Entities\User::class => [ 'to' => Payloads\User::class, 'attributes' => [ 'id' => ['type' => 'string'], 'username' => ['type' => 'string'], 'email' => ['type' => 'string'], 'balance' => ['type' => Domain\Billing\Money\Token::class], 'createdAt' => ['type' => \Carbon\Carbon::class], ] ], Domain\Billing\Money\Token::class => [ 'to' => Payloads\Billing\Token::class, 'attributes' => [ 'amount' => ['type' => \Brick\Math\BigDecimal::class], ] ], ], // ... ];
然后您可以轻松地将实体转换为有效载荷
use Butschster\Exchanger\Contracts\Serializer\ObjectsMapper; class UserController { public function update(ObjectsMapper $mapper, ExchangeManager $manager, Request $request, Domain\User\Entities\User $user) { $data = $request->validate(...); $user->update($data); $payload = $mapper->toPayload($user); $manager->broadcast('com.user.event.updated', $payload); } }
自定义类型
如果您想使用自定义JMS序列化器类型,应使用处理器。它们可以添加到 serializer.php
配置中。
// serializer.php return [ 'handlers' => [ Butschster\Exchanger\Jms\Handlers\CarbonHandler::class, Infrastructure\Microservice\Jms\Handlers\BigDecimalHandler::class ], // .. ]; // BigDecimalHandler.php namespace Infrastructure\Microservice\Jms\Handlers; use Brick\Math\BigDecimal; use Butschster\Exchanger\Contracts\Serializer; use Butschster\Exchanger\Contracts\Serializer\Handler; use JMS\Serializer\GraphNavigatorInterface; use JMS\Serializer\Handler\HandlerRegistryInterface; class BigDecimalHandler implements Handler { public function serialize(Serializer $serializer, HandlerRegistryInterface $registry): void { $registry->registerHandler( GraphNavigatorInterface::DIRECTION_SERIALIZATION, BigDecimal::class, 'json', function ($visitor, BigDecimal $value, array $type) { return $value->toInt(); } ); } public function deserialize(Serializer $serializer, HandlerRegistryInterface $registry): void { $registry->registerHandler( GraphNavigatorInterface::DIRECTION_DESERIALIZATION, BigDecimal::class, 'json', function ($visitor, $value, array $type) { return BigDecimal::of($value); } ); } }
服务运行
此单条命令将运行您的微服务并开始监听在交换点中注册的命令。
php artisan service:run
Supervisor是Linux操作系统的进程监控器,如果horizon进程失败,则会自动重启。要在Ubuntu上安装Supervisor,您可以使用以下命令
sudo apt-get install supervisor
Supervisor配置文件通常存储在 /etc/supervisor/conf.d 目录中。在此目录中,您可以创建任意数量的配置文件,以指示supervisor如何监控您的进程。例如,让我们创建一个microservice.conf文件,该文件启动并监控一个进程
[program:microservice]
process_name=%(program_name)s
command=php /var/www/app.com/artisan service:run
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/var/www/app.com/storage/logs/microservice.log
stopwaitsecs=3600
一旦配置文件已创建,您可以使用以下命令更新Supervisor配置并启动进程
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start microservice