ISUCON4に参加しました

いやー、楽しかったです!

今回は社内若者1名と参戦しました。使用言語はnode.js。

 

まずは環境を作って一回目の測定。

これで3000程度からスタートしました。

 

・nginxのお約束設定をいくつか入れる

unixドメインソケット化

・pm2でクラスタリング

・セッション管理のキャッシュ化

 

この辺りはサクッとできるだろうから着手してもらいつつ、個人的には

 

csspngの配信をnginx側に持っていく

この辺りは設定だけのお手軽対応だったのでここだけ対処。

 

一通り12時頃に目処がつきベンチをかけてみたものの、劇的な改善は無し。6500位。

またお任せしていたクラスタリングunixドメインソケット化にてこずってるようだったので、このスコアとtopのまわり具合から鑑みてそこはパフォーマンスに大きく影響ないかもしれないと一旦元に戻してもらいました。

 

この後、以下着手してもらいます。

・隙あらば他データもキャッシュ化を狙う

 

その間私の方はクエリを見ながらもうちょっとパフォーマンス上がりそうなところの見直しと、インデックスの設定に着手。インデックスの追加(復号インデックス)をやったり、成功/失敗判定部分のクエリをシンプルにしたり。

しかしここでnode.jsにありがちなエンバグをしてしまい、以上終了…

一旦戻し、6500のスコアで提出。追試でやってみたら8500まではいきましたが…
うーん、何かしっくりこない。これでnodeは遅いと言われるのはちょっと無念なので、個人的に追試は続けたいなと思っています。

 

やはり机上ではなく実際の状況での問題解決は色々と実になっていいなと思いました。

 

今回、勉強になりました。

カーネルの設定変更

mysqlチューニング

外部回線が使えない環境にfluentdをインストールする

・外部回線が使えない=yumが使えない=gitがインストールできない
・特定のsvnからソース持ってくるのはいいよ
という地獄の環境にfluentdを入れた話。

一番いいのは素直に外部回線開けてもらうってことなんですけどね。

 

rubyインストール

・インストール先環境とほぼ同じ環境をVMで構築し、

bundle install --path=./vendor/bundle
bundle package #これでdependencyのあるgemファイルをローカルに持ってくる
bundle exec rake build #

ここまでやったところで階層全部svnにadd,commit。

・インストール先にもっていって

cd fluentd/vendor/cache
gem install *.gem
cd ../../
gem install pkg/*.gem

で何とかいけました。(うろ覚え)

 

fluentdのインストールって軒並みgitクライアントが必要で、事あるごとに「gitが無い!」と怒られる。

関連するgitのインストールでどうしてもgit使用を回避かつ適正っぽい手段が無いので、このような泥臭いことをやりました。

 

いやもっとスマートな方法をrubyな人たちは知ってるはず…

ナントカ.frameworkのアーカイブで悉くシンボリックリンクが使われていて困った件

表題の件、展開したやつをMac側でsvnにcommitしてて、Macで取る分には困らないけど、Win側で取るとシンボリックリンクがファイル化されて上手く使えない。Mac前提で開発してりゃいいんでしょうけど。
で、その対策としてアーカイブをcommitして「使う時はMacで展開してね」って言ってたのに、その事情を全く理解せずに似たような構成のframeworkを展開してcommitしおって。。。
。。。もうこういうのってシンボリックリンク付きで納品されるもんなんだろうねと諦めて、まとめて実体化するようなものが無いかどうか、調べてみました。

tar cfh で固めて展開し直すというのが、お手軽なようです。

    % tar cfh work.tar hoge.framework
    % mkdir work
    % cp work.tar ./work/
    % cd ./work/
    % tar xvf work.tar

で展開したものをcommit。

https://groups.google.com/forum/#!msg/fj.unix/6ES_Aqh4PiY/HvgxnS_wCrIJ

node-log4jsと強制ログローテート

log4jsというよりlog4jの仕様ですが、日を跨いでも新たにログ追記されないと日跨ぎログローテーションは行われない、みたい。
で、ログローテートを期待して前日のログファイルを分析するみたいなバッチを実行してると、開発中とかログファイルが生成されておらずに空ファイルを分析してたりとか。

そういうことがあり取った対策は、appenders設定のオプションにalwaysIncludePattern:trueを追記。

<pre>

            appenders: [

                {

                    type: "dateFile",

                    filename: "hoge.log",

                    pattern: "_yyyyMMdd",

                    category: "hoge",

                    alwaysIncludePattern : true,

                    layout: {

                        type: "pattern",

                        pattern: "%m"

                    }

                }

</pre>

これで前日のログは前日から作られているので、確実に読めるはず。

だけどおそらく強制ログローテートのための機能もあった方がいいだろうとは思う。
node-log4jsに強制ログローテートのアクセサを追加しつつ、cronかnode-cronで呼び出すようにしてwrapp。か。

dhtmlxインストールでハマる

webスプレッドシート使いたいなー位で導入を考えてインストールしようとしたらうまく入らず。

いちばんのキモはここでした。

installer/src/codebase/spreadsheet.php内:

$options['dhx_rel_path'] = $protocol.$_SERVER['SERVER_NAME'].$port.pathinfo($_SERVER['PHP_SELF'], PATHINFO_DIRNAME).'/';

SERVER_NAMEがlocalhostだとブラウザ側のPCにアクセスしようとするし、reverse_proxyしてるとポート番号が違ってxss判定されるし。

結局アドレス手書きしました。

nginx + ngx_mruby + redisでredis制御でサーバを切り替えてみる

サーバを緊急メンテ状態にしたいとき、

・バックエンド最前段の実装で設定を読んで動きを変える

・フロントエンドにメンテ設定送り込んで再起動

色々対応方法を考えたけど、redisに設定を入れ込んでフロントエンド側で 判断して動き変えられたら面白いかなと思ってやってみた。

# -*- coding: utf-8 -*-

worker_processes  1;

daemon off;
master_process off;

events {
    worker_connections  1024;
}

http {
    mruby_init_code '
        userdata = Userdata.new "redis_data_key"
        userdata.redis = Redis.new "127.0.0.1", 6379
    ';

    server {
        listen       7777;
        location / {
          echo "port 7777 test";
        }
    }

    server {
        listen       57777;

        location /mruby {
          mruby_set_code $maint '
              userdata = Userdata.new "redis_data_key"
              redis = userdata.redis
              redis.get "ngx_maint"
          ';
          if ($maint = "TRUE") {
            mruby_set_code $res_maint '
              JSON::stringify({"result"=>"ERR", "time"=>Time.now.to_i})
          ';
            echo $res_maint;
          }
          if ($maint != "TRUE") {
             proxy_pass   http://127.0.0.1:7777;
          }
        }
    }
}

問題はredis getのコストか。要調査。

ngx_mruby組み込みに関する対応…

submoduleの辺りではまる…

% git clone https://github.com/agentzh/echo-nginx-module.git

% git clone git://github.com/matsumoto-r/ngx_mruby.git

% cd ngx_mruby/

% git submodule init

% git submodule update

% git submodule foreach 'git pull origin master'

% ./configure --with-ngx-src-root=/home/takeswim/nginx-1.5.0 --with-ngx-config-opt="--add-module=/home/takeswim/echo-nginx-module --prefix=/home/takeswim/nginx150"

% make

% make install