Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ニジエチューニング2014-12

 ニジエチューニング2014-12

ニジエインフラ

December 27, 2014
Tweet

More Decks by ニジエインフラ

Other Decks in Programming

Transcript

  1. あんただれ • 名前 ◦ ٩( )( )۶とか₍₍⁽⁽(◌ી( ・◡・ )ʃ)とか ◦

    匿名ボードだとインちゃんと呼ばれてる • インフラ・バックエンドのボランティアスタッフです • 2014/03/18にJoin • 最近ニジエオフィスで絵を教えてもらいました ◦ みんなうまくてやばい • 誕生月でした TwitterID作ったんでフォローしてね!@nijieinfra
  2. フィルタ機能リリース • 土曜の夜にDB負荷が上がって気づいた ◦ 遅延も発生 • gwの負荷も増えており新機能のフィルタを疑う • 実はフィルタは全く関係なかった ◦

    DBのレプリケーションはSBRで行っていた ◦ 臨時で動いていたbatchがinsertで 非常に重いselectのサブクエリを発行していた ▪ slave/standbyで重いselectを評価していた • 遅延の原因 • 止めてもらった Master Slave Standby まぁこれはおいておいて・・・
  3. フィルタ機能リリース • とりあえずせっかくの新機能だしもうちょい快適に見れるようにしよう ◦ ついでに実トラフィックも下げよう ◦ 今まで小さめにしていたサイトの静的ファイルのTTLを ユーザの滞在時間を参考に引き上げ ▪ cache-controlで同時にブラウザキャッシュも強化

    ◦ 投稿画像はもともと長い+切り離されているので関係なし • wsのリクエスト数を減らそう ◦ 結構ESIのリクエストが多い ◦ 既にmemoryは使いきってる ◦ じゃぁfileに突っ込もう 実はこのへんから対策してたけど焼け石に水
  4. ニジエのVarnishキャッシュポリシー • nukeするとシステムの速度が落ちる+高速である必要があるもの(pri=1) ◦ css/js ◦ 共通系のESI • 多少遅くても問題ないができれば落としたくないもの(pri=2) ◦

    css/js以外の静的ファイル ◦ 閲覧ページのリコメンドやプロファイルのESI等 • ヒットレートがさほど見込めないが高コストのためキャッシュしたいもの(pri=3) ◦ 自由記入が出来る検索系のESI等 pri=1 pri=3 pri=2 多くのページで使われる その人の絵を見る際に必 ず使われる 自由文検索だしHITすれ ば儲けモンぐらいの感覚
  5. とはいえキャッシュしたいがリソースはない • ESIを行っているgwサーバのリソース状況 ◦ ディスクの使用率は89% ◦ メモリは当然足りない ◦ CPUはwioに既に結構持ってかれてる ▪

    user/sysは大したこと無いけど・・・ ▪ SSDにしたとはいえやはりキャッシュサイズ大きいとね・・・ ▪ varnishplusとかあるけどお金ないよ! • 増やすしか無いかなー・・・
  6. 重複リクエスト問題 • すごく単純な話でランダムアクセスされる 1段目を増やすとwsへ行くリクエストが増大する ◦ 最悪値は単純にgwの台数に比例する ws1 ws2 ws3 gw

    ws1 ws2 gw ws3 gw file=Aをリクエスト ここでキャッシュされるので 3reqされてもwsに行くのは1req file=Aをリクエスト gwが2台のため重複リクエストが発生 どのgwかはDNSによる (インフラからすると実質ランダム) じゃぁ交通整理(=hash)をしてあげれば良い
  7. 重複リクエスト問題 • どのオブジェクトをリクエストしているかという情報をハッシュ化する ◦ 代表的な値はホスト名・URLで場合 ◦ 上記で足りないケースもあって同一URLでPC/SPで異なるオブジェクトを帰す場合は その情報もハッシュに含める必要がある • 1段目はランダムでリクエストされるので、1段目→2段目の際にハッシュに基づいて振り分けをする

    ◦ 考え的には剰余を取ってその余りで振り分けを決める • 障害時も有利 ◦ gwが1台死んでもcacheが保持しているし逆にcacheが死んでもgwが保持している • キャッシュサイズが増える ◦ ハッシュ分散なので同一階層では同オブジェクトを持たない ◦ つまり同一階層のノードのキャッシュサイズを足したサイズになる • デメリットもなくはない ◦ 一番大きいのはサーバを経由することによるlatencyの増大 ◦ 今回は同一サーバに立てるので少ない ws1 ws2 cache ws3 cache hash振り分けで同一 Objectの場合 は同じサーバを経由する gw gw 結果重複リクエストが発生しない
  8. 動的生成のキャッシュ不整合問題 • 例えばとあるページの TTL=60秒とした場合で10秒毎にリクエストが来た場合 ◦ gw1にreq、ws1までreqが行き経由したcache1とgw1にオブジェクトがキャッシュされる ◦ 10秒後にgw2にreq、cache1のキャッシュを使用。 gw2はcache1のオブジェクトをキャッシュする •

    ここで問題なのがgwXがcacheXでの経過時間(Age)をきちんと減算しているかということ ◦ gw2は10秒たったcache1のオブジェクトを使っているので TTL50秒のでなくてはならない • 静的コンテンツの場合はさほど問題にならないが動的コンテンツの場合は問題が起きてくる ◦ リロードしてリクエストする gwが変わるたびに違う結果がかえってくる可能性がある • つまり同一ハッシュのオブジェクトが消えるタイミングは同じでなくてはならない ws1 ws2 cache2 ws3 cache1 gw1 gw2
  9. 多段でのTTLの罠 • TTLを多段環境で同一にした場合に 1段目で場合によってはキャッシュされないことが起こりうる ◦ 1段目がnukeしまくってる ◦ 1段目が障害などでキャッシュが飛んだ • 要は2段目のキャッシュが使われる状況になると

    Age分TTLが減る ◦ ある程度のところで均衡するケースもあるが最悪の場合はほぼ 2段目のキャッシュを使う ◦ ハッシュ分散しているためストレージサイズが 2段目>1段目になるのでなりやすい ◦ ESIを使っている場合だと合成を行う Varnishでキャッシュをなるだけ保持したいので痛い • 解決方法は状況によっていくつかあるが今回の場合は 2段目のTTLを短くしてgraceを長めにした ◦ こんな感じ set beresp.ttl = std.duration(req.http.******,10s) / 2;
  10. 更なるキャッシュへ • 今までVarnishでは「すべてのユーザ」で「同じオブジェクト」を返すものをキャッシュしていた • つまり「ユーザ毎」のキャッシュは行っていなかった • 技術的な問題というより安全側に倒すというのと他に効果があるところがあったため • キャッシュで一番怖いのがハッシュ混じりで、本来ユーザ毎のオブジェクトをすべてのユーザで共有し てしまうと当然ながら他人のデータが見えたり酷いことになる

    • 今回は比較的安全な方法でキャッシュを行うようにした ◦ 「すべてのユーザ」向けのリクエスト時はユーザーを特定できる情報を削除する(前からしてた) ◦ 特定のディレクトリ以下にあるときのみ「ユーザ毎」でのキャッシュを行うようにした ▪ このディレクトリ以下みたいな決めはわかりやすくミスしづらい ◦ 「ユーザ毎」のURLへアクセスがあってユーザを特定出来ない場合はキャッシュしない ◦ などのいくつか対策をやった
  11. プロファイラ投入 • そしてピーク時に重い関数を特定 ◦ mcryptだった! • 要はエントロピーの枯渇 ◦ 物理マシンの場合は対して問題にならないが VMの場合は枯渇しやすい

    ◦ 正直これ失念してたスマンカッタ • jump.phpで使う飛び先URLを暗号化していた ◦ そのためview.php / members.phpでエントロピー枯渇で刺さってしまった • 別に暗号化必要ないロジックだったので使わないように変更 ◦ 他の対策法もあるけど・・
  12. まとめとか今後とか • 構成管理 • ミドルウェアバージョンアップによるパフォーマンスアップ • rate-limitいれてく • gwのspof解消 •

    画像配信のトラフィック増への対策(増設予定) • バグ調査 ◦ 特に投稿関連は深刻に受け止めてます・・・