Swoft 是一款基于 Swoole 扩展实现的 PHP 微服务协程框架。Swoft 能像 Go 同样,内置协程网络服务器及经常使用的协程客户端且常驻内存,不依赖传统的 PHP-FPM。有相似 Go 语言的协程操做方式,有相似 Spring Cloud 框架灵活的注解、强大的全局依赖注入容器、完善的服务治理、灵活强大的 AOP、标准的 PSR 规范实现等等。php
Swoft 经过长达三年的积累和方向的探索,把 Swoft 打形成 PHP 界的 Spring Cloud, 它是 PHP 高性能框架和微服务治理的最佳选择。html
Swoft 官方建议开发者使用 Service mesh 模式,好比 Istio/Envoy 框架,把业务和服务治理分开,可是 Swoft 也为中小型企业快速构建微服务提供了一套微服务组件。git
服务注册与发现,须要用到 Swoft 官方提供的 swoft-consul 组件,若是其它第三方也相似。github
监听 SwooleEvent::START
事件,注册服务web
/** * 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;
}
}
复制代码
配置服务提供者express
return [
'user' => [
'class' => ServiceClient::class,
'provider' => bean(RpcProvider::class)
// ...
]
];
复制代码
Swoft 使用 @Breaker
注解实现熔断,能够在***任何方法***上面进行熔断操做。json
/** * 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):