无法关闭会话警报
前言
早上好/晚上好。
我是Una,是Ancar股份有限公司的Web工程师。
这次我将担任「株式会Ancar ~Advent Calendar 2019~」的第八天任务。
我們的宗旨是提供安心安全的移動體驗。
-
- 中古車の個人間売買をオンラインで行うサービス
全国の中古車からお買い得な車を検索・比較できるサービス
を展開しております。
在本文中,我們將分享在服務運營期間出現的警告處理方法。
总结为3条简要描述
PHP Warning: SessionHandler::read(): Unable to clear session lock recordが3件/日ぐらい発生
どうやらセッションロック周りが怪しい → n度修正 → 鳴り止まないアラート
memcachedからredisを移行させた結果、直った(嬉しい
每天有3个会议提醒。
mackerelというサーバー管理システムから、頻繁にアラートがあがるようになった。
内容はPHP Warning: SessionHandler::read(): Unable to clear session lock record
アラートが増加している上に、SEOにも影響が出ている可能性が高まってきたため、対処に動いた。
那个时候的环境
-
- PHP7.1
-
- memcached3.0.3(elasticache)
- nginx/1.10
这是由于会话锁定吗?
经过向谷歌先生询问警报内容后,发现会话锁定存在可疑情况。
为了防止并发写入,会对会话数据进行锁定,因此在某一时刻只能有一个脚本来处理会话。请参考链接:https://www.php.net/manual/ja/function.session-write-close.php
换言之,我推测在会话已经被锁定的情况下,试图再次向该会话写入会导致错误。
我充满信心地为/etc/php/7.1/fpm/conf.d/25-memcached.ini中的sess_lock设置了与测试服务器相同的时间。告别了警报…(我也曾有过这样的时期).
结果,发生了警报…
从这里开始,我与警报之间的激烈战斗(一个丧尸游戏)开始了。
只依靠摇滚时间还不足够吗?
在之前的戰鬥中,有點過於急躁。下定決心進行牢固地佔領,開始深入研究問題。參考了這些問題,來完善設定。
session.lazy_write = Off;
memcached.sess_lock_wait_min = 100;
memcached.sess_lock_wait_max = 150;
memcached.sess_lock_retries = 30;
memcached.sess_lock_expire = 45;
但是,警报声响起得很欢快。
相反,它稍微增多了一些。
原来如此,难道没有怜悯之心吗…
当我开始深入研究这个问题时,我意识到这个问题其实比我想象的更为严重根深蒂固。
修复的方法有些情况是可以通过之前的修正来解决的,但也有相反的情况。
在PHP7.1以前和memcached搭配使用时,这个问题频繁发生,很可能是由于PHP的版本问题所导致的。
通过多次更改设置的实际经验,我深刻感受到,对付这令人厌恶的警报并不是一个合适的方法。
以下是被认为是有效的选项。
-
- PHP7.2以上
cf: https://github.com/php-memcached-dev/php-memcached/issues/269#issuecomment-519886598
redisへ移行
cf: https://github.com/magento/magento2/issues/5319#issuecomment-265595804
迁移到Redis
考虑到对服务的影响,PHP的更新工作风险与回报不成正比,因此决定放弃。
结果,决定改变路线,转向redis迁移。
同时,恶贯满盈的对手升级为宿敌,呼啸先生成为了一名敌人。
转型的关切
-
- redis移行で問題が本当に解決するのか
打ち手: redisにして解決したソースあり
打ち手: 本番2号機サーバーで確認
移行後にmemcachedに戻れるのか
打ち手: エンドポイントをredisに向けて対応(memcachedの設定を上書き)
打ち手: テスト環境で双方向(memcached ↔ redis)の行ききをし、後戻りできることを確認
redis移行で他に問題が起きないのか
打ち手: テスト環境で確認
打ち手: 本番2号機サーバーで検証
影響範囲が大きいため、打ち手と手順を考えて実行した。
1. テスト環境で実装した後、動作確認。
2. 本番環境の冗長構成のサーバーを間借りして、動作確認。
3. 本番に完全移行。
Redis 迁移的步骤
很遗憾,ElastiCache不支持自动将Memcached从Redis迁移至Redis。
-
- 在Elasticache中创建一个Redis实例
-
- 将Redis端口(6379)添加到ELB的安全组
-
- 在服务器内部执行pecl install redis命令
-
- 在/etc/php/7.1/fpm/php.ini文件中添加extension=redis.so
- 在/etc/php/7.1/fpm/php.ini文件中添加session.save_handler和session.save_path
session.save_handler = redis
session.save_path = ****.cache.amazonaws.com:6379
静默的警报
在解决之前的担忧后,我们进行了Redis的完全迁移,数天过去了。
然而,宿敌仍未现身…
那个每隔数个小时就会冒出来的家伙,居然数天都没有露面…
因此,我要宣布胜利了。
闲话
在监视Alert先生时,我使用Apache Bench(以下简称为ab)对Memcached和Redis进行了负载测试。
由于负载测试的结果会因测试环境而有所不同,因此需要在一些不同的地方进行测试。
此外,据说AWS不再需要事先申请渗透测试。
苹果电脑自带ab,但如果在服务器上使用,则需要安装。
sudo apt install apache2-utils //仅安装ab软件包
进行ab负载测试
Redis比较快…!!
估計/猜測
尽管对memcached和redis施加了类似于自我拒绝服务攻击的负载,但未引发警报。
由此可知,警报不是由于会话增加而产生的。
这不是由于总数的增加而引发的,而是由于无法写入会话。
网站的页面访问量和会话警报的增加看起来在时间上有关联,但根本原因尚未解明。