Swoft 是一款基于 Swoole 扩展实现的 PHP 微服务协程框架。Swoft 能像 Go 一样,内置协程网络服务器及常用的协程客户端且常驻内存,不依赖传统的 PHP-FPM。有类似 Go 语言的协程操作方式,有类似 Spring Cloud 框架灵活的注解、强大的全局依赖注入容器、完善的服务治理、灵活强大的 AOP、标准的 PSR 规范实现等等。
Swoft 通过长达三年的积累和方向的探索,把 Swoft 打造成 PHP 界的 Spring Cloud, 它是 PHP 高性能框架和微服务治理的最佳选择。
Swoft 官方建议开发者使用 Service mesh 模式,比如 Istio/Envoy 框架,把业务和服务治理分开,但是 Swoft 也为中小型企业快速构建微服务提供了一套微服务组件。
服务注册与发现,需要用到 Swoft 官方提供的 swoft-consul 组件,如果其它第三方也类似。
监听 SwooleEvent::START
事件,注册服务
/** * Class RegisterServiceListener * * @since 2.0 * * @Listener(event=SwooleEvent::START) */ class RegisterServiceListener implements EventHandlerInterface { /** * @Inject() * * @var Agent */ private $agent; /** * @param EventInterface $event */ public function handle(EventInterface $event): void { /* @var HttpServer $httpServer */ $httpServer = $event->getTarget(); $service = [ // .... ]; $scheduler = Swoole/Coroutine/Scheduler(); $scheduler->add(function () use ($service) { // Register $this->agent->registerService($service); CLog::info('Swoft http register service success by consul!'); }); $scheduler->start(); } }
监听 SwooleEvent::SHUTDOWN
事件,取消服务
/** * Class DeregisterServiceListener * * @since 2.0 * * @Listener(SwooleEvent::SHUTDOWN) */ class DeregisterServiceListener implements EventHandlerInterface { /** * @Inject() * * @var Agent */ private $agent; /** * @param EventInterface $event */ public function handle(EventInterface $event): void { /* @var HttpServer $httpServer */ $httpServer = $event->getTarget(); $scheduler = Swoole/Coroutine/Scheduler(); $scheduler->add(function () use ($httpServer) { $this->agent->deregisterService('swoft'); }); $scheduler->start(); } }
定义服务提供者
/** * Class RpcProvider * * @since 2.0 * * @Bean() */ class RpcProvider implements ProviderInterface { /** * @Inject() * * @var Agent */ private $agent; /** * @param Client $client * * @return array * @example * [ * 'host:port' * ] */ public function getList(Client $client): array { // Get health service from consul $services = $this->agent->services(); $services = [ ]; return $services; } }
配置服务提供者
return [ 'user' => [ 'class' => ServiceClient::class, 'provider' => bean(RpcProvider::class) // ... ] ];
Swoft 使用 @Breaker
注解实现熔断,可以在 任何方法 上面进行熔断操作。
/** * Class BreakerLogic * * @since 2.0 * * @Bean() */ class BreakerLogic { /** * @Breaker(fallback="funcFallback") * * @return string * @throws Exception */ public function func(): string { // Do something throw new Exception('Breaker exception'); } /** * @return string */ public function funcFallback(): string { return 'funcFallback'; } }
Swoft 中使用 @RateLimiter
注解实现服务限流,可以在 任何方法 上面限流,不仅仅是控制器,且 KEY 还支持 symfony/expression-language 表达式。
/** * Class LimiterController * * @since 2.0 * * @Controller(prefix="limiter") */ class LimiterController { /** * @RequestMapping() * @RateLimiter(key="request.getUriPath()", fallback="limiterFallback") * * @param Request $request * * @return array */ public function requestLimiter(Request $request): array { $uri = $request->getUriPath(); return ['requestLimiter', $uri]; } /** * @param Request $request * * @return array */ public function limiterFallback(Request $request): array { $uri = $request->getUriPath(); return ['limiterFallback', $uri]; } }
配置中心,需要用到 Swoft 官方提供的 Swoft-apollo 组件,如果其它第三方也类似。
/** * Class AgentCommand * * @since 2.0 * * @Command("agent") */ class AgentCommand { /** * @Inject() * * @var Config */ private $config; /** * @CommandMapping(name="index") */ public function index(): void { $namespaces = [ 'application' ]; while (true) { try { $this->config->listen($namespaces, [$this, 'updateConfigFile']); } catch (Throwable $e) { CLog::error('Config agent fail(%s %s %d)!', $e->getMessage(), $e->getFile(), $e->getLine()); } } } /** * @param array $data * * @throws ContainerException * @throws ReflectionException */ public function updateConfigFile(array $data): void { foreach ($data as $namespace => $namespaceData) { $configFile = sprintf('@config/%s.php', $namespace); $configKVs = $namespaceData['configurations'] ?? ''; $content = '<?php return ' . var_export($configKVs, true) . ';'; Co::writeFile(alias($configFile), $content, FILE_NO_DEFAULT_CONTEXT); CLog::info('Apollo update success!'); /** @var HttpServer $server */ $server = bean('httpServer'); $server->restart(); } } }
Agent 只需要在服务(Http/RPC/Websocket)启动前,运行即可。
php bin/swoft agent:index
移除(Remove)
request->json()
方法( c9e8f04 ) 新增(Enhancement):
getFile
方法获取文件上传保存之后的信息( fe7e3a6 ) restart()
服务新增重启方法( 2ffec37 ) use
错误提示( b1cec04 ) unfields
( b1bf44f ) batchUpdateByIds
( dc58011 ) 修复(Fixed):
null
问题( a69347c ) null
问题( 4d091be ) 更新(Update):
ErrorHanlders
为 ErrorManager
( f3a8f04b ) E_ALL | E_STRICT
( afff9029 ) 扩展(Extra):