月別アーカイブ: 2015年5月

Webサイト障害復旧体験メモ

恥ずかしながら障害を起こしてしまいました。
久々にデスマにあったときのような気持ちになったので思い出として残そうと思います。

1日目
障害→応急処置→根本対応復旧→障害早期検知ツール構築→
睡眠→3時間で起こされる→
2日目
障害→応急処置→根本対応復旧→睡眠6時間→
3日目
障害早期検知ツール構築

2日目のプレッシャ内での18時間連続作業は前日作業&睡眠3時間もあってかなり辛かった。
胃が圧迫されてるような感じ。

*検知
webサイトのstatus200の監視をしてたcronがメールを届けてくる
確認するとサイト全体が重い状態だった。
確認するとsessionとデータキャッシュで使っているKyototycoonが壊れていることが判明。
急いで治すことに

*やったこと
**Kyototycoonについて
まずはMemcachedに切り替え応急処置。
Kyototycoonのデータ元の以下ファイルの復旧を試みるがどうしてもOpenできなかった。
/var/ktserver/casket.kch
やむなくデータを捨てて別のサーバに切り替えた。
KyototycoonにはSessionデータなども入ってたため
別のサーバに切り替えてしまうとSessionが切れてしまう恐れがあった。
ゲストさんのコンテンツお気に入りリスト・会員のログインフラグが消えてしまうが、
致し方ないと判断。

**prcessがやばいことに
cacheは直したがしばらくするとまた壊れる現象が発生、追加調査したところ
processがやばいことになってた。

$ ps ax | grep php
2737 ? S 0:00 php /var/www/project1/application/batch/ArticleUrlImgGetBat.php
22991 ? Ss 0:00 php /var/www/project1/application/batch/TweetMatomePost.php
22993 ? Ss 0:00 php /var/www/project1/application/batch/TweetNewPost.php
22996 ? Ss 0:00 php /var/www/project1/application/batch/TweetPost.php
22997 ? S 0:00 php /var/www/project1/application/batch/ArticleUrlImgGetBat.php
24588 ? Ss 0:00 php /var/www/project1/application/batch/TweetMatomePost.php
26556 ? Ss 0:00 php /var/www/project1/application/batch/ArticleLogCntBat.php
26557 ? Ss 0:00 php /var/www/project1/application/batch/TweetNewPost.php
26558 ? Ss 0:00 php /var/www/project1/application/batch/TweetPost.php
26559 ? Ss 0:00 /bin/sh -c php /var/www/project1/application/batch/MakeSitemapNews.php > /tmp/makesitemap_news.log
26560 ? Ss 0:00 php /var/www/project1/application/batch/ArticleLogSaveBat.php
26562 ? Ss 0:00 php /var/www/project1/application/batch/TweetMatomePost.php
26563 ? Ss 0:00 php /var/www/project1/application/batch/ArticleLogCntBat.php
26565 ? S 0:00 php /var/www/project1/application/batch/ArticleUrlImgGetBat.php
26566 ? S 0:00 php /var/www/project1/application/batch/MakeSitemapNews.php
29723 ? Ss 0:00 php /var/www/project1/application/batch/ArticleUrlImgDlBat.php
29724 ? Ss 0:00 php /var/www/project1/application/batch/ArticleLogSaveBat.php
29725 ? Ss 0:00 php /var/www/project1/application/batch/TweetNewPost.php
29726 ? Ss 0:00 php /var/www/project1/application/batch/TweetMatomePost.php
29729 ? Ss 0:00 php /var/www/project1/application/batch/TweetPost.php
29730 ? S 0:00 php /var/www/project1/application/batch/ArticleUrlImgGetBat.php

Mroongaのtableのupdate処理がprcesssを維持してた所為でこのような状態に
なっていることが判明。
と同時に、Mysqlのconnectionが異常に発生しmax_connectionと同数となってた。

**Mroongaについて
障害tableを以下で複製しデータをそのまま突っ込むことで一旦復旧したが、
show create table articles;
insert into articles_new select * from articles;

数時間後に再度障害発生。どうもレコード数に起因するようだったので、
テーブルを分割することにした。
Daoを使ってるので、テーブル分割部分を吸収するMapperを作成して
アプリ側で分割させた。
チューニングやカラム数にもよるのかもしれないが、1テーブル30万レコードを超えると起こってた。

**MySQLのmax_connection
MySQLへの接続数が増大しtoo many connectionsが発生していたため、接続数up設定をしたが、
スペルミスで、再起動失敗し以下エラーが出てしまった。
しばらく気付かずDBが壊れてしまったかと思ったが、一つ一つ確認して復旧。アホでした。
“mysqld は停止していますがサブシステムがロックされています”

接続数は2048に変更
# /etc/my.cnf
max_connections=2048
wait_timeout=3600

