Archive for the ‘linux’ Category

    はてなブックマーク - ISUCON3の本選にFulabで参加してきました
    このエントリーをはてなブックマークに追加

    Fusic 平田です。
    予選を繰り上げ当選できたので、本選に参加してきました。

    一緒に参加したヌーラボ染田さんのblog記事ISUCON3本選関連エントリまとめあたりも合わせてご覧ください。
    我々が何をやったかの詳しいところは染田さんの記事に書いてあるので、僕の視点から見たことを時系列で並べてみます。

    前日の作戦会議

    「今日は飲んでも飲みすぎない」が最初の確認事項。
    あとは前回の反省で、「事前の検討を長めに」「入れ替えが容易ならやってみて、だめだったら戻すくらいで」といったところを確認。
    とは言え後は複数台構成だろうってくらいの予想しかできなかったので、「立ち合い強く、あとは流れで」みたいな話になりました。
    「地方参戦の強みをおやつで発揮する」というのも協議結果で、これについては後述。

    で、前日の準備にopsletを活用。
    弊社の眼鏡軍曹が作ったもので、ISUCONに合わせて機能追加までやってくれたものです。
    機能としては、curlで標準出力やらファイルの中身やらをぼんぼんサーバに飛ばすもので、



    こんな感じで見れるってやつです。
    手元で試したのとかを送っておいて、あとは当日活用しようってことで大いに使わせていただきました。

    当日朝

    遅れることなく無事に到着。
    写真をいろいろ撮ったりしつつ。


    ~開始前

    PCの準備をしたり、会場を見回ったり、おやつの確認をしたり。
    おやつは生八つ橋とめんべいを用意。


    事前説明など~競技開始前

    既にwktk感が止まらない事態だったのですが、説明が始まってさらにテンションUP。
    で、OPムービーに「画像投稿」と出た瞬間から「これはやばい」感ががが。

    開始~12:00ごろ

    前日の作戦会議どおり、まずは中身を確認。
    のち以下の方針(染田さんの記事からコピペ)。

    ・予選同様フロントは varnish に入れ替えてキャッシュなるべくきかせよう
    ・アプリの外部プロセスでの変換処理がツラいので Imlib2 (or Imager) に置き換えよう
    ・MySQL の timeline 周りの臭そうな所をひとまずつぶそう
    ・いきなり複数台展開するとボトルネック分かりづらくなるから、まずは一台でチューニングして各サーバへの展開は後からにしよう

    なんとなく「上3つを片付けて、ある程度スコアが伸びるのが15時くらいかなー」「それからボトルネックに合わせて展開しつつ更にいろいろ手を出して17時過ぎて、あとは再起動確認しつつ最終調整かなー」とか考えていたんですが、完全に甘い目論みでした。
    自分は前回同様、varnishでキャッシュして捌くところが担当。

    ~15:00

    とりあえず、varnishに差し替える→fail!fail!fail!
    最低限の設定(静的ファイルだけキャッシュ、あとはpass)しか入れてないはずだけどなー。。。と思いつつ、ヘッダの状況とか確認して合わせたりしつつ。
    timelineが30秒詰まってまともに動かない。。。のでアプリ側を見たらsleepとか入ってて、これで眠ってるんだろうなーということで外して再チェック。
    でもfail!fail!fail!で、こりゃvarnishのほうちゃんと見直そうってことで、サーバ2のほうで別途確認を進めることに。
    この時サーバ2を初めて覗くことになったのですが、
    > 残りの4台は社長が追加契約した直後の状態なので、まっさらな状態です
    てなレギュレーションにガクブルしてたらperlとかmysqlとかは入ってたので、思ったより社長は悪人じゃなかった!と一人ほっとした次第です。

    で、そこからいろいろ設定。

    ・ヘッダをもう少し調整してばっちり合わせる
    ・アプリ側でno-cacheヘッダ付加してたなーと思い、念のためつけてみたり

    とかやっているうちにfailは出ないことを確認して、よし画像をーと進めたのですが

    ・ログインユーザごとにキャッシュ分けなきゃーなので、cookieの値を見て、ユーザのapp_keyごとにキャッシュを分ける
    ・/icon/と/image/をキャッシュさせた時のfailが回避できない
    ・変な状態のキャッシュが残りにくいよう(failしないように)頻繁に消すようにして整合性を重視
    → したつもりでもfailするしそもそもスコアが全然伸びない

    と言ったところで詰まって、どうしたもんかなーとか思っている間に15:00。
    アプリ側は、画像変換処理を入れ替えたらどうもfailするとか、timeline部分のクエリを改善すべくfollow情報をmemcachedに放り込むとか、手は打つものの大きくスコアを伸ばすに至らず、memcachedで画像をキャッシュさせる戦略に切り替えつつ、といったところ。
    要はスコアを伸ばせてない状態のままで、「もう15時かー!」と3人で悲鳴あげてました。

    ~16:45くらい

    とは言えこのまま手をこまねいているわけにもいかないので、vmod-memcachedとか持ってきて策を練るも、うまいことキャッシュを操作しようとなると

    ・そのリクエスト+Cookieの値に合わせた値をmemcachedに保持しておく必要がある
    ・となるとアプリにさらなる改変が必要
    ・画像キャッシュする部分も影響受けそうで、改変コストがだいぶ大きい

    といったところで手を付けられない、ぐぬぬ、と。
    そうこうしている間にアプリ側の改修が進み、画像のキャッシュがヒットしだして、スコアが伸びて4000くらいに到達。
    この辺で山本さんに現状の問題をざーっと伝えたところ、「なんかiconは何も考えずにキャッシュさせるだけでよさげ」といった話になり、あーそれならすぐできるな、とさっくり設定して、ついでにサーバ1(アプリ改修を反映しているサーバ)をバックエンドにしてベンチを走らせてみる。



    ( ゚д゚)
    (つд⊂)ゴシゴシ
    (;゚ Д゚) …?!
    思わずガッツポーズしてしまいました。

    ~17:30くらい

    といったところでworkloadを変えたりいろいろ実験してサーバ構成を見直す。
    個別検証だったり、アプリ改修の最中でサーバを分けていたりの経緯で
    サーバ1 -> APサーバ
    サーバ2 -> キャッシュサーバ
    サーバ3 -> 空き
    サーバ4 -> memcachedサーバ
    サーバ5 -> DBサーバ
    といった役割構成。
    DBは余裕綽々だったので、AP/キャッシュサーバを増やす方向で検証を進める方向にシフト。
    サーバ1とサーバ2をAP+キャッシュ(varnish)の同一構成にしてベンチ→fail!fail!fail!とうまくいかず、調査と対応を進める。
    とかやってるうちにLINE選抜が40000超えのスコアを出して、会場が「うわー」「うげー」「うひー」みたいな声で溢れかえっていました。
    僕は「うわー」って叫んだ一人です。
    引き続きvarnishだけ増やす設定進めようとするも、確実に終わらせるには時間的に厳しいので断念。

    ~18:00

    残り時間も少なく、これ以上の手入れは厳しいと判断して、サーバ再起動をしての動作チェックに移行。
    ここはもう3人で声掛け確認をしつつ、「サーバ2再起動しましたー」「サーバ5再起動OKー」みたいな感じでひたすらに確認。
    全ての懸念が取り除かれて最終ベンチを走らせたところでタイムアップとなり、最終ベンチのスコアは11000くらい。ただしfail(時間切れのためと思われます)。

    結果発表待ち中

    終わってみるといろいろ思いつくもので
    ・そういやimagemagickのパラメータ全然変えてなかった
    ・横展開に舵を切るのが遅かったかしら
    ・iconだけvarnishでキャッシュさせる手はもっと早く気付けたなあ
    ・おやつ全然手を付けてなかった→懇親会で配ろう
    といったあたりがすらすらと出てくるんだから困ったもんです。
    また、この後に備えてウコンを仕入れて投入。

    結果発表

    ご存じのとおりLINE選抜が優勝し、#茶番のハッシュタグが乱舞。



    その後、出題者の藤原組長の講評、そして優勝以外の結果一覧。
    計測前のスコアでは7-8位くらいで、「failしなきゃ真ん中よりは上かなー」くらいに考えていたのですが、



    3位!!ということで、予選繰り上げ通過から考えるとかなりのジャンプアップ。
    100万円とダンボーは残念ながら獲得できませんでしたが、きちんと計測完走して上位に入れたのでほっとしました。

    懇親会

    戦いきった後なので、心地よい疲れとともに飲みまくりました。
    ISUCONの話だったりそうでない話だったり、某社某会長の物まねを見せていただいたり、楽しい時間が過ごせました。
    あと、モリスコールを生で聞けたのでよかったです。

    反省とかいろいろ

    予選の時は、何か手を打つ→スコアが上がる、のループをうまく続けられたのですが、今回はなかなかスコアが上がらずに苦戦しました。
    その中で視野が狭くなっていった部分もあり、この辺はまだまだ精進しなければならないなと感じました。
    また、優勝したチームやベンチで高スコア出していたチームは、早い段階で複数台構成を意識して進めていた点が大きく違ったなと。
    当初のもくろみ通りに早めに複数台に展開できていればまた違ったのでしょうが、この辺は自分の実力が足りなくて次の策を打つまでに時間がかかりすぎたなーと反省しきりです。
    一方で、終盤を再起動検証につぎ込んで結果を残せたのは、安定スキーな自分としては満足のいくところです。

    その後

    お祝いということで、社内の方々からいろいろいただきました。



    ありがとうございますありがとうございますどうしてこうなった。

    最後に

    以前から参加したいと思っていてようやく参加できて、ありがたいことに本選まで参加させていただきました。
    当日もずっと言っていたのですが、1日中ひたすら楽しかったですね。
    楽しいイベントを提供していただいたISUCON運営チームの皆様、本当にありがとうございました。
    また、本選に快く送り出していただいた弊社の皆様、ありがとうございました。
    そして、一緒に戦っていただいたヌーラボの山本さん&染田さん、本当に本当にありがとうございました。
    また次回も参加したいとか言い出すと思いますが、その際は皆様よろしくお願いいたします。ぺこりぺこり。

      はてなブックマーク - ISUCON3のオンライン予選にFulabで参加してきました
      このエントリーをはてなブックマークに追加

      Fusic 平田です。
      あーだこーだ言ったりやったりしている間に当日を迎えてしまいましたので、予選に参加してきました。
      今回はヌーラボさんのお二人(@dragon3さん, @tksmdさん)と組ませてもらい、チーム名はFusic x nulab = Fulabに決定。

      ちなみに最終スコアは

      で、もう一歩のところだったのかなー1 と思われます。
      ※ 2013/10/09 20:00追記: 繰り上がり当選してました!

      だいたい時系列にやったことを並べると、

      前々日にSkypeでざっくり作戦会議

      ・まあPerlかなーとかvarnish使うかなーとか
      ・台風で予定狂いそうだったので3人で祈る

      当日朝

      ・無事3人揃って参加可能に
      ・ヌーラボさんにお邪魔して、環境準備とか
       ・TV会議システムで京都のtksmdさんとやり取り
        ・超スムーズでうらやましくなる
       ・backlogのプロジェクト立てたり、公開鍵渡したり
       ・他にチャットはtypetalk、メモはEtherPad
        ・とか書いてたら普通にヌーラボさんのプロダクツ紹介になっていたことに自分で驚いた

      開始

      ・とりあえず動かして初期スコア確認(Perlで800くらいだった)
      ・皆でいろいろ覗く
      ・とりあえずis_private邪魔だなーとかmy.cnfないなーとかそういう話

      11:00ごろ作戦会議

      ・ちゃっちゃとvarnish立てよう
      ・DBのインデックスとかクエリとか見直さないとね
      ・なんとなくフロント/アプリ/DBで役割分担

      ~13:00くらいまで

      ・さくっと2000くらいまでは行って、TOP5くらいには入っていそうなのを確認
      ・その後も見直しつつベンチ回す
      ・やっぱMySQL重いしCPU食ってるのがなかなか落ち着かない
      ・このへんでmarkdownの生成周りをどうにか対処しないとなーという話に
      ・is_private=0が邪魔なので、memos_publicテーブル作って、SQLのWHERE句に出てこないよう改修開始

      ~16:00くらいまで

      ・じりじり順位落としてツライ
      ・memcacheに乗せられるものを徐々に乗せる方向に
      ・並行してmarkdownの処理もキャッシュ作って乗せたりする方向に対応
      ・workloadを上げてみて、5くらいで一番スコア出たのを確認
      ・いくつか罠を見つけたので、引き続き罠探したり
      ・varnish側でgzip切ったのも多分この辺

      ~18:00

      ・MySQLの設定変えたらdiskfullになるとか
      ・markdown周りのキャッシュが効きだしてスコアがまた伸び始める
      ・他もいろいろmemcacheに乗せまくる
      ・どうもvarnishのキャッシュが乗せきれてないのを対処再開するも時間切れ

      といった感じでした。
      他のチームのやったことを見る限り、アプローチはだいたい間違ってなかったのかなーと。
      いくつか効果出そうなところで手をつけきれなかったりとか、フロントでうまくさばけていれば2 もっとスコア伸ばせたなーとか、その辺でいくらかずつ足りなかったようです。

      開始から終了まで、ずっと楽しかったです。
      ぜひ次回があればまた参加したいですね。
      主催の皆様、本当にありがとうございました。ぺこりぺこり。

      1. 暫定の予選突破ラインが8700くらいだったようで、本当にあと一歩でした。。。 []
      2. varnishでスコア激伸びした!てのも見かけるので、ブレークスルー起こせなかったのが心残り []
        はてなブックマーク - Apacheのmod_cacheを利用して静的コンテンツをキャッシュさせた話(追記あり)
        このエントリーをはてなブックマークに追加

        Fusic 平田です。

        前のエントリの延長のようなそうでもない話です。

        あらすじ

        ある日「サーバがレスポンスをろくに返さない」と連絡があり、すわ障害発生かとおもむろにsshクライアントを立ち上げ、接続。
        この時点でよくあるのは

        • サーバがハングしていたりして接続できない
        • なんとか繋がるもののすごく重い・ロードアベレージが鬼のように高い
        • その他障害などでエラーが発生しているとかディスク障害が起きてるとかblog書いてる場合じゃない事態とか

        といったあたり(書いてる場合じゃない事態はそうそう起きません)なのですが。
        普通にssh接続できるし、dstatで眺めてもCPUなりメモリなりで刺さってるわけでもなし。
        はて。。。と思いつつ

        # tailf /var/log/httpd/access_log

        とかやってみると、滝のように流れまくるアクセスログ。

        「どうしてこうなった」はさておき、とにかく対応せないかんという話で。
        前のエントリの流れを汲むなら「よしvarnishでもさっくり突っ込んでキャッシュでぶん回して対処」といきたい1 んですが。

        で、アクセス状況をざっくり計測した感じだと

        • アクセスは特定の静的ページ(http://toaru-site.com/miwaku_no/contents/)に集中している
        • 特定の静的ページがいわゆるランディングページなので、何かしら宣伝なりを打った結果の一時的なアクセス集中だろう2

        といったあたりから、Apacheのmod_cacheで一時的に凌げる範疇だろうということで、さっくり設定を入れて対応してみました。

        1. キャッシュ設定を追加

        ※ OSはCentOS6で、Apacheは2.2.15です。
        /etc/httpd/conf.d/cache.confとして以下のファイルを作成。

        CacheRoot /tmp/cache
        CacheEnable disk /miwaku_no/contents
        CacheDirLevels 5
        CacheDirLength 3
        CacheIgnoreCacheControl On
        CacheIgnoreNoLastMod On

        のちapache再起動して、/tmp/cache以下にキャッシュファイルが作成されることと、対象ページのレスポンスが速くなることを確認。

        2. 他のパラメータを調整

        これでおおよそ大丈夫かなと思ったのですが、他の設定値を若干絞っていたりして、まだ動作がよろしくない。
        ということで、

        • Maxclientなどの値を、dstatで具合を見つつ増やす
        • KeepAliveをOff→Onに変更

        といったあたりを調整。

        3. キャッシュ設定を少し追加

        画像やCSSもキャッシュさせて、より負荷を下げるように調整。

        これでおおよそ安定して捌けるようになったので、この設定のまま1日様子見。
        のちアクセス具合も通常に戻ったので、設定を戻して事なきを得ました。

        てことで

        現状の構成をなるべく変えることなく、と言う観点で対応できたのは良かったのかなと。
        アクセスが集中しやすい箇所をあらかじめキャッシュさせるようにするなど、事前に戦略を練るべきではありましたが。。。

        追記

        cakephperさんからツッコミいただきました。
        ※ 回答としては、originサーバでの話です。

        言われてみれば若干腑に落ちないところもあるなー、ってことで実験。

        測ってみた

        手元のApache環境で、Cache設定あり/なしで、

        $ http_load -parallel 100 -seconds 10 ./miwaku_no_urllist

        てな感じで、100並列/10秒実行。
        実際にアクセス食らったページとおおよそ同様のページ/画像/他(計53リクエスト)で実験。

        ○ cacheなし

        $ http_load -parallel 100 -seconds 10 ./urllist 
        12186 fetches, 100 max parallel, 2.43872e+08 bytes, in 10 seconds
        20012.4 mean bytes/connection
        1218.6 fetches/sec, 2.43872e+07 bytes/sec
        msecs/connect: 0.119898 mean, 1.853 max, 0.046 min
        msecs/first-response: 81.5065 mean, 925.366 max, 1.622 min
        HTTP response codes:
          code 200 -- 12186

        ○ cacheあり

        $ http_load -parallel 100 -seconds 10 ./miwaku_no_urllist 
        15541 fetches, 100 max parallel, 3.18031e+08 bytes, in 10 seconds
        20464 mean bytes/connection
        1554.1 fetches/sec, 3.18031e+07 bytes/sec
        msecs/connect: 0.119447 mean, 6.493 max, 0.04 min
        msecs/first-response: 63.8984 mean, 988.844 max, 2.231 min
        HTTP response codes:
          code 200 -- 15541

        どちらも10回ほど実験してみて、結果としては

        • cacheなし:約11000~14000リクエスト
        • cacheあり:約14000~17000リクエスト

        てことで、平均すると25~30%程度のパフォーマンス向上が見られます。
        KeepAliveをOn/OffしたりMaxClientあたりをいじってみたりもしましたが、おおよそ同じような向上具合。
        静的コンテンツに対しても、一定の効果はあるようです。

        ついでなので

        varnish突っ込んで

        $ http_load -parallel 100 -seconds 10 ./miwaku_no_urllist_via_varnish

        というのもやってみました。

        ○ varnish

        $ http_load -parallel 100 -seconds 10 ./miwaku_no_urllist_via_varnish 
        65393 fetches, 100 max parallel, 1.35126e+09 bytes, in 10 seconds
        20663.7 mean bytes/connection
        6539.29 fetches/sec, 1.35126e+08 bytes/sec
        msecs/connect: 0.154726 mean, 6.537 max, 0.033 min
        msecs/first-response: 14.9211 mean, 44.383 max, 0.688 min
        HTTP response codes:
          code 200 -- 65393

        はやい。(小並感)

        1. 実際、その選択肢もなくはなかった。 []
        2. 対応する傍らで関係各位に確認した結果、やはりそういった類のアクセス集中だったようで。 []