A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

什么是 Swoft ?
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 组件,如果其它第三方也类似。
声明Agent/** * 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
Agent 只需要在服务(Http/RPC/Websocket)启动前,运行即可。

3 个回复

倒序浏览
有任何问题欢迎在评论区留言
回复 使用道具 举报
或者添加学姐微信号
DKA-2018
回复 使用道具 举报
感谢分享~~
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马