hyperf 3.1安装和配置php-zookeeper扩展

Hyperf 提供了分布式系统的外部化配置支持,默认适配了:

本章节我们使用zookeeper扩展:

环境准备:

php版本:php8.2 

zookeeper版本:3.8.0

php-zookeeper:1.2.1

centos:7.6

hyperf官方使用的是swoole/ext-zookeeper扩展,由于这个扩展很久没有更新了,目前不兼容php8以上的版本,我试了好几个8的版本都不行,无奈只能换到php-zookeeper扩展

1、首先我们需要安装zookeeper,具体安装流程在之前的章节已经说过了

2、安装需要的依赖,由于我系统已经自己安装了gcc(4.9.4),gcc-c++,所以我不需要安装了

yum install -y cppunit-devel ant build-essential zlib zlib-devel openssl openssl-devel pcre pcre-devel autoconf automake

3、我们需要编译zookeeper的c扩展,所以我们需要去下载zookeeper源码编译c的扩展,地址:https://archive.apache.org/dist/zookeeper/zookeeper-3.8.0/apache-zookeeper-3.8.0.tar.gz
如果下载很慢的话,可以使用我百度网盘分享的:

链接:https://pan.baidu.com/s/1vfvLBEbCGDxZkfKoX7Jm4g
提取码:gprp

wget https://archive.apache.org/dist/zookeeper/zookeeper-3.8.0/apache-zookeeper-3.8.0.tar.gz
cd apache-zookeeper-3.8.0

由于我是3.8的版本高于3.6,所以默认解压缩包后是没有 build.xml,ivy.xml,ivysettings.xml 这三个文件,所以我们需要去3.6版本以下的去获取这三个文件,然后并复制到当前目录下,这里我是3.5.9的版本,地址:https://archive.apache.org/dist/zookeeper/zookeeper-3.5.9/apache-zookeeper-3.5.9.tar.gz
解压缩之后,分别将三个文件复制到 apache-zookeeper-3.8.0这个目录下,然后分别执行以下命令:

cp build.xml ivy* /www/server/apache-zookeeper-3.8.0
cd apache-zookeeper-3.8.0
ant compile_jute
cd /www/server/apache-zookeeper-3.8.0/zookeeper-client/zookeeper-client-c
autoreconf -if
./configure --prefix=/usr/local/zookeeper-lib
make && make install

至此就已经编译好了c的扩展,我们可以在 /usr/local/zookeeper-lib 目录下看到已经编译好的

 4、接下来我们编译安装php-zookeeper扩展,链接地址为:https://pecl.php.net/get/zookeeper-1.2.1.tgz

如果下载很慢的话,百度网盘分享:

链接:https://pan.baidu.com/s/14-ZSl7RFl7S3G5qiYugxzg
提取码:y8fz

接着我们分别执行以下命令进行编译安装:

wget https://pecl.php.net/get/zookeeper-1.2.1.tgz
tar -zxvf zookeeper-1.2.1.tgz
cd zookeeper-1.2.1
ln -s /www/server/php/82/bin/php-config /usr/bin
phpize
./configure --with-libzookeeper-dir=/usr/local/zookeeper-lib
make && make install

至此就已经安装好了php-zookeeper扩展,我们只需要将 /www/server/php/82/lib/php/extensions/no-debug-non-zts-20220829/zookeeper.so  加入到php配置文件中去

extension = zookeeper.so

重启php服务

php -m | grep zookeeper 
php --ri zookeeper

查看是否已经加载了zookeeper扩展:

 5、安装完成后,在hyperf中使用,文档我们需要安装扩展包:

cd /www/wwwroot/hyperf
composer require hyperf/config-center
composer require hyperf/config-zookeeper
#生成配置文件
php bin/hyperf.php vendor:publish hyperf/config-center

由于我们安装的是php-zookeeper扩展,并不是hyperf指定的swoole/zookeeper扩展,所以安装后需要更改源码包才行

在 /vendor/hyperf/config-zookeeper/src/Client.php中,需要修改以下代码:

 首先需要注释掉  use Swoole\Zookeeper; 代码段,然后在pull方法中更改代码:

public function pull(): array
    {
        $zk = new \Zookeeper($this->config->get('config_center.drivers.zookeeper.server'));
        $path = $this->config->get('config_center.drivers.zookeeper.path', '/conf');
        $config = $zk->get($path);
        return json_decode($config, true);
    }

然后在生成的配置文件config_center.php中,我们配置一下相关的代码:

<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */
use Hyperf\ConfigCenter\Mode;

use function Hyperf\Support\env;

return [
    'enable' => (bool) env('CONFIG_CENTER_ENABLE', true),
    'driver' => env('CONFIG_CENTER_DRIVER', 'zookeeper'),
    'mode' => env('CONFIG_CENTER_MODE', Mode::COROUTINE),
    'drivers' => [
        'zookeeper' => [
            'driver' => Hyperf\ConfigZookeeper\ZookeeperDriver::class,
            'server' => env('ZOOKEEPER_SERVER', '192.168.43.21:2181'),
            'path' => env('ZOOKEEPER_CONFIG_PATH', '/conf'),
            'interval' => 5,
        ],
    ],
];

然后我们启动hyperf

php bin/hyperf.php server:watch

启动之后,报错,是因为zookeeper服务端没有创建 /conf这个节点,所以我这里写了一个代码创建/conf,并将本地的配置推送到zookeeper服务端:

<?php
declare(strict_types=1);

namespace App\Controller\Mouse;
use App\Controller\AbstractController;
class ConfigCenter extends AbstractController
{
    public function index()
    {
        /** @var \Hyperf\Contract\ConfigInterface $serverConfig */
        $serverConfig = $this->container->get(\Hyperf\Contract\ConfigInterface::class);
        $zookeeperAddress = $serverConfig->get('config_center.drivers.zookeeper.server');
//        $serverConfig->set('databases.default.host','127.0.0.1');
        $path = $serverConfig->get('config_center.drivers.zookeeper.path');
        $serverConfig = \Hyperf\Collection\collect($serverConfig)->toArray();
//        foreach ($serverConfig as $key=>$value){
//            $serverConfig = $value;
//        }
        $config = json_encode($serverConfig);
        $zk = new \Zookeeper($zookeeperAddress);
        $isExist = $zk->exists($path);
        $aclArray = array(
            array(
                'perms'  => \Zookeeper::PERM_ALL,
                'scheme' => 'world',
                'id'     => 'anyone',
            )
        );
//如果节点不存在则创建接节点
if(!$isExist){ $isAdd = $zk->create($path,$config,$aclArray); var_dump($isAdd); } $isSet = $zk->set($path,$config); var_dump($isSet); return $this->jsonResponse(1,'成功更新配置'); } }

更新到zookeeper服务端后,重新启动hyperf,发现配置生效了,但是我尝试修改zookeeper服务端的配置后,本地hyperf配置也自动更新了,但是并没有重新加载配置:

 原来官方就是这么设计的,更新之后需要重启才能生效,但是我想要更新之后不需要重启,所以我这边使用配置更新事件来动态改动:

 

根据官方文档,我首先要注册一个事件,首先生成一个监听器:

php bin/hyperf gen:listener ConfigCenterListener

代码如下:

<?php

declare(strict_types=1);

namespace App\Listener;

use Hyperf\Contract\ConfigInterface;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\Event\Annotation\Listener;
use Hyperf\Event\Contract\ListenerInterface;
use Hyperf\ConfigCenter\Event\ConfigChanged;
use Hyperf\ConfigZookeeper\Client;
use Hyperf\Di\Annotation\Inject;
#[Listener]
class ConfigCenterListener implements ListenerInterface
{
    #[Inject]
    protected Client $zookeeper;

    #[Inject]
    protected ConfigInterface $config;

    #[Inject]
    protected StdoutLoggerInterface $logger;

    public function listen(): array
    {
        return [
            ConfigChanged::class,
        ];
    }

    protected function updateConfig(array $config): void
    {
        foreach ($config as $key => $value) {
            if (is_string($key)) {
                $this->config->set($key, $value);
                $this->logger->debug(sprintf('Config [%s] is updated', $key));
            }
        }
    }


    public function process(object $event): void
    {
        foreach($event->current as $value){
            $this->updateConfig($value);
        }
    }
}

添加完代码之后,$event 里面有两个属性,previous,current

previous:当配置变更之后会把之前的配置对象放在previous属性中,而current则是当前更新后的配置数据,所以我们需要将current属性中的配置再重新加载到config里面就行了。

重启hyperf已经生效,再次更新zookeeper服务端配置之后,本地也能自动更新配置并且生效了,至此hyperf使用zookeeper配置中心就完成,总的来说hyperf对zookeeper的支持还不算太好,主要是swoole/zookeeper不支持高版本的php,所以只能无奈更改hyperf的源代码之后才能实现,现在只能希望zookeeper的swoole扩展能更新一下吧!

posted @ 2024-01-14 08:44  来碗酒喝  阅读(85)  评论(0编辑  收藏  举报