*復旧
**mroongaでバックアップリストアを繰り返したところDb自体が壊れる
mysql> select * from article_1 limit 1;
ERROR 1016 (HY000): mroonga: failed to open table:
アプリサーバ側にバックアップDBをdumpしてあったのでサーバを相互に入れ替えることに。
色々やってる過程で、無理にMySQLを強制終了してしまった所為かなと思う。
DBサーバと同じぐらいアプリサーバを構築して、NFSで元のデータファイルを参照させるのが面倒だった。

**Session(ゲストユーザ数)が爆増
システム仕様として、新規Session時にユーザレコードを作成する仕様なので、
kyototycoonの破壊で、
同じSessionでも別セッションとして扱われてしまって、
ユーザTableにレコードが追加されまくってた。
なので一見さんのレコードを検出しざっくり削除。
27日が少ないのは深夜に出力したため

mysql> select count(*) from users where updated like ‘2015-05-27%';
+———-+
| count(*) |
+———-+
| 69717 |
+———-+

mysql> select count(*) from users where updated like ‘2015-05-26%';
+———-+
| count(*) |
+———-+
| 299143 |
+———-+

mysql> select count(*) from users where updated like ‘2015-05-25%';
+———-+
| count(*) |
+———-+
| 75671 |

*障害結果
キャッシュにKyototycoonを使ってるが、これがまず初めに壊れて、
負荷増で、連鎖的にMroongaのtableのupdate処理が壊れてしまった。

kyototycoon
/usr/local/bin/ktremotemgr: DB::open failed: : 6: network error: connection failed

mroongaで使用してる検索対象じゃないところの更新でプロセスを維持したままフリーズしてた。
update articles set tweet_flag = 1 where id = id;

**対応予定&作成予定検知ツール
プロセスの件数を監視してメールを飛ばす
cactiでmax_connectionの数値をみれるように
本番用の検索メソッドは複雑なので、応急処置時に手軽に使えそうな簡易検索メソッドを用意。
新たにnfsを導入したのでnfsが切れないか監視
mroongaのtableのupdateを監視できるツール作成

**analytics
ざっくりいっちゃってます。遺憾ですな
スクリーンショット 2015-06-10 3.55.49

*今後
現状cactiだけで管理してるので、kibana,zabbixなど監視ツールを色々拡充せねば。
Sessinoのバックアップは大事です。
DBのバックアップはもっと大事です。
レプリケーションなど色々やっていきたい。
awsにするといろんなことが改善できるんだろうけど、
リザーブで使ってもサーバコストが5倍にになるのが・・・。
もっと安くしてほしい。

GTmetrixを使ってパフォーマンスチューニングをしてみた

公式サイト:http://gtmetrix.com/

今回は前回PageSpeedで対策したサイトとはまた別の
最近作ったサイト(apache+php)で対策をしてみました

初期状態で56でした。
スクリーンショット 2015-05-23 15.57.31

Specify image dimensions
画像のwidthとheightの属性を指定で59になりました。
スクリーンショット 2015-05-23 16.27.17

keep-aliveを追加することで83になりました。
Html/パフォーマンスチューニング/その他
スクリーンショット 2015-05-23 16.29.34

速くなった体感はあまりないけど、しばらくms単位のレスポンスタイムを取ってみる。

PageSpeedサイトでパフォーマンスチューニングをしてみた。

2015/8/3で閉鎖予定のPageSpeedでパフォーマンスチューニングをしてみました。
参考
http://jp.techcrunch.com/2015/05/07/20150506google-shuts-down-pagespeed-service-for-accelerating-websites/

PageSpeedサイト
https://developers.google.com/speed/pagespeed/insights/

nginxとphp-fpmで最近作ったサイトを改良みました。

とりあえず初期状態。パソコンは64でした。
スクリーンショット 2015-05-21 5.15.56

静的ファイル圧縮対策後(DEFLATE,gzip)
Linux/nginxインストール/パフォーマンス向上
Html/パフォーマンスチューニング/画像圧縮ツール
49まで上昇。
スクリーンショット 2015-05-21 5.24.21

ブラウザのキャッシュ対策(max-age,expires)
スクロールせずに見えるコンテンツのレンダリングをブロックしているJavaScriptを排除するために
scriptタグにasyncを追加した結果
51で微上昇。
スクリーンショット 2015-05-21 6.14.41

今更だけどga.jsを非同期バージョンのanalytics.jsに修正
これは効果高かった。57に上昇
スクリーンショット 2015-05-21 7.48.26

外部画像をimgタグで貼り付けてたのをやめたら
76に上昇。
外部画像を不用意に使うのはいかんかったです。
パソコンは84でした。
スクリーンショット 2015-05-21 10.27.01

あとは広告用のcssやjsだったりbootstrap.cssだったりするのでこれ以上は難しそう。

画像のexpiresが有効になったせいか?スマホでの閲覧が、結構サクサクになりました。