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

分布式服务,是将多个具有不同或相同功能的服务分散在不同的服务器上,对外提供服务。
那么在分布式服务中,使用 PHP-Casbin 作为权限控制时,不同服务器上的服务的策略要保证是同步的。这里我们主要探讨常驻内存的 PHP 服务,在常驻内存的服务中,PHP-Casbin 一般是单例模式,所有的策略都会加载到内存,性能出色。
PHP-FPM 下每次都重新初始化
Enforcer并重新加载策略,不需要做额外的策略同步。
在 Casbin 中提供了 Watcher ,用于多实例间的消息策略同步。
原理
当某个实例的Enforcer中的策略发生变化时,调用 Watcher ,向消息队列(MQ)中推送消息,监听到该消息队列的Enforcer收到消息后,自动刷新当前实例中的策略。
主要是在常驻进程的框架中使用 Casbin ,例如:Swoole、WorkerMan、ReactPHP 等。
第一种是单实例、多进程,进程中的数据相互隔离的;第二种则是多实例的场景。
环境
这里采用 PHP 8.4、Swoole 作为演示环境,并且借助 Redis watcher for PHP-Casbin in Swoole 作为 Watcher。
使用composer安装一下依赖:
composer require casbin/casbin
composer require casbin/dbal-adapter
composer require casbin/swoole-redis-watcher
编码
初始化 Swoole 的 Server,使用 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 仓库:github.com/php-casbin 。
原文:PHP-Casbin 在分布式服务中利用 Watcher 做策略同步
本作品采用《CC 协议》,转载必须注明作者和本文链接
关于 LearnKu
推荐文章: