Moodle的会话处理
Moodleでのセッション管理
会话管理设置的位置。
Moodleでは独自にセッション管理を行っているため、php.iniなどでPHPのセッション情報の保存先変更などを行っていても上書きされる。
そのため、config.phpに規定された内容を記載してセッション管理設定を変更する必要がある。
会话信息保存位置类型
-
- file: moodledata/sessionsディレクトリ(変更可)内にファイルとして保存する。実際はメモリ上に収まると考えられるため、シングルサーバ構成でおそらく最適。しかし、moodledataディレクトリがNFS上などにある場合は速度低下およびファイルロックの問題があるため不適。
-
- database: Moodle用データベースのsessionsテーブルに記録される。設定が楽だが、同時利用者が多いと簡単にパフォーマンスのボトルネックになる。
-
- memcached: Memcachedサーバとphp-pecl-memcachedを利用する。
-
- memcache: php-pecl-memcachedの代わりにphp-pecl-memcacheを利用する。セッションロックが不可能なため非推奨(config-dist.phpに記載)らしい。
Moodle 3.6から非対応になった。
redis: Redisサーバとphp-pecl-redisを利用する。memcached/memcacheと異なり、MUC(Moodle Universal Cache)と同居可能。
决定保存会话信息的位置
在Moodle中,会话信息的存储位置由以下部分决定。
/**
* Create handler instance.
*/
protected static function load_handler() {
global $CFG, $DB;
if (self::$handler) {
return;
}
// Find out which handler to use.
if (PHPUNIT_TEST) {
$class = '\core\session\file';
} else if (!empty($CFG->session_handler_class)) {
$class = $CFG->session_handler_class;
} else if (!empty($CFG->dbsessions) and $DB->session_lock_supported()) {
$class = '\core\session\database';
} else {
$class = '\core\session\file';
}
self::$handler = new $class();
}
根据阅读,根据默认设置,文件会被用作session存储方式,如果有其他定义,则会使用该定义。$CFG->dbsessions似乎是为了与过去保持兼容性(和便捷设置)而设立的。
请留意以下事项
如果使用了file作为存储的方式,在moodledata无法进行文件锁定的位置时,会导致会话信息无法保存(当PHP脚本在排他锁失败时会中止保存过程),从而无法登录。
此外,在安装过程中创建config.php的时机决定了是否能继续安装,因此需要在安装后进行追加。
如果是Web服务器+数据库服务器的搭配,可以通过更改file存储会话信息的位置来解决问题。如果存在多个Web服务器,则需要使用数据库、Memcached或Redis来共享会话信息。
关于设定
設定更改的背景
Pound配下で複数のWebサーバを利用している環境でdatabaseをセッション管理に利用していたが、50名程度が同時利用するような状況でまれにslow queryが記録され、Webサーバの負荷に余裕があるにも関わらず利用者から速度低下が報告されていたため設定を見直すこととした。なお、DBサーバは高速なストレージを利用していた訳ではない(安物NASでiSCSIを利用)。
如何设置
セッション情報保存先ごとの速度比較は行っていないが、MUCでも利用したいためredisを利用することにする。
DBサーバ(192.168.101.101)にRedisを導入してWebサーバ側からtelnetなどで疎通確認を行っておく。
Moodleのconfig.phpに以下の内容を記載して設定終了。詳しくはconfig.dist.phpを参照。
$CFG->dbsessions = false;
$CFG->session_handler_class = '\core\session\redis';
$CFG->session_redis_host = '192.168.101.101';
$CFG->session_redis_port = 6379;
$CFG->session_redis_database = 0;
$CFG->session_redis_prefix = '';
$CFG->session_redis_acquire_lock_timeout = 120;
$CFG->session_redis_lock_expire = 7200;
尽管$CFG->dbsessions在开头原本是不必要的,但为了避免在Moodle网站管理页面上启用DB会话检查,这样写入。
如果您使用的是Moodle 3.3或更新的版本,可以通过运行# yum install -y php-pecl-igbinary来安装igbinary模块,以提高性能速度。
可以通过使用telnet连接到Redis服务器并执行MONITOR命令来进行动作检查。
被覆写的会话相关设置
在Moodle 3.4版本中,由于PHP的设置值被重写了,所以无论在php.ini等文件中进行设置,都不会在Moodle上反映出来。在Moodle 3.1版本周围也是相同的情况。
session_name($sessionname);
session_set_cookie_params(0, $CFG->sessioncookiepath, $CFG->sessioncookiedomain, $cookiesecure, $CFG->cookiehttponly);
ini_set('session.use_trans_sid', '0');
ini_set('session.use_only_cookies', '1');
ini_set('session.hash_function', '0'); // For now MD5 - we do not have room for sha-1 in sessions table.
ini_set('session.use_strict_mode', '0'); // We have custom protection in session init.
ini_set('session.serialize_handler', 'php'); // We can move to 'php_serialize' after we require PHP 5.5.4 form Moodle.
// Moodle does normal session timeouts, this is for leftovers only.
ini_set('session.gc_probability', 1);
ini_set('session.gc_divisor', 1000);
ini_set('session.gc_maxlifetime', 60*60*24*4);
随后
随着同时访问数量的增加,不再报告网速减慢的情况。(神秘的?)因此,我认为在使用多个 Web 服务器进行 Moodle 网站负载均衡时,最好使用 Redis 而不是数据库。