博客 / 詳情

返回

PHP-Casbin 在分佈式服務中利用 Watcher 做策略同步

分佈式服務,是將多個具有不同或相同功能的服務分散在不同的服務器上,對外提供服務。

那麼在分佈式服務中,使用 PHP-Casbin 作為權限控制時,不同服務器上的服務的策略要保證是同步的。這裏我們主要探討常駐內存的 PHP 服務,在常駐內存的服務中,PHP-Casbin 一般是單例模式,所有的策略都會加載到內存,性能出色。

PHP-FPM 下每次都重新初始化 Enforcer 並重新加載策略,不需要做額外的策略同步。

Casbin 中提供了 Watcher ,用於多實例間的消息策略同步。

原理

當某個實例的Enforcer中的策略發生變化時,調用 Watcher ,向消息隊列(MQ)中推送消息,監聽到該消息隊列的Enforcer收到消息後,自動刷新當前實例中的策略。

主要是在常駐進程的框架中使用 Casbin ,例如:Swoole、WorkerMan、ReactPHP 等。

第一種是單實例、多進程,進程中的數據相互隔離的;第二種則是多實例的場景。

環境

這裏採用 PHP 8.4Swoole 作為演示環境,並且藉助 Redis watcher for PHP-Casbin in Swoole 作為 Watcher

使用composer安裝一下依賴:

composer require casbin/casbin
composer require casbin/dbal-adapter

composer require casbin/swoole-redis-watcher

編碼

初始化 SwooleServer,使用 swoole 啓動一個HTTP服務常駐內存。

use Casbin\Enforcer;
use CasbinAdapter\DBAL\Adapter;
use CasbinWatcher\SwooleRedis\Watcher;
use Swoole\Http\Server;

Co::set(['hook_flags' => SWOOLE_HOOK_ALL]);

$serv = new Server('127.0.0.1', 9501);
$serv->set(['worker_num' => 4]);

在服務啓動後,注入回調函數,初始化Casbin的決策器。

$serv->on('WorkerStart', function($server, $worker_id) {
    global $enforcer;

    $adapter = Adapter::newAdapter([
        'driver' => 'pdo_mysql',
        'host' => '127.0.0.1',
        'dbname' => 'test',
        'user' => 'root',
        'password' => '',
        'port' => '3306',
    ]);

    $enforcer = new Enforcer('./path/to/model.conf', $adapter);

    // 設置 Watcher
    $watcher = new Watcher([
        'host' => '127.0.0.1',
        'password' => '',
        'port' => 6379,
        'database' => 0,
    ]);
    $enforcer->setWatcher($watcher);
});

$serv->start();

可以看到,在初始化決策器後,又初始化了Watcher,並調用決策器(Enforcer)設置Watcher

Swoole Watcher 是一個通過 redis發佈訂閲功能實現的消息生產和消費的。在 swoole 中使用協程異步非阻塞訂閲 redis 的消息,收到消息後觸發回調,隨後調用決策器的loadPolicy(),重新加載策略從而實現不同實例的策略更新。

最後

本文介紹瞭如何在分佈式多實例的架構下實現 Casbin 的策略同步,隨着新技術的不斷涌現,如今的 PHP 已經不再是完全依賴 PHP-FPM 來運行,不只是 Swoole,還有 FrankenPHP RoadRunner ReactPHP WorkerMan 等框架為 PHP 提供了運行環境來為 PHP 加速。

PHP-Casbin 還有非常多的擴展,為各種各樣的框架集成提供了便利,可以查看 GitHub 倉庫:https://github.com/php-casbin 。

user avatar luguodeshanyang 頭像 seth9shi 頭像
2 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.