<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
		xmlns:xhtml="http://www.w3.org/1999/xhtml"
>

<channel>
	<title>cloudrop</title>
	<atom:link href="http://cloudrop.jp/feed" rel="self" type="application/rss+xml" />
	<link>http://cloudrop.jp</link>
	<description>クラウド使ったインターネットサービスの技術支援、ウェブサービスの開発</description>
	<lastBuildDate>Mon, 26 Dec 2011 13:27:30 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.4.1</generator>
<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://cloudrop.jp/feed" />
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/><atom:link rel="hub" href="http://superfeedr.com/hubbub"/>		<item>
		<title>簡単！リアルタイム画像変換をNginxだけで行う方法</title>
		<link>http://cloudrop.jp/labs/nginx_image_filter?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=nginx_image_filter</link>
		<comments>http://cloudrop.jp/labs/nginx_image_filter#comments</comments>
		<pubDate>Fri, 09 Dec 2011 01:00:57 +0000</pubDate>
		<dc:creator>sekine</dc:creator>
				<category><![CDATA[サーバー]]></category>
		<category><![CDATA[勉強会]]></category>
		<category><![CDATA[実験・研究]]></category>
		<category><![CDATA[nginx]]></category>

		<guid isPermaLink="false">http://cloudrop.jp/?p=1352</guid>
		<description><![CDATA[AWS S3に置かれたマスターとなる画像ファイルを取得し、与えられたパラメータでリアルタイム（オンザフライ）にリサイズ・トリミングを行うリアルタイム画像変換をNginxだけで実現する方法を実験してみました。]]></description>
			<content:encoded><![CDATA[<style><!--
#log20111205 { border: 1px solid #999; margin-bottom:1em; border-collapse: collapse;}
#log20111205 th { border: 1px solid #999; padding: 2px 5px; line-height: 1.2em; }
#log20111205 td { text-align:right; border: 1px solid #999; padding: 2px 5px;}
--></style>
<p><img src="http://cloudrop.jp/wp-content/uploads/2011/12/nginx_if_eye.jpg" alt="image filterイメージ" title="image filterイメージ" width="272" height="172" class="alignleft size-full wp-image-1469" />先週金曜日（12/2）にクックパッドインフラ勉強会に参加しまして、そこで同社の成田さんから「今日からできるApacheモジュール開発と運用」という発表がありました。<br />
リアルタイム画像変換モジュールの「TOFU」を開発するに至った経緯と、Apacheモジュール開発についてのお話でした。</p>
<p>TOFUは、S3に置かれたマスターとなる画像ファイルを取得し、<strong>与えられたパラメータでリアルタイム（オンザフライ）にリサイズ・トリミングを行うモジュール</strong>（mod_tofu）です。</p>
<ul>
<li><a href="http://www.slideshare.net/mirakui/ss-8150494">料理を楽しくする画像配信システム</a></li>
</ul>
<p>実際は、モジュールによる画像取得・変換をベースに、キャッシュや配信までも含めた一連の画像配信システムと言えそうです。</p>
<p>この仕組みをNginxを使って実装できないかと考えて、リアルタイム変換の仕組みを<strong>Nginxだけで実現する</strong>方法を実験してみました。<br />
<br clear="all" style="clear:both;"/><br />
<!--TOC--></p>
<h3>準備するもの</h3>
<h4>HttpImageFilterModule</h3>
<p>このモジュールはパッケージに同梱されているオプションモジュールの一つで、JPEG、GIF、PNGを変換するフィルターを提供します。<br />
有効にするには、ビルド時にパラメータを指定する必要があります。</p>
<pre class="terminal">./configure --with-http_image_filter_module</pre>
<blockquote><p>
ビルドし直したnginxの入れ替えを行う場合は、こちらを参考にしてください。</p>
<ul>
<li><a href="http://cloudrop.jp/labs/nginx_upgrade" >リクエストを落とさずにnginxをアップグレードする方法とその検証</a></li>
</ul>
</blockquote>
<p>また、ビルドにはlibgdが必要なので<strong>GDライブラリを別途インストールしておく必要があります</strong>。</p>
<h4>最も簡単な例</h4>
<p>/imagesディレクトリにあるjpgファイルを全て150*150のサムネイルに変換したい場合は、以下の設定を書くだけです。</p>
<pre class="terminal">
location ~ /images/.*\.jpg$ {
   image_filter  crop  150  150;
}
</pre>
<p>このままだと元サイズのファイルにアクセスできなかったり、エラー制御がしにくいのですが、このモジュールがいかに簡単に使えるかがわかると思います。</p>
<h3>ローカルファイルで実験</h3>
<p>前述の最も簡単な例を発展させて、外部からのパラメータに従って、まずはローカルディスクにある画像に対してリアルタイム変換をしてみます。</p>
<h4>対象とするファイル</h4>
<ul>
<li><a href="http://nginx.labs.cloudrop.jp/images/momiji.jpg" target="_blank">momiji.jpg</a></li>
<li>JPEGファイル</li>
<li>1024&#215;683 ピクセル</li>
<li>274,661 バイト</li>
</ul>
<h4>外部からのパラメータ</h4>
<ul>
<li>width（幅）</li>
<li>height（高さ）</li>
<li>type（リサイズの方法）
<ul>
<li>resize（縦横比を変えずにサイズ変換）</li>
<li>crop（サイズ変換後に指定されたサイズに切り取る）</li>
</ul>
</li>
<li>quality（JPEGの画質≒圧縮率）</li>
</ul>
<h4>要件</h4>
<p>/imagesディレクトリにあるJPEGファイル（*.jpg）にパラメータを付けてアクセスをした時、パラメータに従って変換された画像を返す。</p>
<h4>結果</h4>
<p>以下のように、パラメータを変えるだけで欲しい画像サイズに変換されます。</p>
<p><img src="http://nginx.labs.cloudrop.jp/images/momiji.jpg?width=150&#038;height=150&#038;type=resize" width="150" height="100" /><br />
/images/momiji.jpg?width=150&#038;height=150&#038;type=resize</p>
<p><img src="http://nginx.labs.cloudrop.jp/images/momiji.jpg?width=200&#038;height=200&#038;type=crop" width="200" height="200" /><br />
/images/momiji.jpg?width=200&#038;height=200&#038;type=crop</p>
<p><img src="http://nginx.labs.cloudrop.jp/images/momiji.jpg?width=400&#038;height=100&#038;type=crop&#038;quality=5" width="400" height="100" /><br />
/images/momiji.jpg?width=400&#038;height=100&#038;type=crop&#038;quality=5</p>
<p>こちらのリンク先でパラメータをいろいろ変更してテストができます。お試し下さい。<br />
<a href="http://nginx.labs.cloudrop.jp/images/momiji.jpg?width=150&#038;height=150" target="_blank">http://nginx.labs.cloudrop.jp/images/momiji.jpg?width=150&#038;height=150</a></p>
<h4>設定方法</h4>
<p><a href="http://cloudrop.jp/wp-content/uploads/2011/12/nginx_if_static.png"><img src="http://cloudrop.jp/wp-content/uploads/2011/12/nginx_if_static.png" alt="処理の流れ（ローカル）" title="処理の流れ（ローカル）" width="220" height="200" class="alignleft size-full wp-image-1378" /></a>
<ol style="margin-left:250px;">
<li>/images でパラメータの有無をチェックします。なければ通常の画像を返すようにしています。（何もしない）</li>
<li>パラメータがあれば /image_filter へリライトされ、パラメータから変数に代入し、$arg_typeを元に /resize か /corp へリライトします。</li>
<li>/reize /crop でそれぞれ処理をし、変換された画像が返されます。</li>
</ol>
<p>※ ImageFilterが処理できない場合は415エラーが発生するので、それを1*1pxの透過GIFに置き換えています。<br />
<br clear="all"/></p>
<h4>設定ファイル</h4>
<pre class="terminal">
location ~ /images/.*\.jpg$ {
    if ($query_string ~ .*=.*) {
      rewrite ^/images/(.*\.jpg)$ /image_filter/$1 last;
    }
}

location ~ ^/image_filter/(.*\.jpg)$ {
    internal;

    set $file $1;
    set $width 150;
    set $height 150;
    set $quality 75;

    if ($arg_width ~ (\d*)) {
        set $width $1;
    }
    if ($arg_height ~ (\d*)) {
        set $height $1;
    }
    if ($arg_quality ~ (100|[1-9][0-9]|[1-9])) {
        set $quality $1;
    }

    if ($arg_type = "resize") {
        rewrite ^ /resize last;
    }
  
    rewrite ^ /crop last;
}

location /resize {
    internal;
    rewrite ^ /images/$file break;
    image_filter  resize  $width $height;
    image_filter_jpeg_quality $quality;
    error_page 415 = @empty;
}

location /crop {
    internal;
    rewrite ^ /images/$file break;
    image_filter  crop  $width $height;
    image_filter_jpeg_quality $quality;
    error_page 415 = @empty;
}

location @empty {
    empty_gif;
}
</pre>
<h4>パフォーマンス</h4>
<p><a href="http://cloudrop.jp/wp-content/uploads/2011/12/nginx_if_static_graph.jpg" target="_blank"><img src="http://cloudrop.jp/wp-content/uploads/2011/12/nginx_if_static_graph.jpg" alt="ローカル&amp;no cache(req/s)グラフ" title="ローカル&amp;no cache(req/s)グラフ" width="304" height="213" class="aligncenter size-full wp-image-1447" /></a></p>
<p style="font-size:90%;font-style:italic;">ab（ApacheBench）で100リクエストを並列で一度に送り、1秒あたりのリクエスト処理数を5回測定した平均値。クライアントとサーバーは別でインターネットを経由して測定。</p>
<p>ローカルでの処理なのでネットワークのボトルネックはありません。一方、キャッシュを利用していないので、リクエストごとに変換処理が動くことになります。<br />
無変換を基準に考えると、サイズが大きめの画像へのリサイズは時間がかかりますが、小さくなるに従って無変換よりもパフォーマンスが上がります。<br />
変換に処理時間がかかるものの、Webで利用するサムネイル程度のサイズにすれば十分実用的な速度だと思います。</p>
<h3>S3経由で実験</h3>
<p>今度はTOFUの仕様に近づくべく、S3（リモートサーバー）にあるファイルを取得するようにします。<br />
実験のサーバーは「さくらのVPS512」でS3は「USスタンダードリージョン」です。ネットワークのレイテンシは150ms程です。</p>
<h4>対象とするファイル</h4>
<ul>
<li><a href="http://cloudrop.s3.amazonaws.com/sanzaru.jpg" target="_blank">sanzaru.jpg</a></li>
<li>US Standard リージョン</li>
<li>JPEGファイル</li>
<li>1024&#215;683 ピクセル</li>
<li>194,728 バイト</li>
</ul>
<h4>外部からのパラメータ（ローカルと同じ）</h4>
<ul>
<li>width（幅）</li>
<li>height（高さ）</li>
<li>type（リサイズの方法）
<ul>
<li>resize（縦横比を変えずにサイズ変換）</li>
<li>crop（サイズ変換後に指定されたサイズに切り取る）</li>
</ul>
</li>
<li>quality（JPEGの画質≒圧縮率）</li>
</ul>
<h4>要件</h4>
<p>JPEGファイル（*.jpg）にパラメータを付けてアクセスをした時、S3上にある同名ファイルを取得し、パラメータに従って変換された画像を返す。<br />
変換した画像はキャシュし、<strong>2回目以降はキャッシュ</strong>を利用する。</p>
<h4>結果</h4>
<p><img src="http://nginx.labs.cloudrop.jp/s3images/sanzaru.jpg?width=150&#038;height=150&#038;type=resize" width="150" height="100" /><br />
/s3images/sanzaru.jpg?width=150&#038;height=150&#038;type=resize</p>
<p><img src="http://nginx.labs.cloudrop.jp/s3images/sanzaru.jpg?width=200&#038;height=200&#038;type=crop" width="200" height="200" /><br />
/s3images/sanzaru.jpg?width=200&#038;height=200&#038;type=crop</p>
<p><img src="http://nginx.labs.cloudrop.jp/s3images/sanzaru.jpg?width=400&#038;height=100&#038;type=crop&#038;quality=5" width="400" height="100" /><br />
/s3images/sanzaru.jpg?width=400&#038;height=100&#038;type=crop&#038;quality=5</p>
<p>こちらのリンク先でパラメータをいろいろ変更してテストができます。お試し下さい。<br />
<a href="http://nginx.labs.cloudrop.jp/s3images/sanzaru.jpg?width=200&#038;height=200&#038;type=crop" target="_blank">http://nginx.labs.cloudrop.jp/s3images/sanzaru.jpg?width=200&#038;height=200&#038;type=crop</a></p>
<h4>設定方法</h4>
<p><a href="http://cloudrop.jp/wp-content/uploads/2011/12/nginx_if_s3.png" target="_blank"><img src="http://cloudrop.jp/wp-content/uploads/2011/12/nginx_if_s3.png" alt="処理の流れ（S3）" title="処理の流れ（S3）" width="305" height="183" class="wp-image-1427" style="float:left; margin:0 40px 5px 0;"/></a>
<ol style="padding-left:30px;">
<li>80番ポートで待ち受ける/s3images で8080番ポートで動くバックエンドの/s3images へリクエストをそのまま渡します。</li>
<li>8080番ポートの/s3imagesでパラメータから変数に代入し、$arg_typeを元に/s3_resize か/s3_corp へ、パラメータがなければ/s3_original へリライトします。<br clear="all"/></li>
<li>/s3_resize /s3_crop /s3_originalでそれぞれS3からファイルを取得・変換処理をし、画像を80番ポートのフロントエンドへ返します。</li>
<li>80番ポートのフロントエンドはバックエンドから返ってきたレスポンスをキャッシュし、画像を返します。以降、すでにキャッシュ済みリクエストだった場合は、バックエンドへ送らず、キャッシュを返します。</li>
</ol>
<h4>設定ファイル</h4>
<pre class="terminal">
server {
    listen 80;
    server_name localhost;
    root /var/www/html;

    location /s3images {
        proxy_pass http://localhost:8080;
        proxy_cache s3cache;
        proxy_cache_key $scheme$host$uri$arg_width$arg_height$arg_type$arg_quality;
        proxy_cache_valid  200 60m;
    }
}

server {
    listen 8080;
    server_name localhost;
    root /var/www/html;

    access_log logs/proxy_access.log;
    access_log logs/error_access.log;

    resolver 8.8.8.8;

    location ~ /s3images/(.*\.jpg)$ {

        set $s3host MY_S3_HOST;
        set $file $1;
        set $width 150;
        set $height 150;
        set $quality 75;

        if ($query_string !~ .*=.*) {
          rewrite ^ /s3_original last;
        }

        if ($arg_width ~ (\d*)) {
            set $width $1;
        }
        if ($arg_height ~ (\d*)) {
            set $height $1;
        }
        if ($arg_quality ~ (100|[1-9][0-9]|[1-9])) {
            set $quality $1;
        }

        if ($arg_type = "resize") {
            rewrite ^ /s3_resize last;
        }

        rewrite ^ /s3_crop last;
    }

    location /s3_original {
        internal;
        proxy_pass http://$s3host/$file;
    }

    location /s3_resize {
        internal;
        proxy_pass http://$s3host/$file;
        image_filter  resize  $width  $height;
        image_filter_jpeg_quality  $quality;
        error_page 415 = @empty;
    }

    location /s3_crop {
        internal;
        proxy_pass http://$s3host/$file;
        image_filter  crop  $width  $height;
        image_filter_jpeg_quality  $quality;
        error_page 415 = @empty;
    }

    location @empty {
        empty_gif;
    }
}
</pre>
<p>8080ポート側にresolverの設定が入っています。NginxはOS標準の名前解決方法を利用してくれないため、ネームサーバーをresolverに設定する必要があります。<br />
ここではGoogle Public DNSが設定されていますが、利用するサーバーの最寄り（通常同じDC内）のネームサーバーを指定します。</p>
<h4>パフォーマンス</h4>
<p><a href="http://cloudrop.jp/wp-content/uploads/2011/12/nginx_if_s3_graph.jpg" target="_blank"><img src="http://cloudrop.jp/wp-content/uploads/2011/12/nginx_if_s3_graph.jpg" alt="S3経由&amp;cache(req/s)グラフ" title="S3経由&amp;cache(req/s)グラフ" width="313" height="213" class="aligncenter size-full wp-image-1452" /></a></p>
<p style="font-size:90%;font-style:italic;">ab（ApacheBench）で100リクエストを並列で一度に送り、1秒あたりのリクエスト処理数を5回測定した平均値。クライアントとサーバーは別でインターネットを経由して測定。</p>
<p>S3からファイルを取得する処理を含めると、ネットワークのボトルネックがあり、1リクエスト2秒程度かかります。それを含めてしまうと、ネットワークに引きずられて正確な値がでないので、キャッシュに対して測定しています。</p>
<p>キャッシュからの応答になるので、純粋にファイルサイズの大きさに比例していきます。マスターの画像が変更されないことがわかっている場合、もしくは、変更があった場合にハッシュ値などを使ってキャッシュを書き換えるなどすると、実用的な速度で利用できることがわかります。</p>
<h3>まとめ</h3>
<p>細かい設定（例えば、左上から右へ10px下へ20pxを起点に切り取るなど）はできませんし、pngからjpgなどのフォーマット変換もできないので、多くの機能を望む場合は、他のプログラムを利用するか、Nginxモジュールを書く事になると思います。</p>
<p>とは言っても、モジュールをインストールして、設定を書くだけで利用できるので、プロトタイプ開発の用途には使えますし、リモートサーバーのファイル自体をキャッシュしたり、Proxy Cacheを適切に設定したり、多段にキャッシュを用意したりすれば、用途に限りがありますが、プロダクションでも使えると思います。</p>
<h4>Nginxモジュール開発の参考</h4>
<ul>
<li><a href="http://d.hatena.ne.jp/yone098/20090930/1254275423">NginxでのModuleの作り方 &#8211; よねのはてな</a></li>
<li><a href="http://techblog.heartrails.com/2011/01/rails-nginx.html">Rails アプリを nginx の拡張モジュールで置き換えて高速化する方法 &#8211; HeartRails Tech Blog</a></li>
<li><a href="http://www.evanmiller.org/nginx-modules-guide.html">Emiller&#8217;s Guide to Nginx Module Development</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://cloudrop.jp/labs/nginx_image_filter/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://cloudrop.jp/labs/nginx_image_filter" />
	</item>
		<item>
		<title>さくらのクラウドでネットワークがつながらない時の対処法</title>
		<link>http://cloudrop.jp/cloud/sacloud_network_lost?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sacloud_network_lost</link>
		<comments>http://cloudrop.jp/cloud/sacloud_network_lost#comments</comments>
		<pubDate>Mon, 28 Nov 2011 07:47:28 +0000</pubDate>
		<dc:creator>sekine</dc:creator>
				<category><![CDATA[クラウド]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[さくらのクラウド]]></category>

		<guid isPermaLink="false">http://cloudrop.jp/?p=1265</guid>
		<description><![CDATA[さくらのクラウドでプライベートテンプレートから仮想サーバーを起動させた時、インターネットにつながらない場合の対処法。]]></description>
			<content:encoded><![CDATA[<p>さくらのクラウドでプライベートテンプレートから仮想サーバーを起動させると、こういうことが起ります。</p>
<pre class="terminal" style="margin-bottom:0.5em;">
[root@sakura ~]# ping google.com
ping: unknown host google.com
</pre>
<p style="color:#666;text-align:right;">（コントロールパネルのコンソールから実行）</p>
<p>普通に外部（インターネット）と通信ができません。</p>
<blockquote><p>
AWS EC2やRackspace Cloudではテンプレートから新しくインスタンスを立ち上げた場合は、ネットワーク設定周りを自動的に調整してくれて、起動直後からインターネットにつながります。<br />
逆に言うと、さくらのクラウドは純粋な仮想サーバーと考えると扱いやすくなります。
</p></blockquote>
<p>これは、クラウドのシステムから仮想サーバーに<strong>割り振られたグローバルIPアドレスと起動したサーバーのネットワークの設定がずれているのが原因</strong>です。</p>
<h3>対処法手順</h3>
<p>まずは、コントロールパネル ＞ サーバー ＞ 詳細情報で、割り振られているIPアドレスなどネットワークアドレス情報、Macアドレスを確認して、OSのネットワーク設定を変更します。</p>
<p style="text-align:center;">
<a href="http://cloudrop.jp/wp-content/uploads/2011/11/eth0_config.png" target="_blank"><img src="http://cloudrop.jp/wp-content/uploads/2011/11/eth0_config.png" alt="ネットワークの設定" title="ネットワークの設定" width="254" height="232" class="wp-image-1304" /></br>（クリックで拡大）</a>
</p>
<p>以下の例は、RedHat系Linuxの場合で、割り振られたIPv4アドレスが「133.242.xxx.xxx」、ゲートウェイが「133.242.xxx.1」、eth0のMacアドレスが「9c:a3:ba:xx:xx:xx」だったとします。</p>
<h4>NICの設定ファイル</h4>
<p>ネットワークインターフェースの設定を書き換えます。</p>
<pre class="terminal">
[root@sakura ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0 
</pre>
<p><span style="color:#ff0000;font-weight:bold;">× NG</span></p>
<pre class="terminal">
DEVICE=eth0
BOOTPROTO=none
<span style="color:#ff0000">HWADDR=9c:a3:ba:yy:yy:yy</span>
NM_CONTROLLED=yes
ONBOOT=yes
TYPE=Ethernet
NETMASK=255.255.255.0
<span style="color:#ff0000">BROADCAST=133.242.yyy.255</span>
<span style="color:#ff0000">IPADDR=133.242.yyy.zzz</span>
<span style="color:#ff0000">NETWORK=133.242.yyy.0</span>
<span style="color:#ff0000">GATEWAY=133.242.yyy.1</span>
IPV6INIT=no
USERCTL=no
</pre>
<p><span style="color:#008000;font-weight:bold;">◯ OK</span></p>
<pre class="terminal">
DEVICE=eth0
BOOTPROTO=none
<span style="color:#00ff00">HWADDR=9c:a3:ba:xx:xx:xx</span>
NM_CONTROLLED=yes
ONBOOT=yes
TYPE=Ethernet
NETMASK=255.255.255.0
<span style="color:#00ff00">BROADCAST=133.242.xxx.255</span>
<span style="color:#00ff00">IPADDR=133.242.xxx.xxx</span>
<span style="color:#00ff00">NETWORK=133.242.xxx.0</span>
<span style="color:#00ff00">GATEWAY=133.242.xxx.1</span>
IPV6INIT=no
USERCTL=no
</pre>
<h4>udevルールファイル</h4>
<p>Macアドレスも変更されている（OS的にはハードウェアが新しくなったと認識している）ので、udevルールファイルも書き換える必要があります。</p>
<pre class="terminal">
[root@sakura ~]# vi /etc/udev/rules.d/70-persistent-net.rules 
</pre>
<p><span style="color:#ff0000;font-weight:bold;">× NG</span></p>
<pre class="terminal">
<span style="color:#ff0000"># PCI device 0x8086:0x100e (e1000) (custom name provided by external tool)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="9c:a3:ba:zz:zz:zz", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"</span>

<span style="color:#ff0000"># PCI device 0x8086:0x100e (e1000)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="9c:a3:ba:yy:yy:yy", ATTR{type}=="1", KERNEL=="eth*", NAME="eth2"</span>

# PCI device 0x8086:0x100e (e1000)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="9c:a3:ba:xx:xx:xx", ATTR{type}=="1", KERNEL=="eth*", NAME="<span style="color:#ff0000">eth3</span>"
</pre>
<p><span style="color:#008000;font-weight:bold;">◯ OK</span></p>
<pre class="terminal">
[root@sakura ~]# vi /etc/udev/rules.d/70-persistent-net.rules 
# PCI device 0x8086:0x100e (e1000)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="9c:a3:ba:xx:xx:xx", ATTR{type}=="1", KERNEL=="eth*", NAME="<span style="color:#00ff00">eth0</span>"
</pre>
<h4>再起動</h4>
<p>システムを再起動します。</p>
<pre class="terminal">
[root@sakura ~]$ reboot
</pre>
<h4>確認</h4>
<p>通信が成功します。</p>
<pre class="terminal">
[root@sakura ~]$ ping google.com -c 4
PING google.com (72.14.203.104) 56(84) bytes of data.
64 bytes from tx-in-f104.1e100.net (72.14.203.104): icmp_seq=1 ttl=54 time=51.0 ms
64 bytes from tx-in-f104.1e100.net (72.14.203.104): icmp_seq=2 ttl=54 time=51.3 ms
64 bytes from tx-in-f104.1e100.net (72.14.203.104): icmp_seq=3 ttl=54 time=51.3 ms
64 bytes from tx-in-f104.1e100.net (72.14.203.104): icmp_seq=4 ttl=54 time=50.6 ms

--- google.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3052ms
rtt min/avg/max/mdev = 50.669/51.102/51.339/0.270 ms
</pre>
<h4>余談</h4>
<p style="margin-bottom:0.5em;">
9C-A3-BAのOUIはさくらインターネットのなんですね。
</p>
<blockquote><p><a href="http://twitter.com/#!/jq6xze_1/status/103647787014569984">Twitter / 大久保　修一: MACアドレスを取得しました。 9C-A3-BA / SAKURA Internet Inc.</a></p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://cloudrop.jp/cloud/sacloud_network_lost/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://cloudrop.jp/cloud/sacloud_network_lost" />
	</item>
		<item>
		<title>携帯向けTwitterクライアントサービス「yubitter」のアカウント数が25万アカウントを突破</title>
		<link>http://cloudrop.jp/news/20111128?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=20111128</link>
		<comments>http://cloudrop.jp/news/20111128#comments</comments>
		<pubDate>Mon, 28 Nov 2011 04:00:38 +0000</pubDate>
		<dc:creator>sekine</dc:creator>
				<category><![CDATA[ニュースリリース]]></category>

		<guid isPermaLink="false">http://cloudrop.jp/?p=1289</guid>
		<description><![CDATA[クラウドロップ株式会社が運営する携帯電話向けTwitterクライアントサービス「yubitter」（ http://yubitter.com/ ）の登録アカウント数が2011年11月26日に25万アカウントを突破致しました。 2009年12月8日のリリースから約2年での達成となります。]]></description>
			<content:encoded><![CDATA[<p>クラウドロップ株式会社が運営する携帯電話向けTwitterクライアントサービス「yubitter」（ <a href="http://yubitter.com/">http://yubitter.com/</a> ）の登録アカウント数が2011年11月26日に25万アカウントを突破致しました。<br />
2009年12月8日のリリースから約2年での達成となります。</p>
<p><a href="http://yubitter.com/"><img src="http://cloudrop.jp/wp-content/uploads/2011/11/yubitter_catch_l.jpg" alt="yubitter" title="yubitter" width="113" height="157" class="alignleft size-full wp-image-1290" /></a><br />
yubitter<br />
<a href="http://yubitter.com/">yubitter.com</a><br />
yubitterは見やすさ、つぶやきやすさを重視した携帯電話、PHSでTwitterを利用するためのサービスです。docomo, au, SoftBank, WILLCOM の端末に対応しています。<br />
<br clear="all" style="clear:both;"/></p>
]]></content:encoded>
			<wfw:commentRss>http://cloudrop.jp/news/20111128/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://cloudrop.jp/news/20111128" />
	</item>
		<item>
		<title>Nginxを使ったもう一歩進んだWordPressチューニング</title>
		<link>http://cloudrop.jp/wordpress/more_tuning_on_nginx?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=more_tuning_on_nginx</link>
		<comments>http://cloudrop.jp/wordpress/more_tuning_on_nginx#comments</comments>
		<pubDate>Fri, 25 Nov 2011 09:39:54 +0000</pubDate>
		<dc:creator>sekine</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[nginx]]></category>

		<guid isPermaLink="false">http://cloudrop.jp/?p=1175</guid>
		<description><![CDATA[Nginxを使ったWordPressのチューニングといえば、フロントエンドのNginxとバックエンドのNginx（もしくはApache）に分けてproxy cacheを効かせるのが王道です。 さらにWP Super Cacheプラグインを利用してなるべくPHPやMySQLにアクセスさせないようにすると、手軽で絶大なパフォーマンスアップが可能です。 今回はそこからもう一歩進めたチューニングについて書きたいと思います。]]></description>
			<content:encoded><![CDATA[<p><img src="http://cloudrop.jp/wp-content/uploads/2011/11/wp_on_nginx.png" alt="" title="wp_on_nginx" width="250" height="99" class="alignleft size-full wp-image-1200" />Nginxを使ったWordPressのチューニングといえば、フロントエンドのNginxとバックエンドのNginx（もしくはApache）に分けてproxy cacheを効かせるのが王道です。<br />
さらにWP Super Cacheプラグインを利用してなるべくPHPやMySQLにアクセスさせないようにすると、手軽で絶大なパフォーマンスアップが可能です。</p>
<p>今回はそこからもう一歩進めたチューニングについて書きたいと思います。</p>
<p><!--TOC--></p>
<h3 style="margin-top:1em;">二段階層を廃したシンプルな構成</h3>
<p>まずは、図をご覧ください。</p>
<p><img src="http://cloudrop.jp/wp-content/uploads/2011/11/nginx_wp_ab.png" alt="構成図" title="構成図" width="619" height="443" class="aligncenter size-full wp-image-1190" /></p>
<p>前述の王道チューニングの構成はA図となります。</p>
<p><strong>proxy cache</strong>はNginxがバックエンドのサーバーに処理を回し、返ってきたレスポンスをキャッシュして、Nginx自身がキャッシュを返すことでパフォーマンスを上げる仕組みです。<br />
A図-1がキャッシュの無いアクセス、A図-2がキャッシュが効いているアクセスを表しています。<br />
A図-3は静的なファイル（css, js, jpgなど）をフロントのNginxが直接返すことを表しています。</p>
<h4>fastcgi cache（HttpFcgiModule）</h4>
<p>proxy cache自体はバックエンドのサーバーがHTTPでコンテンツを返してくれれば、どんなアプリケーションでも問わない汎用的なキャッシュ機能です。つまり、proxy cacheを利用しようとするともうひとつHTTPサーバーが必要になり、A図のようにHTTPのレイヤーが二段構成になります。</p>
<p>Nginxにはproxy cacheと似た機能で<strong>fastcgi cache</strong>という機能（<a href="http://wiki.nginx.org/HttpFcgiModule">HttpFcgiModule</a>）があります。これはバックエンドのFastCGIのレスポンスをキャッシュする機能です。<br />
これを利用すると、proxy cacheを利用したのと同じ効果をHTTPサーバーなしに実現できます。<br />
A図の8080ポートのサーバーが必要なくなり、B図の構成になります。<br />
無駄な通信と処理がなくなり、シンプルです。</p>
<h3>WP Super Cacheを最大限利用する</h3>
<p><strong>WP Super Cache</strong>は、アクセスごとに動的に生成される記事を、静的なHTMLファイルとして保存（キャッシュ）して、それを返すように振舞うプラグインです。<br />
キャッシュが効いている間はMySQLにアクセスすることが無いのでパフォーマンスが上がります。</p>
<h4>.htacessの落とし穴</h4>
<p>WP Super Cacheを利用すると、.htaccessに以下の設定が追加されます。<br />
(利用しているプラグインによって多少変わります)</p>
<pre class="terminal" style="height: 250px;">
# BEGIN WPSuperCache
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
AddDefaultCharset UTF-8
RewriteCond %{REQUEST_METHOD} !POST
RewriteCond %{QUERY_STRING} !.*=.*
RewriteCond %{HTTP:Cookie} !^.*(comment_author_|wordpress_logged_in|wp-postpass_).*$
RewriteCond %{HTTP:X-Wap-Profile} !^[a-z0-9\"]+ [NC]
RewriteCond %{HTTP:Profile} !^[a-z0-9\"]+ [NC]
RewriteCond %{HTTP_USER_AGENT} !^.*(2.0\ MMP|240x320|400X240|AvantGo|BlackBerry|Blazer|Cellphone|Danger|DoCoMo|Elaine/3.0|EudoraWeb|Googlebot-Mobile|hiptop|IEMobile|KYOCERA/WX310K|LG/U990|MIDP-2.|MMEF20|MOT-V|NetFront|Newt|Nintendo\ Wii|Nitro|Nokia|Opera\ Mini|Palm|PlayStation\ Portable|portalmmm|Proxinet|ProxiNet|SHARP-TQ-GX10|SHG-i900|Small|SonyEricsson|Symbian\ OS|SymbianOS|TS21i-10|UP.Browser|UP.Link|webOS|Windows\ CE|WinWAP|YahooSeeker/M1A1-R2D2|iPhone|iPod|Android|BlackBerry9530|LG-TU915\ Obigo|LGE\ VX|webOS|Nokia5800).* [NC]
RewriteCond %{HTTP_user_agent} !^(w3c\ |w3c-|acs-|alav|alca|amoi|audi|avan|benq|bird|blac|blaz|brew|cell|cldc|cmd-|dang|doco|eric|hipt|htc_|inno|ipaq|ipod|jigs|kddi|keji|leno|lg-c|lg-d|lg-g|lge-|lg/u|maui|maxo|midp|mits|mmef|mobi|mot-|moto|mwbp|nec-|newt|noki|palm|pana|pant|phil|play|port|prox|qwap|sage|sams|sany|sch-|sec-|send|seri|sgh-|shar|sie-|siem|smal|smar|sony|sph-|symb|t-mo|teli|tim-|tosh|tsm-|upg1|upsi|vk-v|voda|wap-|wapa|wapi|wapp|wapr|webc|winw|winw|xda\ |xda-).* [NC]
RewriteCond %{HTTP_USER_AGENT} !^(DoCoMo/|J-PHONE/|J-EMULATOR/|Vodafone/|MOT(EMULATOR)?-|SoftBank/|[VS]emulator/|KDDI-|UP\.Browser/|emobile/|Huawei/|IAC/|Nokia|mixi-mobile-converter/)
RewriteCond %{HTTP_USER_AGENT} !(DDIPOCKET;|WILLCOM;|Opera\ Mini|Opera\ Mobi|PalmOS|Windows\ CE;|PDA;\ SL-|PlayStation\ Portable;|SONY/COM|Nitro|Nintendo)
RewriteCond %{HTTP:Accept-Encoding} gzip
RewriteCond %{DOCUMENT_ROOT}/wp-content/cache/supercache/%{HTTP_HOST}/$1/index.html.gz -f
RewriteRule ^(.*) "/wp-content/cache/supercache/%{HTTP_HOST}/$1/index.html.gz" [L]

RewriteCond %{REQUEST_METHOD} !POST
RewriteCond %{QUERY_STRING} !.*=.*
RewriteCond %{HTTP:Cookie} !^.*(comment_author_|wordpress_logged_in|wp-postpass_).*$
RewriteCond %{HTTP:X-Wap-Profile} !^[a-z0-9\"]+ [NC]
RewriteCond %{HTTP:Profile} !^[a-z0-9\"]+ [NC]
RewriteCond %{HTTP_USER_AGENT} !^.*(2.0\ MMP|240x320|400X240|AvantGo|BlackBerry|Blazer|Cellphone|Danger|DoCoMo|Elaine/3.0|EudoraWeb|Googlebot-Mobile|hiptop|IEMobile|KYOCERA/WX310K|LG/U990|MIDP-2.|MMEF20|MOT-V|NetFront|Newt|Nintendo\ Wii|Nitro|Nokia|Opera\ Mini|Palm|PlayStation\ Portable|portalmmm|Proxinet|ProxiNet|SHARP-TQ-GX10|SHG-i900|Small|SonyEricsson|Symbian\ OS|SymbianOS|TS21i-10|UP.Browser|UP.Link|webOS|Windows\ CE|WinWAP|YahooSeeker/M1A1-R2D2|iPhone|iPod|Android|BlackBerry9530|LG-TU915\ Obigo|LGE\ VX|webOS|Nokia5800).* [NC]
RewriteCond %{HTTP_user_agent} !^(w3c\ |w3c-|acs-|alav|alca|amoi|audi|avan|benq|bird|blac|blaz|brew|cell|cldc|cmd-|dang|doco|eric|hipt|htc_|inno|ipaq|ipod|jigs|kddi|keji|leno|lg-c|lg-d|lg-g|lge-|lg/u|maui|maxo|midp|mits|mmef|mobi|mot-|moto|mwbp|nec-|newt|noki|palm|pana|pant|phil|play|port|prox|qwap|sage|sams|sany|sch-|sec-|send|seri|sgh-|shar|sie-|siem|smal|smar|sony|sph-|symb|t-mo|teli|tim-|tosh|tsm-|upg1|upsi|vk-v|voda|wap-|wapa|wapi|wapp|wapr|webc|winw|winw|xda\ |xda-).* [NC]
RewriteCond %{HTTP_USER_AGENT} !^(DoCoMo/|J-PHONE/|J-EMULATOR/|Vodafone/|MOT(EMULATOR)?-|SoftBank/|[VS]emulator/|KDDI-|UP\.Browser/|emobile/|Huawei/|IAC/|Nokia|mixi-mobile-converter/)
RewriteCond %{HTTP_USER_AGENT} !(DDIPOCKET;|WILLCOM;|Opera\ Mini|Opera\ Mobi|PalmOS|Windows\ CE;|PDA;\ SL-|PlayStation\ Portable;|SONY/COM|Nitro|Nintendo)
RewriteCond %{DOCUMENT_ROOT}/wp-content/cache/supercache/%{HTTP_HOST}/$1/index.html -f
RewriteRule ^(.*) "/wp-content/cache/supercache/%{HTTP_HOST}/$1/index.html" [L]
</IfModule>

# END WPSuperCache
</pre>
<p>これは、すでにWP Super Cacheによって静的なファイルが生成されている場合、PHPを介さずにApacheが直接リクエストを返すようにする設定です。<br />
WP Super Cacheの推奨設定では、index.htmlとそれを圧縮したindex.html.gzが用意されるので、冗長な設定になっています。</p>
<p>Nginxにとって<strong>.htaccessはただのテキストファイルです</strong>から、上記RewriteRuleをNginxの設定ファイルに移植しないと、WP Super Cacheは本来のパフォーマンスを発揮しません。<br />
この移植をすることで、B図-4のように、fastcgi cacheに到達することもなく、静的ファイルと同じ処理、パフォーマンスになります。</p>
<h4>HttpGzipStaticModule</h4>
<p>Nginxの<a href="http://wiki.nginx.org/HttpGzipStaticModule">HttpGzipStaticModule</a>は、同じディレクトリ内にあらかじめ圧縮ファイル（.gz）が用意されている場合に、クライアント判定を行なって自動的に圧縮ファイルを返してくれるモジュールです。（正確には、Gzip圧縮に対応しているクライアントからリクエストが来て、同ディレクトリに同タイムスタンプで同名+.gzという名前のファイルがある場合）</p>
<p>このモジュールを導入するメリットは、gzファイル分の.htaccessを移植する手間がなくなることです。ただし、コアモジュールではないので、コンパイル時にオプションで指定する必要があります。</p>
<pre class="terminal">
./configure --with-http_gzip_static_module
</pre>
<blockquote><p>コンパイルし直したnginxの入れ替えを行う場合は、こちらを参考にしてください。</p>
<ul>
<li><a href="http://cloudrop.jp/labs/nginx_upgrade">リクエストを落とさずにnginxをアップグレードする方法とその検証</a></li>
</ul>
</blockquote>
<p>Nginxにはコアモジュールで<a href="http://wiki.nginx.org/HttpGzipModule">HttpGzipModule</a>があり、設定をオンにすることで特定のContent-TypeにGzip圧縮をかけてレスポンスを返すことができます。こちらはリクエストごとにオンザフライで圧縮をかけるので、余分に処理がかかります。あらかじめcssやjsなどの圧縮ファイルが用意できる場合は、同階層に設置してHttpGzipStaticModuleの恩恵を受けたほうがいいと思います。</p>
<h3>サンプル設定ファイル</h3>
<p>前述の項目を網羅して、かつ可能な限り正常に動いている環境の設定ファイルを載せています。</p>
<h4>nginx.conf</h4>
<pre class="terminal">
user  nginx nginx;
worker_processes  2; <span style="color:#00ff00"># サーバーのコア数に合わせて</span>

pid  /var/run/nginx.pid;

events {
    worker_connections  1024;
    use epoll;　<span style="color:#00ff00"># Linuxの場合</span>
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    <span style="color:#00ff00"># 最後の$request_timeは処理時間(ms)</span>
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for" $request_time';

    sendfile        on;
    tcp_nopush     on;
    tcp_nodelay on;

    keepalive_timeout  10;

    connection_pool_size 256;
    client_header_buffer_size 1k;
    large_client_header_buffers 4 2k;
    request_pool_size 4k;
    if_modified_since before;
    ignore_invalid_headers on;
    server_tokens off;

    gzip  on;
    gzip_min_length 0;
    gzip_buffers 4 8k;
    gzip_types text/plain text/xml application/x-javascript text/css;
    gzip_disable "msie6";
    gzip_vary on;
    <span style="color:#00ff00"># HttpStaticGzipModuleをオンに</span>
    gzip_static on;

    output_buffers 1 32k;
    postpone_output 1460;

    <span style="color:#00ff00"># fastcgi cacheの設定（httpディレクティブ内のみ有効）</span>
    fastcgi_cache_path      /usr/local/nginx/cache levels=1:2 keys_zone=wpcache:10m max_size=50M inactive=30m;

    server {
        listen       80;
        server_name  localhost;
        charset utf-8;

        location / {
            return 403;
        }

        location /nginx_status {
            stub_status on;
            access_log off;
            allow 127.0.0.1;
            deny all;
        }  

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

    include ./wordpress.conf;
}
</pre>
<h4>wordpress.conf</h4>
<pre class="terminal">
<span style="color:#00ff00"># 設定を変えやすいようにupstreamにまとめておく</span>
upstream phpfpm {
    <span style="color:#00ff00"># ローカルの場合はUNIXソケットで</span>
    server unix:/var/run/php-fpm/www.sock;
}

server {
    listen       80;
    server_name  example.com;
    root /var/www/wordpress;
    access_log logs/access.log main;

    location / {
        <span style="color:#00ff00"># 静的なファイルの場合は処理をとめる</span>
        <span style="color:#00ffff"># リクエストの度にファイルの存在をチェックするのは無駄だという意見もありますが、</span>
        <span style="color:#00ffff"># どのURLの時index.phpに渡すのか、プラグインを含めて全仕様が分からないため、</span>
        <span style="color:#00ffff"># これが最も安全だと思います。</span>
        if (-f $request_filename) {
            break;
        }

        <span style="color:#00ff00"># ここからWP Super Cacheの設定（少しfastcgi cacheの設定も）</span>
        <span style="color:#00ff00"># モバイルからのアクセスはキャッシュさせないようにする変数</span>
        set $nocache "";
        set $supercache_file $document_root/wp-content/cache/supercache/${http_host}${uri}/index.html;
        set $supercache_uri "";
        if (-f $supercache_file) {
            set $supercache_uri /wp-content/cache/supercache/${http_host}${uri}/index.html;
        }

        if ($request_method = "POST") {
            set $supercache_uri "";
            set $nocache "1";
        }

        if ($query_string ~ .*=.*) {
            set $supercache_uri "";
        }

        if ($http_cookie ~ ^.*(comment_author_|wordpress_logged_in|wp-postpass_).*$) {
            set $supercache_uri "";
            set $nocache "1";
        }

        if ($http_x_wap_profile ~ ^[a-z0-9\"]+) {
            set $supercache_uri "";
            set $nocache "1";
        }

        if ($http_profile ~ ^[a-z0-9\"]+) {
            set $supercache_uri "";
            set $nocache "1";
        }

        if ($http_user_agent ~ ^.*(2.0\ MMP|240x320|400X240|AvantGo|BlackBerry|Blazer|Cellphone|Danger|DoCoMo|Elaine/3.0|EudoraWeb|Googlebot-Mobile|hiptop|IEMobile|KYOCERA/WX310K|LG/U990|MIDP-2.|MMEF20|MOT-V|NetFront|Newt|Nintendo\ Wii|Nitro|Nokia|Opera\ Mini|Palm|PlayStation\ Portable|portalmmm|Proxinet|ProxiNet|SHARP-TQ-GX10|SHG-i900|Small|SonyEricsson|Symbian\ OS|SymbianOS|TS21i-10|UP.Browser|UP.Link|webOS|Windows\ CE|WinWAP|YahooSeeker/M1A1-R2D2|iPhone|iPod|Android|BlackBerry9530|LG-TU915\ Obigo|LGE\ VX|webOS|Nokia5800).*) {
            set $supercache_uri "";
            set $nocache "1";
        }

        if ($http_user_agent ~ ^(w3c\ |w3c-|acs-|alav|alca|amoi|audi|avan|benq|bird|blac|blaz|brew|cell|cldc|cmd-|dang|doco|eric|hipt|htc_|inno|ipaq|ipod|jigs|kddi|keji|leno|lg-c|lg-d|lg-g|lge-|lg/u|maui|maxo|midp|mits|mmef|mobi|mot-|moto|mwbp|nec-|newt|noki|palm|pana|pant|phil|play|port|prox|qwap|sage|sams|sany|sch-|sec-|send|seri|sgh-|shar|sie-|siem|smal|smar|sony|sph-|symb|t-mo|teli|tim-|tosh|tsm-|upg1|upsi|vk-v|voda|wap-|wapa|wapi|wapp|wapr|webc|winw|winw|xda\ |xda-).*) {
            set $supercache_uri "";        
            set $nocache "1";
        }

        if ($http_user_agent ~ ^(DoCoMo/|J-PHONE/|J-EMULATOR/|Vodafone/|MOT(EMULATOR)?-|SoftBank/|[VS]emulator/|KDDI-|UP\.Browser/|emobile/|Huawei/|IAC/|Nokia|mixi-mobile-converter/)) {
            set $supercache_uri "";
            set $nocache "1";
        }

        if ($http_user_agent ~ (DDIPOCKET\;|WILLCOM\;|Opera\ Mini|Opera\ Mobi|PalmOS|Windows\ CE\;|PDA\;\ SL-|PlayStation\ Portable\;|SONY/COM|Nitro|Nintendo)) {
            set $supercache_uri "";
            set $nocache "1";
        }

        if ($supercache_uri) {
            rewrite ^ $supercache_uri last;
            break;
        }

        rewrite ^ /index.php last;
    }

    location ~ \.php {
        <span style="color:#00ff00"># 存在しないPHPファイルをシャットアウト</span>
        if (!-f $request_filename) {
            return 404;
            break;
        }

        <span style="color:#00ff00"># fastcgi とfastcgi cacheの設定</span>
        include ./fastcgi.conf;
        fastcgi_pass          phpfpm;
        fastcgi_cache         wpcache;
        fastcgi_cache_key     "$scheme://$host$request_uri";
        fastcgi_cache_valid   200 10m;
        fastcgi_cache_valid   404 1m;
        <span style="color:#00ff00"># $nocache = "1"の時、fastcgi cacheが無効になる</span>
        fastcgi_cache_bypass  $nocache;
    }

    <span style="color:#00ff00"># よくアクセスされる静的ファイルにブラウザキャッシュが効くように設定</span>
    location ~ \.(jpg|png|gif|swf|jpeg)$ {
        log_not_found off; <span style="color:#00ff00"># 404の時にerror_logに書き込まないようにする設定</span>
        access_log off;
        expires 3d;
    }

    location ~ \.ico$ {
        log_not_found off;
        access_log off;
        expires max;
    }

    location ~ \.(css|js)$ {
        charset  UTF-8;
        access_log off;
        expires 1d;
    }

    <span style="color:#00ff00"># ドット始まりのファイルはアクセスできないように</span>
    location ~ /\. {
        deny all;
        log_not_found off;
        access_log off;
    }

    <span style="color:#00ff00"># リライトされたWP Super Cacheのファイル</span>
    location ~ /wp-content/cache/supercache/${http_host}${uri}/index\.html(\.gz)?$ {
        charset  UTF-8;
        internal; <span style="color:#00ff00"># この指定をしておくとURLを指定して直接アクセスできなくなる</span>
    }

    location ~ /wp-admin/$ {
        rewrite ^/wp-admin/$ /wp-admin/index.php last;
    }
}
</pre>
<h4>処理の解説</h4>
<p>Nginxのlocationディレクティブの評価順番は、wordpress.confを例にとると、すべてのアクセスが最初に &#8220;location /&#8221;ディレクティブを通ります。（記述順番は関係ありません。）</p>
<h5>静的ファイルのチェック</h5>
<p>このディレクティブの先頭でリクエストされた静的ファイルが存在するかのチェックを行なっています。<br />
静的ファイルとして存在した場合、breakで&#8221;location /&#8221;ディレクティブの処理が終わります。次に、マッチするlocationディレクティブがあればそちらが実行されます。<br />
例えば、cssファイルだった場合は、&#8221;location ~ \.(css|js)$&#8221;ディレクティブへ処理が続いていきます。これが<strong>B図-3</strong>の流れです。</p>
<h5>WP Super Cacheのチェック、fastcti cacheのチェック</h5>
<p>静的ファイルとして存在しなかった場合、処理は下へ進みます。<br />
次の処理ではWP Super Cacheが生成したキャッシュファイルの存在をチェックし、キャッシュファイルを利用するかどうかを下に続く条件で確認していきます。各条件では同時にfastcgi cacheを利用するかどうかのチェックも行なっています。</p>
<p>ここでは、$supercache_uriが&#8221;"（空文字）に書き換えられると、WP Super Cacheの静的キャッシュファイルが使われず（下の判定で利用されます）、$nocacheが&#8221;1&#8243;に書き換えられると、fastcgi cacheが使われません（ ~ \.phpディレクティブで利用されます）。</p>
<p>$supercache_fileが存在し、$supercache_uriが空でない場合は、&#8221;location ~ /wp-content/cache/supercache/${http_host}${uri}/index\.html(\.gz)?$&#8221;ディレクティブへ処理が続きます。これが<strong>B図-4</strong>の流れです。</p>
<h5>全てを受け止めるindex.php</h5>
<p>静的ファイルのチェック、WP Super Cacheのチェックが終わっても処理が続く場合は、すべてにリクエストがindex.phpへと渡され、&#8221;location ~ \.php&#8221;ディレクティブへ処理が続きます。<br />
すでにキャッシュされていて期限が有効な場合は、fastcgi cacheが使われ<strong>（B図-2）</strong>、キャッシュがなかったり、期限が切れていた場合は、FastCGI（PHP）へ処理が渡されます<strong>（B図-1）</strong>。</p>
<p>今回はステータスコード200の時は10分、404の時は1分キャッシュするように設定してあります。</p>
<h4>404がキャッシュされない</h4>
<p>目に見える記事部分のキャッシュが効いて応答が良くなると忘れてしまいがちですが、WordPressが返す404 Not Foundは無視できないくらい重い処理です。<br />
404に対してキャッシュが作られないと、存在しない記事にアクセスがくる度にPHPとMySQLが仕事をしてしまいます。</p>
<p>そこで、fastcgi cacheの設定で &#8220;fastcgi_cache_valid   404 1m;&#8221; を指定しているわけですが、そのままだとキャッシュが効ききません（WordPress 3.2.1）。<br />
調べてみると、WordPressは404の時、ヘッダーに &#8220;Cache-Control:no-cache, must-revalidate, max-age=0&#8243; を付けてレスポンスを返すことがわかりました。<br />
このヘッダーがあるのでfastcgi cacheはキャッシュを作らないようなのです。</p>
<p>もっとスマートな方法があると思いますが、今回はWordPressのソースを少しいじって対応することにしました。</p>
<p><strong>wp-includes/class-wp.php</strong></p>
<pre class="terminal">
function handle_404() {
    global $wp_query;

    if ( !is_admin() &#038;&#038; ( 0 == count( $wp_query->posts ) ) &#038;&#038; !is_404() &#038;&#038; !is_robots() &#038;&#038; !is_search() &#038;&#038; !is_home() ) {
        // Don't 404 for these queries if they matched an object.
        if ( ( is_tag() || is_category() || is_tax() || is_author() || is_post_type_archive() ) &#038;&#038; $wp_query->get_queried_object() &#038;&#038; !is_paged() ) {
            if ( !is_404() )
                status_header( 200 );
            return;
        }
        $wp_query->set_404();
        status_header( 404 );
        <span style="color:#00ffff">//nocache_headers();</span> <span style="color:#00ff00"># ここをコメントアウト</span>
    } elseif ( !is_404() ) {
        status_header( 200 );
    }
}
</pre>
<p>これで404もキャッシュされるようになりました。</p>
<h3>おわりに</h3>
<p><a href="http://2011.tokyo.wordcamp.org/"><img src="http://cloudrop.jp/wp-content/uploads/2011/11/180x150-sponsor.png" alt="WordCamp Tokyo 2011" title="WordCamp Tokyo 2011" width="180" height="150" class="alignleft size-full wp-image-1249" /></a>弊社はWordPessのイベント、<a href="http://2011.tokyo.wordcamp.org/">WordCamp 2011 Tokyo</a>に微力ながらスポンサーとして協力させて頂きました。</p>
<p>ブログにもWordPressの記事が少なく、弊社がWordPressにコミットしている感じが伝わっていないと思ったので、開催前に何とか間に合って良かったです。</p>
<h3>参考サイト</h3>
<ul>
<li><a href="http://dogmap.jp/wckobe2011/">ハイパフォーマンス WordPress サイト入門</a></li>
<li><a href="http://wpdocs.sourceforge.jp/Nginx">Nginx &#8211; WordPress Codex 日本語版</a></li>
<li><a href="http://wordpress.org/support/topic/nginx-php-fpm-php-apc-wordpress-multisite-subdirectory-wp-super-cache">WordPress › Support » nginx + php-fpm + PHP APC + WordPress multisite (subdirectory) + WP Super Cache</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://cloudrop.jp/wordpress/more_tuning_on_nginx/feed</wfw:commentRss>
		<slash:comments>21</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://cloudrop.jp/wordpress/more_tuning_on_nginx" />
	</item>
		<item>
		<title>さくらのクラウドは本当に安いのか？</title>
		<link>http://cloudrop.jp/cloud/sacloud_price?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sacloud_price</link>
		<comments>http://cloudrop.jp/cloud/sacloud_price#comments</comments>
		<pubDate>Fri, 11 Nov 2011 08:25:37 +0000</pubDate>
		<dc:creator>sekine</dc:creator>
				<category><![CDATA[クラウド]]></category>
		<category><![CDATA[さくらのクラウド]]></category>

		<guid isPermaLink="false">http://cloudrop.jp/?p=1093</guid>
		<description><![CDATA[さくらのクラウドの料金が発表になり、相対的に他のクラウドサービスより安いと言われています。ところが、実際にAWSなどから置き換えるような用途を考えた場合に、今までの感覚でプランを選ぼうとすると、本当に安いのか疑問になる部 [...]]]></description>
			<content:encoded><![CDATA[<style>
<!--
table#sacloud_price {
  border-collapse: separate;
  border-spacing: 2px 2px;
  empty-cells: show;
}
table#sacloud_price th {
  padding: 5px;
  font-weight: bold;
  text-align: right;
  padding-right: 1em;
}
table#sacloud_price td {
  padding: 5px;
  border: 1px solid #999;
  text-align: center;
}
table#sacloud_price td.result {
  width: 11em;
}
table#sacloud_price td.c {
  text-align: right;
  font-size: 110%;
}
-->
</style>
<p>さくらのクラウドの料金が発表になり、相対的に他のクラウドサービスより安いと言われています。ところが、実際にAWSなどから置き換えるような用途を考えた場合に、今までの感覚でプランを選ぼうとすると、本当に安いのか疑問になる部分が出てきたので、シミュレーションをしながら考えてみました。</p>
<h3 style="margin-top:1em;">バランスが悪い？CPUがネック？</h3>
<p>アプリケーションサーバーの用途などCPUパワーが必要なケースを考えます。<br />
例えば、4コアは欲しいけどメモリは少なくてもいい場合、4コアの最低プランであるプラン7（メモリ16GB）を選択しないといけなくなります。これはAWSでいうCPUに重みを置いたc1.mediumインスタンスのようなプランがないためで、バランスが悪くオーバースペックになってしまいますし、価格も高めになります。</p>
<p>しかし、パフォーマンスは使われているサーバーのスペックやリソース配分が影響を与えるので、元々の能力が違う上でコア数の多寡だけを取り上げても判断材料にはなりません。</p>
<p>実際多くの方が、先行サービスのさくらのVPSとAWS（EC2）のベンチマークを行なっていて、結果は概ねさくらのVPSが優れているというものです。</p>
<ul>
<li><a href="http://d.hatena.ne.jp/nakakoh/20110303/1299136337">unixbench on AWS micro instance &amp; さくらのVPS &#8211; Never forget your first resolution.</a></li>
<li><a href="http://tanaka.sakura.ad.jp/2011/02/vps-sakura-saases-serversman.html">格安の低価格ＶＰＳを比較する &#8211; さくらインターネット創業日記</a></li>
<li><a href="http://d.hatena.ne.jp/rx7/20100722/p1">Amazon EC2性能検証！気になるパフォーマンスをインスタンスタイプやリージョン毎に計測・比較してみた &#8211; RX-7乗りの適当な日々</a></li>
</ul>
<p>また、EC2で定義されているECUというCPUの単位は、以下のようなものです。</p>
<blockquote><p>特定のインスタンスに配分されている CPU 量は、これらの EC2 Compute Unit で明示されます。当社はいくつかのベンチマークとテストを使用して、EC2 Compute Unit のパフォーマンスの安定性と予測可能性を管理します。1つの EC2 Compute Unit は、1つの 1.0-1.2 GHz 2007 Opteron または 2007 Xeon プロセッサの CPU 能力に等しい能力を提供します。</p>
<div style="text-align:right;">引用元 <a href="http://aws.amazon.com/jp/ec2/instance-types/">Amazon EC2 インスタンスタイプ</a>より</div>
</blockquote>
<p>c1.mediumインスタンス（5 ECU（2.5 ECU × 2仮想コア））の場合は2007 Opteronの2.5-3.0GHz × 2仮想コア相当のパフォーマンスだということになります。</p>
<p>この辺りを考慮にいれて、コア数に振り回されないように、実際のアプリケーションでテストを行って最適なプランを選ぶことになりそうです。<br />
現段階では安いとも高いとも言えないところです。</p>
<h3 style="margin-top:1em;">メモリ特化の用途には安い！ではディスクは？</h3>
<p>DBサーバーやキャッシュサーバーの用途などメモリが多く必要なケースを考えます。<br />
例えばmemcachedサーバーの用途でメモリが8GBあればCPUもディスク容量も問わないケースだと、プラン5になりAWSのm1.largeインスタンスと比べて半額で済みます。</p>
<p>一方、m1.largeインスタンス並のディスク容量を追加しようとすると、プラン5+750GBで26,150円と高くなります。<br />
これはAWSのディスクが安いとも言えるので、大容量のストレージが必要な場合はさくらのクラウドは安いとは言えないでしょう。</p>
<p>実際、DBサーバーの用途で8GBのメモリを積んだサーバーを運用する場合、850GBものデータを扱うことはパフォーマンスを考えるとありえないので、通常のケースでは問題にならないと思っています。</p>
<h3 style="margin-top:1em;">トラフィック特化の用途では？</h3>
<p>大容量コンテンツの配信やストリーミングサービスだけでなく、単純にアクセス数が多いサービスだと転送量に対する課金が全体の半分くらいに達することもあります。<br />
さくらのクラウドは転送量やリクエスト数に応じて従量課金されることがないので、トラフィックに関しては安いと言えます。</p>
<h3 style="margin-top:1em;">スペック・料金シミュレータ</h3>
<p>上記を踏まえて、スペックと料金のシミュレータを作って見ました。<br />
利用したいスペックを選択するとマッチする最低ラインのプランが決定されます。<br />
利用したいスペックよりも表記上オーバースペックの場合、該当のスペックが<span style="color:red">赤く</span>なります。<br />
（※ 料金表記などに誤りがある場合もありますのでご了承の上、ご利用下さい。）</p>
<p><span style="font-weight:bold;">利用したいスペック</span><br />
<select name="core" id="core"></select>
<select name="memory" id="memory"></select>
<select name="disk" id="disk"></select>
<table id="sacloud_price">
<tr>
<th>選択されたプラン</th>
<td id="plan_name"></td>
</tr>
<tr>
<th>CPU</th>
<td id="cpu_name" class="result"></td>
</tr>
<tr>
<th>メモリ</th>
<td id="memory_name" class="result"></td>
</tr>
<tr>
<th>ディスク</th>
<td id="disk_name" class="result"></td>
</tr>
<tr>
<th>月額料金</th>
<td id="monthly_price" class="result c"></td>
</tr>
<tr>
<th>日割料金</th>
<td id="daily_price" class="result c"></td>
</tr>
</table>
<p><script type="text/javascript" src="/fragment/sacloud_price.js"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://cloudrop.jp/cloud/sacloud_price/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://cloudrop.jp/cloud/sacloud_price" />
	</item>
		<item>
		<title>さくらのクラウドまとめメモ</title>
		<link>http://cloudrop.jp/cloud/sacloud1107?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sacloud1107</link>
		<comments>http://cloudrop.jp/cloud/sacloud1107#comments</comments>
		<pubDate>Mon, 07 Nov 2011 14:42:56 +0000</pubDate>
		<dc:creator>sekine</dc:creator>
				<category><![CDATA[クラウド]]></category>
		<category><![CDATA[勉強会]]></category>
		<category><![CDATA[さくらのクラウド]]></category>

		<guid isPermaLink="false">http://cloudrop.jp/?p=1041</guid>
		<description><![CDATA[本日の第4回さくらの夕べで明らかになった情報のメモを整理します。 ほとんどの情報は明日のプレスリリースで公開される情報です。 リリース日 2011年11月15日 15:00に石狩データセンターがオープンし、そのタイミング [...]]]></description>
			<content:encoded><![CDATA[<style>
<!--
table#sakuraPrice { border-top: 1px solid #222;border-left: 1px solid #222;border-spacing:0;empty-cells:show; margin-bottom:1em;}
table#sakuraPrice th{ font-weight:bold; text-align:center; background-color:#eee; border-bottom: 1px solid #222;border-right: 1px solid #222;padding: 2px 5px; }
table#sakuraPrice td{ text-align:center; border-bottom: 1px solid #222;border-right: 1px solid #222; padding: 2px 5px;}
table#sakuraPrice td.c{ text-align:right;}
-->
</style>
<p>本日の第4回さくらの夕べで明らかになった情報のメモを整理します。<br />
ほとんどの情報は明日のプレスリリースで公開される情報です。</p>
<h3 style="margin-top:1em;">リリース日</h3>
<p>2011年11月15日 15:00に石狩データセンターがオープンし、そのタイミングでリリース予定とのこと。申込みページはこちら[<a href="http://cloud.sakura.ad.jp/">さくらのクラウド</a>] になる予定。</p>
<h3 style="margin-top:1em;">さくらのクラウド プラン別価格表</h3>
<table id="sakuraPrice">
<tr>
<th>プラン名</th>
<th>CPU</th>
<th>メモリ</th>
<th>ディスク</th>
<th>月額料金</th>
<th>日割料金</th>
</tr>
<tr>
<td>プラン1</td>
<td>仮想1コア</td>
<td>2GB</td>
<td rowspan="13">20GB</td>
<td class="c">¥2,500</td>
<td class="c">¥126</td>
</tr>
<tr>
<td>プラン2</td>
<td>仮想1コア</td>
<td>3GB</td>
<td class="c">¥3,750</td>
<td class="c">¥189</td>
</tr>
<tr>
<td>プラン3</td>
<td>仮想2コア</td>
<td>4GB</td>
<td class="c">¥5,200</td>
<td class="c">¥260</td>
</tr>
<tr>
<td>プラン4</td>
<td>仮想2コア</td>
<td>6GB</td>
<td class="c">¥7,800</td>
<td class="c">¥390</td>
</tr>
<tr>
<td>プラン5</td>
<td>仮想3コア</td>
<td>8GB</td>
<td class="c">¥10,400</td>
<td class="c">¥520</td>
</tr>
<tr>
<td>プラン6</td>
<td>仮想3コア</td>
<td>12GB</td>
<td class="c">¥15,600</td>
<td class="c">¥780</td>
</tr>
<tr>
<td>プラン7</td>
<td>仮想4コア</td>
<td>16GB</td>
<td class="c">¥20,800</td>
<td class="c">¥1,040</td>
</tr>
<tr>
<td>プラン8</td>
<td>仮想4コア</td>
<td>24GB</td>
<td class="c">¥31,200</td>
<td class="c">¥1,560</td>
</tr>
<tr>
<td>プラン9</td>
<td>仮想6コア</td>
<td>32GB</td>
<td class="c">¥41,500</td>
<td class="c">¥2,080</td>
</tr>
<tr>
<td>プラン10</td>
<td>仮想8コア</td>
<td>48GB</td>
<td class="c">¥52,800</td>
<td class="c">¥2,640</td>
</tr>
<tr>
<td>プラン11</td>
<td>仮想10コア</td>
<td>64GB</td>
<td class="c">¥64,000</td>
<td class="c">¥3,200</td>
</tr>
<tr>
<td>プラン12</td>
<td>仮想12コア</td>
<td>96GB</td>
<td class="c">¥81,600</td>
<td class="c">¥4,080</td>
</tr>
<tr>
<td>プラン13</td>
<td>仮想12コア</td>
<td>128GB</td>
<td class="c">¥96,000</td>
<td class="c">¥4,800</td>
</tr>
</table>
<p>上記のプランをベースにローカルネットワークで通信をする場合は仮想スイッチ（¥5,250）、ストレージを増やしたい場合は容量に応じて追加料金でディスクを増やす料金体系。<strong>転送量は込み込み</strong>なので、転送量の多いサービスはAWSなどに比べてさらに料金が圧縮できる。<br />
ベースの料金は1日〜20日までの利用は日割料金、それ以上の利用は月額料金で課金される。</p>
<h3>ロケーション</h3>
<p>さくらのクラウドのロケーションは新設の石狩データセンターになるので、在庫は潤沢（1,000台でも2,000台でも）。<br />
東京や大阪などのリージョンも要望が多ければ考える予定。<br />
クラウドとVPSや専用サーバーを同一の石狩データセンターで借りれば、レイテンシーが1ms以下で通信できるミクスチャー環境が構築できる。</p>
<h3>その他気になったこと</h3>
<h4>SSD</h4>
<p>ストレージとしてSSDやioDriveも選択できるようにする予定とのこと。手軽に利用できるようになれば、I/Oで頭を悩ませなくて済むようになりそう。</p>
<h4>オートスケール</h4>
<p>オートスケールは実装する予定はないとのこと。<br />
クラウドをコントロールするAPIが用意されるので、サードパーティーが参入できる部分。</p>
]]></content:encoded>
			<wfw:commentRss>http://cloudrop.jp/cloud/sacloud1107/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://cloudrop.jp/cloud/sacloud1107" />
	</item>
		<item>
		<title>リクエストを落とさずにnginxをアップグレードする方法とその検証</title>
		<link>http://cloudrop.jp/labs/nginx_upgrade?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=nginx_upgrade</link>
		<comments>http://cloudrop.jp/labs/nginx_upgrade#comments</comments>
		<pubDate>Mon, 23 May 2011 01:31:43 +0000</pubDate>
		<dc:creator>sekine</dc:creator>
				<category><![CDATA[サーバー]]></category>
		<category><![CDATA[実験・研究]]></category>
		<category><![CDATA[nginx]]></category>

		<guid isPermaLink="false">http://cloudrop.jp/?p=926</guid>
		<description><![CDATA[はじめに nginxは頻繁に保守されていてどんどんバージョンが上がっていく一方で、UbuntuやWindows以外ではソースコードからビルドする方法が一般的だと思います。 nginxのバージョンアップ頻度 2011/05 [...]]]></description>
			<content:encoded><![CDATA[<h3 style="margin-top:1em;">はじめに</h3>
<p><img src="http://cloudrop.jp/wp-content/uploads/2011/05/nginx_logo.png" alt="" title="nginx_logo" width="180" class="alignleft size-full wp-image-963" />nginxは頻繁に保守されていてどんどんバージョンが上がっていく一方で、UbuntuやWindows以外ではソースコードからビルドする方法が一般的だと思います。</p>
<blockquote><p>
nginxのバージョンアップ頻度</p>
<ul>
<li>2011/05/10 1.0.2</li>
<li>2011/05/03 1.0.1</li>
<li>2011/04/12 1.0.0</li>
<li>2011/04/04 0.9.7</li>
<li>2011/03/21 0.9.6</li>
</ul>
<p><a href="http://nginx.org/en/CHANGES">nginx CHANGES</a>より</p></blockquote>
<blockquote><p>
LinuxやBSDの多くのディストリビューションではNginxがパッケージリポジトリに含まれており、通常のソフトウェアインストール手法でインストールする事ができます。(Debianにおけるapt-getや、Gentooにおけるemerge、FreeBSDにおけるports、Fedora の yum、Vine Linux の apt-get など）</p>
<p>たまにこれらのパッケージは古いものであったりすることがあるので気をつけてください。最新の機能やバグ修正版を求めるなら、ソースコードからビルドすることをお勧めします。&#8230;<br />
<a href="http://wiki.nginx.org/InstallJa">http://wiki.nginx.org/InstallJa</a>より
</p></blockquote>
<p>上記のようにどのディストリビューションでもパッケージは用意されているものの、バージョンが古いことが多いですし、何よりも各機能を追加するモジュールがApache（httpd）と違ってスタティックな方式を採用しているので、用途に合わせてモジュールを追加したい場合は自分でビルドするしかありません。</p>
<p>そうすると、自分でバイナリを上書きしてアップグレードすることになります。<br />
メンテナンス時間を設けてサービスを止めて保守出来る場合はいいですが、積極的に止めることは避けたいサービスの場合、以下の方法でリクエストを止めることなくアップグレードができます。</p>
<p><a href="http://wiki.nginx.org/CommandLineJa#.E3.82.AA.E3.83.B3.E3.83.BB.E3.82.B6.E3.83.BB.E3.83.95.E3.83.A9.E3.82.A4.E3.81.A7.E6.96.B0.E3.81.97.E3.81.84.E3.83.90.E3.82.A4.E3.83.8A.E3.83.AA.E3.81.AB.E3.82.A2.E3.83.83.E3.83.97.E3.82.B0.E3.83.AC.E3.83.BC.E3.83.89.E3.81.99.E3.82.8B">オン・ザ・フライで新しいバイナリにアップグレードする</a></p>
<p>今回は、nginx0.7.67を最新版（1.0.2 2011/5/23現在）にアップグレードした時の手順の確認と結果の検証を行いました。</p>
<p><!--TOC--></p>
<h3>準備</h3>
<h4>現在稼動しているバージョンのビルドオプションを確認する</h4>
<p>-Vオプションで確認することが出来ます。</p>
<pre class="terminal">
$ /usr/local/nginx/sbin/nginx -V
nginx version: nginx/0.7.67
built by gcc 4.1.2 20080704 (Red Hat 4.1.2-48)
TLS SNI support disabled
configure arguments: --with-http_stub_status_module --with-http_ssl_module
</pre>
<p>configure argumentsがオプション部分です。<br />
サードパーティ製のモジュールを入れている場合（&#8211;add-module）は、そのモジュールが新しいバージョンのnginxに対応しているか、対応しているモジュールのバージョンがリリースされていないか、確認する必要があります。</p>
<h4>最新バージョンをビルドする</h4>
<p>先ほど確認したビルドオプションで新しいバージョンをビルドします。</p>
<pre class="terminal">
$ wget http://nginx.org/download/nginx-1.0.2.tar.gz
$ tar vfxz nginx-1.0.2.tar.gz 
$ cd nginx-1.0.2

<span style="color:#00ff00"># ここで先のオプションを使う</span>
$ ./configure --with-http_stub_status_module --with-http_ssl_module
$ make

<span style="color:#00ff00"># 成功すると./objs 以下に新しいバイナリが出来上がるので確認</span>
$ ./objs/nginx -V
nginx: nginx version: nginx/1.0.2
nginx: built by gcc 4.1.2 20080704 (Red Hat 4.1.2-50)
nginx: TLS SNI support disabled
nginx: configure arguments: --with-http_stub_status_module --with-http_ssl_module
</pre>
<h4>現行の設定ファイルのままで問題がないか確認する</h4>
<p>仕様の変更などで利用できなくなるディレクティブなどがあるかもしれません。現行の設定ファイルでconfig testが通るかチェックします。</p>
<pre class="terminal">
$ sudo ./objs/nginx -t -c /usr/local/nginx/conf/nginx.conf
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
</pre>
<h3>アップグレード</h3>
<h4>バイナリをコピーする</h4>
<p>単純にコピーnginxファイルを上書きするか、make installで上書きします。</p>
<pre class="terminal">
$ sudo cp objs/nginx /usr/local/nginx/sbin/nginx
</pre>
<p>or</p>
<pre class="terminal">
$ sudo make install
</pre>
<h4>プロセスを確認する</h4>
<p>いよいよ本題です。現在動いているnginxのマスタープロセスのpidを確認します。</p>
<h5>psコマンド確認する方法</h5>
<pre class="terminal">
$ ps aux |grep nginx
<strong>root      5559  0.0  0.0  40976  1000 ?        Ss   16:36   0:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf</strong>
nginx     5560  0.0  0.2  42572  3052 ?        S    16:36   0:00 nginx: worker process                                          
nginx     5561  0.0  0.2  42572  3044 ?        S    16:36   0:00 nginx: worker process                                          
nginx     5562  0.0  0.2  42572  2992 ?        S    16:36   0:00 nginx: worker process                                          
nginx     5564  0.0  0.2  42572  2940 ?        S    16:36   0:00 nginx: worker process  
</pre>
<h5>pidファイルで確認する方法</h5>
<p>nginx.confにpidディレクティブを設定している場合は設定したパスにpidファイルがあります。</p>
<pre class="terminal">
$ cat /var/run/nginx.pid;
5559
</pre>
<p>pidは<strong>5559</strong>です。<br />
ワーカープロセス数は、confファイル&quot;worker_processes&quot;の設定に依存します。</p>
<h4>新しいバイナリを実行する（USR2シグナル）</h4>
<p>USR2シグナルをマスタープロセスに送ります。</p>
<pre class="terminal">
$ sudo kill -USR2 5559
</pre>
<p>すると、古いバージョンのプロセスと新しいバージョンのプロセスが共存する状態になります。</p>
<pre class="terminal">
$ ps aux |grep nginx
root      5559  0.0  0.0  40976  1068 ?        Ss   16:36   0:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
nginx     5560  0.0  0.2  42572  3052 ?        S    16:36   0:00 nginx: worker process                                          
nginx     5561  0.0  0.2  42572  3044 ?        S    16:36   0:00 nginx: worker process                                          
nginx     5562  0.0  0.2  42572  2992 ?        S    16:36   0:00 nginx: worker process                                          
nginx     5564  0.0  0.2  42572  2940 ?        S    16:36   0:00 nginx: worker process                                          
root      7962  2.0  0.2  41024  3084 ?        S    19:29   0:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
nginx     7963  0.0  0.2  42732  3060 ?        S    19:29   0:00 nginx: worker process                                          
nginx     7964  0.0  0.2  42732  2860 ?        S    19:29   0:00 nginx: worker process                                          
nginx     7965  0.0  0.2  42732  2860 ?        S    19:29   0:00 nginx: worker process                                          
nginx     7966  0.0  0.2  42732  2852 ?        S    19:29   0:00 nginx: worker process 
</pre>
<h4>古いバージョンのワーカーを止める（WINCHシグナル）</h4>
<p>WINCHシグナルを古いマスタープロセスに送ります。</p>
<pre class="terminal">
$ sudo kill -WINCH 5559
</pre>
<p>すると、既に受け持っているリクエストの処理が終わり次第、古いワーカープロセスが順次終了していきます。古いプロセスはマスタープロセスだけになり、リクエストは新しいワーカープロセスが受け持っています。</p>
<pre class="terminal">
ps aux |grep nginx
root      5559  0.0  0.0  40976  1072 ?        Ss   16:36   0:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
root      7962  0.0  0.2  41024  3084 ?        S    19:29   0:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
nginx     7963  0.0  0.2  42732  3060 ?        S    19:29   0:00 nginx: worker process                                          
nginx     7964  0.0  0.2  42732  2860 ?        S    19:29   0:00 nginx: worker process                                          
nginx     7965  0.0  0.2  42732  2860 ?        S    19:29   0:00 nginx: worker process                                          
nginx     7966  0.0  0.2  42732  2852 ?        S    19:29   0:00 nginx: worker process  
</pre>
<h4>古いバージョンのマスタープロセスを止める（QUITシグナル）</h4>
<p>QUITシグナルを古いマスタープロセスに送ります。</p>
<pre class="terminal">
$ sudo kill -QUIT 5559
</pre>
<p>古いマスタープロセスが終了し、新しいマスタープロセスとワーカープロセスだけになりました。</p>
<pre class="terminal">
$ ps aux |grep nginx
root      7962  0.0  0.2  41024  3084 ?        S    19:29   0:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
nginx     7963  0.0  0.2  42732  3060 ?        S    19:29   0:00 nginx: worker process                                          
nginx     7964  0.0  0.2  42732  2860 ?        S    19:29   0:00 nginx: worker process                                          
nginx     7965  0.0  0.2  42732  2860 ?        S    19:29   0:00 nginx: worker process                                          
nginx     7966  0.0  0.2  42732  2852 ?        S    19:29   0:00 nginx: worker process 
</pre>
<h3>検証</h3>
<h4>検証方法</h4>
<p><a href="http://www.acme.com/software/http_load/">http_load</a>を使ってドキュメントルートに置いたテキストファイルをアップグレード作業中にクライアントから毎秒10リクエスト行う。</p>
<h4>結果</h4>
<p>作業中の2分間、1199リクエストが全て正常に終了したので、問題なくアップグレードができたと思われます。</p>
<pre class="terminal">
./http_load -rate 10 -seconds 120  -verbose url_file
--- 60.0062 secs, 600 fetches started, 599 completed, 1 current
--- 120.006 secs, 1200 fetches started, 1199 completed, 1 current
1199 fetches, 1 max parallel, 3597 bytes, in 120.006 seconds
3 mean bytes/connection
9.99115 fetches/sec, 29.9735 bytes/sec
msecs/connect: 0.417418 mean, 0.717 max, 0.248 min
msecs/first-response: 0.353556 mean, 0.605 max, 0.253 min
HTTP response codes:
  code 200 -- 1199
</pre>
]]></content:encoded>
			<wfw:commentRss>http://cloudrop.jp/labs/nginx_upgrade/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://cloudrop.jp/labs/nginx_upgrade" />
	</item>
		<item>
		<title>第3回 MongoDB勉強会 ダイジェスト</title>
		<link>http://cloudrop.jp/mongodb/3rd_digest?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=3rd_digest</link>
		<comments>http://cloudrop.jp/mongodb/3rd_digest#comments</comments>
		<pubDate>Thu, 19 May 2011 06:57:14 +0000</pubDate>
		<dc:creator>sekine</dc:creator>
				<category><![CDATA[MongoDB]]></category>
		<category><![CDATA[勉強会]]></category>

		<guid isPermaLink="false">http://cloudrop.jp/?p=857</guid>
		<description><![CDATA[「第3回 MongoDB 勉強会 in Tokyo」 : ATND 先週土曜日（2011年5月14日）にフューチャーアーキテクトさんのセミナールームにて行われたMongoDBの勉強会に行ってきました。 MongoDBの仕 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://cloudrop.jp/wp-content/uploads/2011/05/mongodb_logo.png"><img src="http://cloudrop.jp/wp-content/uploads/2011/05/mongodb_logo.png" alt="mongoDB" title="mongodb_logo" width="244" height="125" class="alignleft size-full wp-image-872" /></a><br />
<a href="http://atnd.org/events/15305">「第3回 MongoDB 勉強会 in Tokyo」 : ATND</a><br />
先週土曜日（2011年5月14日）にフューチャーアーキテクトさんのセミナールームにて行われたMongoDBの勉強会に行ってきました。<br />
<br clear="all"/><br />
MongoDBの仕様・機能などの体系的な話からチューニングの話、開発に利用する話、プロダクションとして運用している話と、バランスよくまとまっていてとても勉強になりました。<br />
RDBとの違いや特有の挙動をきちんと把握して利用すれば、十分プロダクションで利用出来るというビジョンが見えました。</p>
<p>詳細は各発表者の方のスライドを見るとわかると思いますが、当日会場でメモしたものでダイジェスト的にまとめました。<br />
MongoDB勉強会は毎月開催（予定）しているそうなので、興味を持たれた方は是非参加して見てください。<br />
MongoDBコミュニティー：<a href="http://groups.google.com/group/mongodb-jp">MongoDB JP | Google グループ</a></p>
<p><!--TOC--></p>
<h3>【発表1】MongoDB全機能解説1</h3>
<p>MongoDB特有の仕様や機能など、プロダクションで使う場合には特に注意が必要な部分を中心に説明されていました。</p>
<div style="width:425px" id="__ss_7960564"> <strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/doryokujin/mongodb1" title="MongoDB全機能解説1">MongoDB全機能解説1</a></strong> <iframe src="http://www.slideshare.net/slideshow/embed_code/7960564" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
<div style="padding:5px 0 12px"> View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/doryokujin">Takahiro Inoue</a> </div>
</p></div>
<h4>ロック</h4>
<p>Read/Writeの各オペレーション時に<strong>DBに対してロック</strong>がかかる。<br />
MongoDBをフロントエンドで使う場合、DBがロックして応答が返って来なくなるなどの問題が起きる可能性があるので、時間がかかる処理には注意が必要とのこと。</p>
<p>実際、単体のRead/Writeは十分高速でロックの待ち時間で問題が起こることはないが、複数のWrite処理をアトミックで行なったり（{atomic: ture}）、MapReduceで重い処理をさせるケース（ロックはかからないが処理が重いので）が問題になる。</p>
<h4>mongos</h4>
<p>mongosサーバーは協調する複数のmongodサーバーがある場合、それを一つのクラスターとして扱うためのルーティングサーバーで、それ自体ではストレージする機能はない。<br />
アプリケーションは複数あるmongodサーバーの中でどれががマスターでどれがスレーブなのかを知らなくてもmongosサーバに問い合わせればいい。</p>
<h4>database</h4>
<p> 32bit環境ではDBサイズが2.5GBまで扱えないので、<strong>要64bit環境</strong>とのこと。<br />
参考：<a href="http://blog.mongodb.org/post/137788967/32-bit-limitations">32-bit limitations</a></p>
<h4>BSON</h4>
<p>データはBSONという形式で保存されている。データ型が複数あり、どのデータ型で保存されるのかはドライバーに依存する。<br />
→ 例えば、PHPの場合はMongoInt32やMongoInt64などのデータ型用のクラスが用意されてる。<br />
オブジェクト内の順序もみているので、順番が入れ替わるだけで別のオブジェクトととされてしまう。<br />
→ { &#8216;key1&#8242;: &#8216;value1&#8242;, &#8216;key2&#8242;: &#8216;value2&#8242; } ≠  { &#8216;key2&#8242;: &#8216;value2&#8242;, &#8216;key1&#8242;: &#8216;value1&#8242; }</p>
<h4>Capped Collection</h4>
<p>サイズを指定してCollectionを作成するとCapped Collectionになる。<br />
サイズが固定なのでサイズを越えた場合は古いものから自動的に削除される。<br />
とにかく書き込みが速い。でも削除できない。<br />
 _idにすらindexがつかない。indexを張ることもできるが遅くなる（それでも速い方）。<br />
 shardingすることはできない。<br />
 用途 → ロギング（ディスクサイズを圧迫しない）<br />
 　　 → キャッシング<br />
 　　 → MapReduceの一時的なCollectinとして</p>
<h4>Insert周り</h4>
<h5>Bulk Insert</h5>
<p>複数のdocumentを配列に入れて一括でインサートする「Bulk Insert」が速い。<br />
ただ、どのくらいのサイズまでが最適なのかはスペック依存で、経験上16MBを超えるとエラーが出るそう。</p>
<h5>fire and forget</h5>
<p>インサートはデフォルトでは<strong>データベースからの応答を待たない</strong>。<br />
応答を確認するには、各種ドライバーでインサート時に応答を待つ処理を明示的にオプションとして指定する必要がある。<br />
→ PHPではarray(&#8216;safe&#8217;=>true)</p>
<h5>トランザクション</h5>
<p>RDBのように複数のオペレーションをトランザクション処理することは出来ないので、連続インサートする場合、途中でエラーになっても一連のインサートを<strong>ロールバックすることは出来ない</strong>。</p>
<h5>getLastErrorメソッド</h5>
<pre class="terminal">db.getLastError();</pre>
<p>でオペレーションの最後に起こったエラーがわかるので、このメソッドは重要。</p>
<h5>fsyncコマンド</h5>
<p>メモリ上のデータを強制的にストレージにフラッシュするコマンド。</p>
<pre class="terminal">db.runCommand({fsync:1});</pre>
<p>fsyncは自動的に60秒に1回走るようになっていて、mongod起動時に、&#8211;syncdelayオプションで変更可能だが10genとしては非推奨とのこと。<br />
つまり、<strong>最長60秒間に行われたデータの更新は喪失する可能性</strong>がある。</p>
<h5>Journaling(v1.7.5)</h5>
<p>オペレーション前にJournalingファイルに保存し、オペレーションに失敗した場合、次回実行される。<br />
100ms毎にジャーナリングされる。つまり、100ms間のオペレーションは喪失する可能性がある仕様。</p>
<h4>Query</h4>
<h5>printjson</h5>
<p>シェル（mongo）でデータを確認するときには</p>
<pre class="terminal">
db.collection.find().<strong>forEach(printjson)</strong>;
</pre>
<p>とするとJSON形式にフォーマットされ見やすくなる。</p>
<h5>入れ子</h5>
<p>入れ子になったオブジェクトをサブオブジェクト形式でfindする場合は、完全に一致したオブジェクトでないと取得できない。<br />
サブオブジェクト内のあるキーだけを検索対象としたい場合は、dot notation形式({author.name: &#8216;Jane&#8217;})で問い合わせる。  </p>
<pre class="terminal">
var doc = { title: 'タイトル', body: '本文', author: { first_name: '太郎', family_name: '山田'} };
db.collection.insert(doc);
db.collection.find({author.first_name: '太郎'}); //◯ヒットする
db.collection.find({author: { first_name: '太郎'} }); //×ヒットしない
</pre>
<h4>Update</h4>
<h5>Update</h5>
<p>デフォルトでは<strong>最初にヒットしたオブジェクトのみを更新</strong>する。<br />
→ ヒットした全てを更新対象としたい場合は{ &#8216;multi&#8217;: true } オプションを付ける。<br />
→ 複数の更新をアトミックに行うには { &#8216;$atomic&#8217;: true } オプションを付ける。</p>
<h5>Save</h5>
<p>同じ_idのオブジェクトがあれば自動的にドキュメント全体を更新する。</p>
<h5>modifier オペレーション</h5>
<p>アップデートのオプションとして$inc/$set/$push/$popなどのオペレーションがある。<br />
modifierオペレーションを指定しないでアップデートを行うとオブジェクト（ドキュメント）をまるごと上書きするのでとても怖い。</p>
<h5>in-place update</h5>
<p>データサイズが変わらない更新の場合は高速。（例えば、{ &#8216;$inc&#8217;; { key: 1 } } など。）<br />
また、データの更新を高速に行うため、インサートされた際に実データサイズよりも大きめにストレージを使って保存している。<br />
→ 多少のサイズの増加も高速に更新出来る。逆に言うと無駄にストレージを使う。</p>
<h5>Snapshot</h5>
<p>MongoDBはデータサイズが大きく増えた場合、データベースファイルの新しい領域にデータを格納し直す。この瞬間にfind()すると<strong>同じドキュメントが2個取れたりする可能性がある</strong>。<br />
find()で取り出した複数のドキュメントをupdate()するようなケースでは問題になるので、重複を排除して結果を返すsnapshot()を使う。</p>
<pre class="terminal">db.collection.find({name:'Jane'}).<strong>snapshot()</strong>;</pre>
<h4>Indexについて</h4>
<h5>B-Tree indexes</h5>
<p>インデックスを生成するオペレーションensureIndex()はデフォルトではDBをブロックする。<br />
<strong>{ background: true } オプションを付けるとロックしない</strong>ので、基本的にこれを必ず付けること。</p>
<pre class="terminal">db.collection.ensureIndex({name: 1}, {background:true});</pre>
<p>参考：<a href="http://www.mongodb.org/display/DOCS/Indexing+as+a+Background+Operation">Indexing as a Background Operation</a></p>
<h5>Sparse Index(v 1.7.4)</h5>
<p>インデックスの設定されたフィールドを持っていないドキュメントは無視される。<br />
→ コレクション全体的の中でSparse Indexに設定されたフィールドに値を持っているドキュメントがが少ない場合にパフォーマンスが出るインデックス。</p>
<h5>Unique Index</h5>
<p>インデックスを張ったキーが存在しないドキュメントを登録するとnullが挿入され、nullがユニークの対象となる。<br />
→ インデックスを張ったキーが存在しないドキュメントをもう一つ登録すると重複エラーになる。<br />
ただし、<strong>sharding環境では重複する可能性がある</strong>。</p>
<h4>Replication</h4>
<ul>
<li>Master-Slave：一般的なM/S構成</li>
<li>Replica Sets：自動フェイルオーバ機能などを提供</li>
</ul>
<h5>Master-Slave</h5>
<p>Master->Slaveは非同期でコピーされる。<br />
mongodをそれぞれ、&#8211;master、 &#8211;slaveを付けて起動するだけ。<br />
→ slaveには直接書き込みできない。（mongos経由）</p>
<p>同期は各データベースがそれぞれローカルに自動的に作成するoplog(operation log)コレクションを介して行われる。</p>
<ol>
<li>スレーブ（セカンダリ）はマスターのoplogを監視している。　
<li>マスター（プライマリ）は更新系のオペレーションをoplogに書き込み、自分のデータベースに実行する。</li>
<li>スレーブはマスターとの差分のoplogを自分のoplogへコピーし、そのオペレーションを自分のデータベースに実行する。</li>
</ol>
<p>MySQLのバイナリログと同じようなイメージ。</p>
<h5>Replica Sets</h5>
<p>3台〜12台で構成でき、自動フェイルオーバー機能／自動リカバリ機能を持つ。<br />
ノードタイプには、Standard（データあり。Primaryになれる。）、Passive（データあり。Primaryになれない。）、Arbiter（データなし。投票権はある。）がある。<br />
フェイルオーバーは、起動時に設定するprimary値の高いもの ＞ 最も新鮮なデータを持っているもの ＞ 投票数の多いもの の順で順番付けされ、決定したセカンダリーがプライマリになる。<br />
ダウンしているサーバーが多かったり、最終更新データが古すぎたりするとどのセカンダリーもプライマリにならないことがある。→ 手動で対応。</p>
<h3>【発表2】ソーシャルアプリのプロトタイプ制作にMongoDBを活用</h3>
<div style="width:425px" id="__ss_7948933"> <strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/fungoing/mongodb-7948933" title="ソーシャルアプリのプロトタイプ制作にMongoDBを活用 ">ソーシャルアプリのプロトタイプ制作にMongoDBを活用 </a></strong> <iframe src="http://www.slideshare.net/slideshow/embed_code/7948933" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
<div style="padding:5px 0 12px"> View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/fungoing">fungoing</a> </div>
</p></div>
<h4>Sleepy.Mongoose</h4>
<p>アプリケーションとデータベースの通信は<a href="http://www.snailinaturtleneck.com/blog/2010/02/22/sleepy-mongoose-a-mongodb-rest-interface/">Sleepy.Mongoose</a>（pythonで実装されたRestインターフェース）を利用して、curlで実装している。<br />
→ Sleepy.Mongooseにはcount()が実装されていないのでforkしたものをGitHubに置いてあるとのこと。<br />
<a href="https://github.com/bibrost/sleepy.mongoose">bibrost / sleepy.mongoose</a></p>
<h4>Cray Model</h4>
<p>自動車開発のプロセスで粘土細工（Cray Model）で何度も何度も型を作ってから金型を作るように、プロトタイプの開発がしたい。<br />
RDBのようにスキーマを定義して、チーム内で変更を共有して、不整合が起きないようにCREATE TABLEしたりALTER TABLEしたりするのは面倒。<br />
MongoDBはアプリケーション上でいくらでもデータ構造を変更できるので、ソースさえ共有すればよく、途中でドキュメント構造が変わっても、手を止めることなくcollection名を変えるだけでいい。→まさに粘土細工のように失敗したら壊してまた作ればいい。</p>
<h4>なぜ最終的にRDBにするのか</h4>
<ul>
<li>MongoDBを保守できるエンジニアがいない。</li>
<li>MongoDBをクリティカルなプロダクションで使うことが難しい（トランザクションがない）。</li>
</ul>
<h3>【発表3】MongoDBチューニング 〜スロークエリ撲滅までの道筋〜</h3>
<div style="width:425px" id="__ss_7960592"> <strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/matsuou1/20110514-mongo-db" title="20110514 mongo dbチューニング">20110514 mongo dbチューニング</a></strong> <iframe src="http://www.slideshare.net/slideshow/embed_code/7960592" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
<div style="padding:5px 0 12px"> View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/matsuou1">Yuichi Matsuo</a> </div>
</p></div>
<h4>オプティマイザ</h4>
<p>RDBで多く採用されている一般的なオプティマイザは統計情報を元にしたコストベースで、本番環境と検証環境で統計情報が異なっていると実行計画が違ってきたり、悪い実行計画も行われる。<br />
MongoDBのオプティマイザはコストベースではなく、新しいクエリー実行がある度に計算する仕様。（オーバーヘッド・CPUコストが高いが、最適な計画が行われる）</p>
<ul>
<li>新しいクエリー実行時に複数の実行計画を並行に実施して一番速いのを採用・学習し、他のものは途中で止める。</li>
<li>100回データ更新が行われ時やindexが変更された時、最初の評価時からスキャンするドキュメントが大きく増えた場合（nscannedの値が10倍になったら）再評価を実施する。</li>
</ul>
<h4>explainメッソド</h4>
<p>explain()で実行計画を確認できる。</p>
<pre class="terminal">db.collection.find(query).explain();</pre>
<p>勘所としてはBasicCursorは全件スキャンなので<strong>×</strong>、millisが長いと処理時間が遅いので<strong>×</strong>、nscannedが多いとスキャン対象のドキュメント数が多いので<strong>×</strong>、など。</p>
<h4>スロークエリの特定</h4>
<li>slowmsオプションをつけて起動する。<br />
→ ログファイルに保存される。</li>
<li>db.setProfilingLevel()を実行する。<br />
→ db.system.profileコレクションに保存されていく。（デフォルト100ms）</li>
<li>db.currentOp()を実行する<br />
→ 現在実行中のクエリが見られる。</li>
<h4>複合インデックス</h4>
<p>順序が大事。<br />
db.collection.find({x: 10}).sort({ y: 1});でも { x: 1, y: 1 }のインデックスが使われる。</p>
<h4>hintメソッド</h4>
<p>hintメソッドを使うと特定のインデックスを使わせることができる。<br />
インデックス設定されていれば、<br />
db.collection.find().hint({uid:1}); より db.collection.find().hint({uid:1, path:1}); の方がより絞られて高速になる。</p>
<h4>mongostat</h4>
<p>mongoやmongodなどと一緒にインストールされるmongostatコマンド。<br />
ロックされている割合やインデックスが利用されなかった割合などの統計情報が確認できる。</p>
<h4>killメソッド</h4>
<p>db.killOp(opId)で実行中のクエリをkillできる。</p>
<h3>【発表4】MongoDBを使用したモバイルゲーム開発</h3>
<div style="width:425px" id="__ss_7962043"> <strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/ygenki/mongodb-7962043" title="MongoDBを使用したモバイルゲーム開発">MongoDBを使用したモバイルゲーム開発</a></strong> <iframe src="http://www.slideshare.net/slideshow/embed_code/7962043" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
<div style="padding:5px 0 12px"> View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/ygenki">ygenki</a> </div>
</p></div>
<h4>東京ガールズスナップの構成</h4>
<p>Java（appサーバー2台）+ MongoDB（Replica Setで3台）で運用している。<br />
MongoDBに対応したSpring Data Documentを利用して開発した。</p>
<h4>MongoDBで良かったこと</h4>
<p>階層型にデータが持てるのでkey-value的に使えた。<br />
→ ドキュメント内に配列を持つことができるので、RDBのようなリレーションや連結などしなくても直接$pushや$popで複数のデータを出し入れできる。</p>
<p>バイナリデータが保存しやすい<br />
当初の想定していた利用法ではなかったが画像データのキャッシュストレージとして利用できた。<br />
→ 4MBまでだったらバイナリデータをそのまま格納できる。</p>
<h4>MongoDBが問題になったこと</h4>
<ul>
<li>オペレーションミスが大変なことになる（update時に$setで指定しないと全部上書きする）</li>
<li>アプリ経由ではなくコンソールでデータを更新したらデータ型が変わってしまった（intがdoubleに）</li>
<li>ドキュメント設計の最適化に時間がかかった（ベストプラクティスがわからない）</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://cloudrop.jp/mongodb/3rd_digest/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://cloudrop.jp/mongodb/3rd_digest" />
	</item>
		<item>
		<title>ATNDのスケジュールを1発でiPhoneに取り込む方法</title>
		<link>http://cloudrop.jp/labs/webcal_atnd?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=webcal_atnd</link>
		<comments>http://cloudrop.jp/labs/webcal_atnd#comments</comments>
		<pubDate>Mon, 02 May 2011 09:11:31 +0000</pubDate>
		<dc:creator>sekine</dc:creator>
				<category><![CDATA[実験・研究]]></category>
		<category><![CDATA[ATND]]></category>
		<category><![CDATA[iCal]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Webcal]]></category>

		<guid isPermaLink="false">http://cloudrop.jp/?p=758</guid>
		<description><![CDATA[ATNDのAPIを利用してワンクリックで自分の登録しているイベントをiPhoneのカレンダーに取り込めます。 通常のAPIへのアクセス方法を以下のように変更して、iPhoneのsafariでアクセスするだけです。 htt [...]]]></description>
			<content:encoded><![CDATA[<style>
<!--
#atnd_url_ex{
  margin: 0 auto 15px auto;
  text-align:center;
  width: 90%;
  padding: 20px 0;
  border: 1px dashed #444;
  background-color: #f4ffce;
}
#atnd_webcal{
  margin: 0 auto;
  text-align:center;
  width: 30em;
  padding: 20px 0;
  border: 1px solid #666;
  background-color: #dffcf9;
}
-->
</style>
<p>ATNDのAPIを利用してワンクリックで自分の登録しているイベントをiPhoneのカレンダーに取り込めます。</p>
<p>通常のAPIへのアクセス方法を以下のように変更して、iPhoneのsafariでアクセスするだけです。</p>
<div id="atnd_url_ex">
<strong>http://</strong>api.atnd.org/events/?nickname=ms76&#038;count=100&#038;format=ics<br />
↓<br />
<strong style="color:red;">webcal://</strong>api.atnd.org/events/?nickname=ms76&#038;count=100&#038;format=ics
</div>
<p>すると、カレンダーに取り込む（照会する）かを聞かれるので</p>
<p><a href="http://cloudrop.jp/wp-content/uploads/2011/05/2dc9d7973535619c528d35a0a318da0f.png"><img src="http://cloudrop.jp/wp-content/uploads/2011/05/2dc9d7973535619c528d35a0a318da0f.png" alt="" title="Webcalでアクセス" width="256" height="384" class="aligncenter" /></a></p>
<p>照会を押します。</p>
<p><a href="http://cloudrop.jp/wp-content/uploads/2011/05/ab92b0f0ca7d88525ad16e3fa63425f5.png"><img src="http://cloudrop.jp/wp-content/uploads/2011/05/ab92b0f0ca7d88525ad16e3fa63425f5.png" alt="" title="" width="256" height="384" class="aligncenter" /></a></p>
<p>取り込み完了です。</p>
<p>カレンダーにアクセスをするとATNDのイベントスケジュールが表示されます。</p>
<p><a href="http://cloudrop.jp/wp-content/uploads/2011/05/315501cc6aec1621c42a4acc1c7528bd.png"><img src="http://cloudrop.jp/wp-content/uploads/2011/05/315501cc6aec1621c42a4acc1c7528bd.png" alt="" title="" width="256" height="384" class="aligncenter" /></a></p>
<p>URLにアクセスするのも面倒かもしれないのでスクリプトを書きました。<br />
以下のテキストフォームに<strong>ATNDのニックネーム</strong>を入れて、「<strong>カレンダーを開く</strong>」を押すと上記の手順でアクセス出来ます。是非ご利用下さい。</p>
<div id="atnd_webcal"><input type="text" style="width:8em;"/><input type="button" value="カレンダーを開く"/></div>
<p><script type="text/javascript">
//<![CDATA[ 
jQuery(function(){
  var defaultVal = 'ニックネーム';
  var url = 'webcal://api.atnd.org/events/?nickname=';
  var params = '&amp;count=100&amp;format=ics'; 
  var $text = jQuery('#atnd_webcal input[type="text"]');
  var $button = jQuery('#atnd_webcal input[type="button"]');
  $text.val(defaultVal).css('color','#ccc');
  $text.focus(function(){
    if($text.val() === defaultVal){
      $text.val('').css('color','#000');
    }
  });
  $text.blur(function(){
    if($text.val() === ''){
      $text.val(defaultVal).css('color','#ccc');
    }
  });
  $button.click(function(){
    var nickName = $text.val();
    if(nickName === '' || nickName === defaultVal){
      alert('ニックネームを入れてください。');
      return false;
    }
    if(confirm('"' + url + nickName + params + '"を開きます。よろしいですか？')){
      window.location.href = url + nickName + params;
      return true;
    }
    return false;
});
});
//]]&gt;
</script> </p>
<blockquote><p>※iPhone以外でも、Webcalに対応していれば同様のことが可能です。</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://cloudrop.jp/labs/webcal_atnd/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://cloudrop.jp/labs/webcal_atnd" />
	</item>
		<item>
		<title>Osukini Cloudはクラウドとは言えないけど優れたVPSだった</title>
		<link>http://cloudrop.jp/cloud/saases-osukini-cloud?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=saases-osukini-cloud</link>
		<comments>http://cloudrop.jp/cloud/saases-osukini-cloud#comments</comments>
		<pubDate>Mon, 07 Feb 2011 08:39:32 +0000</pubDate>
		<dc:creator>sekine</dc:creator>
				<category><![CDATA[クラウド]]></category>
		<category><![CDATA[サーバー]]></category>
		<category><![CDATA[Osukini]]></category>
		<category><![CDATA[SaaSes]]></category>
		<category><![CDATA[VPS]]></category>
		<category><![CDATA[Xen]]></category>
		<category><![CDATA[さくらのVPS]]></category>

		<guid isPermaLink="false">http://cloudrop.jp/?p=694</guid>
		<description><![CDATA[Osukini Cloudとは クラウドサービス「Osukini クラウド」｜クラウドならSaaSes Osukini Cloudは日本ラッドが提供するSaas/Paasサービスのブランド「SaaSes」の1商品です。  [...]]]></description>
			<content:encoded><![CDATA[<p><!--TOC--></p>
<h3>Osukini Cloudとは</h3>
<p><a href="http://www.saases.jp/cloud/osukini_cloud.html">クラウドサービス「Osukini クラウド」｜クラウドならSaaSes</a></p>
<p>Osukini Cloudは日本ラッドが提供するSaas/Paasサービスのブランド「SaaSes」の1商品です。<br />
Cloudと銘打ってはいるものの、サーバーのスナップショットイメージを保存して再利用したり、稼働済みのサーバーのクローンを立ち上げたりする、スケールアウト向けの機能はありません。</p>
<p>簡単に言うと、CPU・メモリ・ハードディスクを動的にスケールアップ・ダウンできる機能が付いたXenベースのVPSサービスです。<br />
仮想サーバーの仕組みをそのままサービスにしたイメージです。</p>
<h3>Osukini Cloudの使いどころ</h3>
<p>上述のように急激なアクセス増が予想されるスケールアウト必至のサービスには向いていないので、使いどころとしては</p>
<ul>
<li>当面は低スペックで構わないが後々のアクセス増対応に不安</li>
<li>既存の格安VPSでどのプランで契約していいかわからない</li>
</ul>
<p>ようなケースが当てはまるかもしれません。</p>
<p>さくらのVPSが価格の割に品質がよく、満足できるVPSサービスだと思いますが、現時点でスペックが固定なので、もう少し高スペックで同様に低価格なサービスを探している方にはOsukini Cloudはおすすめだと思います。</p>
<h3>スペックと価格</h3>
<p>一般的なVPSサービスのようにプランごとにスペックが決まるのではなく、1プランでスペック変更が可能というところが特徴ですので、最低スペックで始めて運用しながら随時変更することができます。<strong>（スケールアップ・ダウンには再起動・サービスダウンが伴うようです。）</strong></p>
<p>料金とスペックをまとめると以下のようになります。（全て月額）</p>
<style>
table#vps_value {
  margin: 0 auto;
  border-collapse: collapse;
  border-right: 1px solid #666;
  border-bottom: 1px solid #666;
  margin-bottom:15px;
}
table#vps_value th, 
table#vps_value td {
  height: 1.5em;
  padding: 2px 4px;
  border-top: 1px solid #666;
  border-left: 1px solid #666;
}
table$vps_value th {
  position: relative;
}
table#vps_value th.cpu {
  text-align:center;
  background-color: rgb(0,112,192);
  color: #fff;
}
table#vps_value th.hdd {
  text-align:right;
  background-color: rgb(146,200,80);
}
table#vps_value td.value {
  text-align:right;
}
</style>
<table id="vps_value">
<tbody>
<tr>
<td>&nbsp;</td>
<th class="cpu">1CPU+1GB</th>
<th class="cpu">2CPU+2GB</th>
<th class="cpu">3CPU+3GB</th>
<th class="cpu">4CPU+4GB</th>
</tr>
<tr>
<th class="hdd">80GB</th>
<td class="value">¥1,000</td>
<td class="value">¥2,200</td>
<td class="value">¥3,800</td>
<td class="value">¥5,800</td>
</tr>
<tr>
<th class="hdd">160GB</th>
<td class="value">¥1,900</td>
<td class="value">¥3,100</td>
<td class="value">¥4,700</td>
<td class="value">¥6,700</td>
</tr>
<tr>
<th class="hdd">240GB</th>
<td class="value">¥2,800</td>
<td class="value">¥4,000</td>
<td class="value">¥5,600</td>
<td class="value">¥7,600</td>
</tr>
<tr>
<th class="hdd">320GB</th>
<td class="value">¥3,700</td>
<td class="value">¥4,900</td>
<td class="value">¥6,500</td>
<td class="value">¥8,500</td>
</tr>
</tbody>
</table>
<p>CPUとメモリは連動で、4&#215;4の16パターンの料金体系があり、月途中でスペックを変更した場合は、<strong>その月で最もハイスペックだった料金が請求される</strong>仕組みです。<br />
転送量に対する課金もありませんし、稼働時間に対する課金もありませんので、料金が非常に明確になります。</p>
<p>利用可能なOSは以下の通りです。</p>
<ul>
<li>CentOS ver5.5 32bit</li>
<li>CentOS ver5.5 64bit</li>
<li>Ubuntu ver10.04 32bit</li>
<li>Debian ver5.0(lenny) 32bit</li>
<li>Debian ver5.0(lenny) 64bit</li>
<li>Debian ver6.0(squeeze) 32bit</li>
<li>Debian ver6.0(squeeze) 64bit </li>
</ul>
<h3>実際に使ってみて</h3>
<p>現在、4CPU/4GB+80GB(¥5,800)、CentOS5.5 64bitのサーバーを3台契約しています。<br />
ホームページ上では最短5分以内でスタートできると書いてありますが、1台目を契約した際は<a href="http://twitter.com/SaaSes/status/30573322030817281">在庫がない</a>とのことで、サービスの利用開始まで丸1日かかり、2台目・3台目は14、5分でした。<strong>必ずしも契約後すぐに利用できるわけではない</strong>ので、注意が必要です。</p>
<p>参考までに、サーバーの基本的なスペック情報は以下の通りです。</p>
<h4>システム情報</h4>
<pre class="terminal">
$ uname -a
Linux hostname 2.6.18-194.32.1.el5xen #1 SMP Wed Jan 5 18:44:24 EST 2011 x86_64 x86_64 x86_64 GNU/Linux
</pre>
<h4>CPU情報</h4>
<pre class="terminal" style="height:10em;">
$ cat /proc/cpuinfo
processor	: 0
vendor_id	: AuthenticAMD
cpu family	: 16
model		: 9
model name	: AMD Opteron(tm) Processor 6128
stepping	: 1
cpu MHz		: 2000.154
cache size	: 512 KB
physical id	: 0
siblings	: 1
core id		: 0
cpu cores	: 1
fpu		: yes
fpu_exception	: yes
cpuid level	: 5
wp		: yes
flags		: fpu tsc msr pae mce cx8 apic mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt lm 3dnowext 3dnow constant_tsc pni monitor cx16 popcnt lahf_lm cmp_legacy svm cr8_legacy abm sse4a misalignsse
bogomips	: 5003.13
TLB size	: 1024 4K pages
clflush size	: 64
cache_alignment	: 64
address sizes	: 48 bits physical, 48 bits virtual
power management: ts ttp tm stc [6] [7] [8]

processor	: 1
vendor_id	: AuthenticAMD
cpu family	: 16
model		: 9
model name	: AMD Opteron(tm) Processor 6128
stepping	: 1
cpu MHz		: 2000.154
cache size	: 512 KB
physical id	: 1
siblings	: 1
core id		: 0
cpu cores	: 1
fpu		: yes
fpu_exception	: yes
cpuid level	: 5
wp		: yes
flags		: fpu tsc msr pae mce cx8 apic mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt lm 3dnowext 3dnow constant_tsc pni monitor cx16 popcnt lahf_lm cmp_legacy svm cr8_legacy abm sse4a misalignsse
bogomips	: 5003.13
TLB size	: 1024 4K pages
clflush size	: 64
cache_alignment	: 64
address sizes	: 48 bits physical, 48 bits virtual
power management: ts ttp tm stc [6] [7] [8]

processor	: 2
vendor_id	: AuthenticAMD
cpu family	: 16
model		: 9
model name	: AMD Opteron(tm) Processor 6128
stepping	: 1
cpu MHz		: 2000.154
cache size	: 512 KB
physical id	: 2
siblings	: 1
core id		: 0
cpu cores	: 1
fpu		: yes
fpu_exception	: yes
cpuid level	: 5
wp		: yes
flags		: fpu tsc msr pae mce cx8 apic mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt lm 3dnowext 3dnow constant_tsc pni monitor cx16 popcnt lahf_lm cmp_legacy svm cr8_legacy abm sse4a misalignsse
bogomips	: 5003.13
TLB size	: 1024 4K pages
clflush size	: 64
cache_alignment	: 64
address sizes	: 48 bits physical, 48 bits virtual
power management: ts ttp tm stc [6] [7] [8]

processor	: 3
vendor_id	: AuthenticAMD
cpu family	: 16
model		: 9
model name	: AMD Opteron(tm) Processor 6128
stepping	: 1
cpu MHz		: 2000.154
cache size	: 512 KB
physical id	: 3
siblings	: 1
core id		: 0
cpu cores	: 1
fpu		: yes
fpu_exception	: yes
cpuid level	: 5
wp		: yes
flags		: fpu tsc msr pae mce cx8 apic mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt lm 3dnowext 3dnow constant_tsc pni monitor cx16 popcnt lahf_lm cmp_legacy svm cr8_legacy abm sse4a misalignsse
bogomips	: 5003.13
TLB size	: 1024 4K pages
clflush size	: 64
cache_alignment	: 64
address sizes	: 48 bits physical, 48 bits virtual
power management: ts ttp tm stc [6] [7] [8]
</pre>
<h4>メモリ情報</h4>
<pre class="terminal" style="height:10em;">
$ cat /proc/meminfo
MemTotal:      4194304 kB
MemFree:         67556 kB
Buffers:         59036 kB
Cached:        3588160 kB
SwapCached:          0 kB
Active:        2048284 kB
Inactive:      1838268 kB
HighTotal:           0 kB
HighFree:            0 kB
LowTotal:      4194304 kB
LowFree:         67556 kB
SwapTotal:     8393952 kB
SwapFree:      8393880 kB
Dirty:            1064 kB
Writeback:           0 kB
AnonPages:      239332 kB
Mapped:          11304 kB
Slab:           115088 kB
PageTables:       8744 kB
NFS_Unstable:        0 kB
Bounce:              0 kB
CommitLimit:  10491104 kB
Committed_AS:   332088 kB
VmallocTotal: 34359738367 kB
VmallocUsed:      4340 kB
VmallocChunk: 34359734027 kB
</pre>
<h4>ディスク性能(Read)</h4>
<pre class="terminal">
$ sudo hdparm -Tt /dev/xvda3

/dev/xvda3:
 Timing cached reads:   9604 MB in  1.99 seconds = 4818.05 MB/sec
 Timing buffered disk reads:  340 MB in  3.01 seconds = 113.05 MB/sec
</pre>
<h4>ディスク性能(Write)</h4>
<pre class="terminal">
$ dd if=/dev/zero of=/tmp/test.tmp bs=1M count=256
256+0 records in
256+0 records out
268435456 bytes (268 MB) copied, 0.63945 seconds, 420 MB/s

$ dd if=/dev/zero of=/tmp/test.tmp bs=1M count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 2.70829 seconds, 396 MB/s
</pre>
<h3>最後に</h3>
<p>運用して1週間程立ちましたが、スペック通り十分なパフォーマンスを安定して発揮してくれています。リプレース元のサーバーでは転送量課金もかかっていたので、だいぶコストを圧縮することが出来ました。</p>
<p>格安VPSではスペックがネックになって利用シーンが限られていたと思いますが、Osukini Cloudはスペックの自由度が高いので、格安VPSと専用サーバーの間の領域を柔軟にカバーしてくれる数少ない優れたVPSサービスだと思います。</p>
]]></content:encoded>
			<wfw:commentRss>http://cloudrop.jp/cloud/saases-osukini-cloud/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://cloudrop.jp/cloud/saases-osukini-cloud" />
	</item>
	</channel>
</rss>

<!-- Dynamic page generated in 0.313 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2013-05-26 03:12:06 -->
<!-- Compression = gzip -->