php
Swoft 是一款基於 Swoole 擴展實現的 PHP 微服務協程框架。Swoft 能像 Go 同樣,內置協程網絡服務器及經常使用的協程客戶端且常駐內存,不依賴傳統的 PHP-FPM。有相似 Go 語言的協程操做方式,有相似 Spring Cloud 框架靈活的註解、強大的全局依賴注入容器、完善的服務治理、靈活強大的 AOP、標準的 PSR 規範實現等等。html
Swoft 經過長達三年的積累和方向的探索,把 Swoft 打形成 PHP 界的 Spring Cloud, 它是 PHP 高性能框架和微服務治理的最佳選擇。git
Swoft 官方建議開發者使用 Service mesh 模式,好比 Istio/Envoy 框架,把業務和服務治理分開,可是 Swoft 也爲中小型企業快速構建微服務提供了一套微服務組件。github
服務註冊與發現,須要用到 Swoft 官方提供的 swoft-consul 組件,若是其它第三方也相似。web
監聽 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(); } }
定義服務提供者express
/** * 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; } }
配置服務提供者json
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):