<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF
 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 xmlns="http://purl.org/rss/1.0/"
 xmlns:content="http://purl.org/rss/1.0/modules/content/"
 xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
 xmlns:dc="http://purl.org/dc/elements/1.1/"
 xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
 xmlns:admin="http://webns.net/mvcb/"
 xmlns:atom="http://www.w3.org/2005/Atom"
>
<channel rdf:about="http://dsas.blog.klab.org/">
<title>DSAS開発者の部屋</title>
<link>http://dsas.blog.klab.org/</link>
<description>
</description>
<dc:language>ja</dc:language>
<admin:generatorAgent rdf:resource="http://blog.livedoor.com/?v=2.0" />
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com" />
<items>
 <rdf:Seq>
  <rdf:li rdf:resource="http://dsas.blog.klab.org/archives/52111531.html" />
  <rdf:li rdf:resource="http://dsas.blog.klab.org/archives/52109828.html" />
  <rdf:li rdf:resource="http://dsas.blog.klab.org/archives/52109160.html" />
  <rdf:li rdf:resource="http://dsas.blog.klab.org/archives/52109070.html" />
  <rdf:li rdf:resource="http://dsas.blog.klab.org/archives/52108950.html" />
  <rdf:li rdf:resource="http://dsas.blog.klab.org/archives/52107940.html" />
  <rdf:li rdf:resource="http://dsas.blog.klab.org/archives/52107477.html" />
  <rdf:li rdf:resource="http://dsas.blog.klab.org/archives/52105107.html" />
  <rdf:li rdf:resource="http://dsas.blog.klab.org/archives/52104348.html" />
  <rdf:li rdf:resource="http://dsas.blog.klab.org/archives/52097996.html" />
 </rdf:Seq>
</items>
</channel>
<item rdf:about="http://dsas.blog.klab.org/archives/52111531.html">
<title>Webアプリ開発者のための MySQL 基礎研修の資料を公開します</title>
<link>http://dsas.blog.klab.org/archives/52111531.html</link>
<description>新卒や海外拠点の新しい Web プログラマーに MySQL のインデックスや explain, トランザクションと MVCC について説明するための研修資料を作りました。特に社内情報が含まれていないのでそのまま公開します。


MySQL Bootcamp


他人に講師役を任せたり、ある程度独習もで...</description>
<dc:creator>songofacandy</dc:creator>
<dc:date>2013-05-17T14:23:24+09:00</dc:date>
<dc:subject>mysql</dc:subject>
<content:encoded><![CDATA[<p>新卒や海外拠点の新しい Web プログラマーに MySQL のインデックスや explain, トランザクションと MVCC について説明するための研修資料を作りました。特に社内情報が含まれていないのでそのまま公開します。

<p>
<a href="http://lab.klab.org/mysql-bootcamp">MySQL Bootcamp</a>

<p>
他人に講師役を任せたり、ある程度独習もできるようにしたつもりなので、よかったらご活用ください。
<hr>
<div style="margin: 1px 3px 1px 0px; text-align: right;">@methane</div>
<img src="http://counter2.blog.livedoor.com/c?ro=1&act=rss&output=no&id=1623805&name=klab_gijutsu2&pid=52111531" width="1" height="1" />
]]>
</content:encoded>
</item>
<item rdf:about="http://dsas.blog.klab.org/archives/52109828.html">
<title>QR コードを機器間での秘密情報の輸送に利用する試み</title>
<link>http://dsas.blog.klab.org/archives/52109828.html</link>
<description>QR コードのもうひとつの利点

QR コードはインターネットアドレスなど所定のテキストデータを簡単に機器に取り込むための手段として広く利用されています。印刷物に限らずさまざまな媒体で扱えるのも便利ですね。


先日、公開鍵暗号を使う Android アプリを試作していた折...</description>
<dc:creator>klab_gijutsu2</dc:creator>
<dc:date>2013-05-02T14:25:18+09:00</dc:date>
<dc:subject>Android</dc:subject>
<content:encoded><![CDATA[<h3>QR コードのもうひとつの利点</h3>
<p>
QR コードはインターネットアドレスなど所定のテキストデータを簡単に機器に取り込むための手段として広く利用されています。印刷物に限らずさまざまな媒体で扱えるのも便利ですね。

<p>
先日、公開鍵暗号を使う Android アプリを試作していた折に、自分の端末 A で生成した秘密鍵を手持ちの別の端末 B へ安全に輸送する手段の検討が必要になりました。やり方はいろいろありそうですが、よりシンプルな方法をとあれこれ考えている内に、机上に無造作に置いたチラシの QR コードにふと目が留まりました。

<p>
QR コードからのデータ取り込みは通常光学的に行われます。このことは電子機器の視覚を利用したデータ通信と考えることができるでしょう。第三者による情報窃取の可能性がしばしば問題となるネットワーク通信とは異なり、「目」を使っての情報伝達には物理的に介入することが難しいため、デジタルデータを画像で表現する QR コードは秘匿性の求められる局面での通信手段としても有用と考えられます。

<p>
今回の話題はふたつの端末の間でのデータ授受なので、送り側の端末で QR コードの生成と画面表示を行い、受け側の端末でそれを読み取ればよさそうです。情報の受け渡しさえできればコードを残しておく必要はないので QR コードは常に動的に生成し使い捨てとすればよいでしょう。


<h3>留意すべき点</h3>
<p>
一件の QR コードに格納できるデータの量には上限があります。QR コードの開発元である株式会社デンソーウェーブ様のサイトの記事から概要を示す表を以下に引用します。
<p>
<center>
<a href="http://www.qrcode.com/about/standards.html">QRコード規格化・標準化｜QRコードドットコム｜株式会社デンソーウェーブ</a>

<p>
<table border=1>
<tr>
<td>コードの大きさ</td>
<td colspan=2>21セル×21セル～177セル×177セル(4セル /辺毎に増加)</td>
</tr>
<tr>
<td>情報の種類及び
情報量(混在も可)<br>
<font size=-1><a href="http://www.qrcode.com/about/version.html">QRコードの情報量とバージョンについて</a></font></td>
<td>
数字<br>
英数字<br>
８ビットバイト(バイナリ)<br>
漢字</td>
<td>
最大7,089文字<br>
最大4,296文字<br>
最大2,953文字<br>
最大1,817文字<br>
</td>
</tr>
<tr>
<td>
誤り訂正能力<br>
(データ復元機能)<br>
<font size=-1><a href="http://www.qrcode.com/about/error_correction.html">誤り訂正能力について</a></font>
</td>
<td>
レベルL<br>
レベルM<br>
レベルQ<br>
レベルH<br>
</td>
<td>
コードワードの約 7% が復元可能<br>
コードワードの約 15% が復元可能<br>
コードワードの約 25% が復元可能<br>
コードワードの約 30% が復元可能<br>
</td>
<tr>
<td>
コード連結機能
</td>
<td colspan=2>
最大16分割 (細長いエリアなどへの印刷)
</td>
</tr>
</table>
</center>

表には、セル（QR コードを構成する最小の点）構成の最大値である 177 セル×177 セルから成る「バージョン 40」の器に、誤り訂正用の冗長データの最も薄い「レベル L」でエンコードしたデータを格納する際の最大文字数が記載されています。すべての半角英数記号を使う場合は 2953 文字です。この容量の多寡はさておき、普段目にする QR コードのそれとはかけ離れた規模のデータを納めた場合、実用的にはどうなのでしょう。

<p>
下の QR コードには半角英数記号 1675 文字を格納しています。これを一般的なサイズ・解像度の PC のモニタで表示した状態であればおそらく多くの携帯端末の QR コードリーダーで読み取ることが可能でしょう。しかし、スマートフォンの小さな画面にこれを表示した状態だと読み取りに失敗するリーダーが出てくるかもしれません。また、一般に情報の密度が高くなるほど読み取りにより多くの時間がかかるため、たとえ成功しても別のストレスが残る可能性もあります。

<center>
<img src="http://livedoor.blogimg.jp/klab_gijutsu2/imgs/e/3/e3380301.gif">
</center>

<p>
そういった事情を考え合わせると、今回のような目的で QR コードを利用する場合は、一件のコードに強引に多くのデータを押し込むのではなく、複数のコードに分けて利用することを前提に余裕を持ってデータを扱うほうが賢明でしょう。

<p>
実は上の表にも記述があるように、QR コードには一件のデータを最大 16 件のコードに分割して格納することの可能な「コード連結」という仕様があります。次の記事には分割 QR コードの実例が掲載されています。
<font size=-1>
<a href="http://www.a-poc.co.jp/howto/howto_p_IT4206_014.html">「IT4206,QRコードの連結機能に対応していますか。」 - 株式会社エイポック様 公式サイトより -</a>
</font>

<p>
残念ながらすべてのリーダー・ライブラリがこの機能に対応しているわけではなく、現在手元で使っているメジャーな ZXing のライブラリも未対応のようです。しかし、今回はリーダーだけではなくライターも自作することが前提なので、両者間で整合性のとれる内容で独自の分割プロトコルを用意すれば事足りると判断しました。また、二台の端末を操作しながら複数のコードを順番に処理していくのは想像するだけで非常に面倒なので、両者の連携にネットワーク通信を併用し、リーダーが正しくコードを読み取ったらライターが自動的に次のコードを表示することにしました。

<p>
ちなみに、<a href="http://dsas.blog.klab.org/archives/52107940.html">先日の記事</a>で操作性の良い QR コードリーダーを自作するために行った取り組みを紹介しましたが、そのきっかけは今回の一連の話題にありました。リーダーを自分で実装すれば上記のような細かい取り回しも柔軟に実現できるわけですね。QR コードの読み取りが主目的ではないアプリへ補助機能としてリーダー処理を組み込むことにはちょっと新鮮な印象があります。

<h3>試作と実験</h3>
<p>
そんなわけで次のような QR コードライターアプリと QR コードリーダーアプリを作ってみました。

<p>
<font size=-1>
<ul style="padding: 20; margin:1;">
<li>ライターとリーダーは QR コードの出入力処理とネットワーク通信の併用によって連携する
<li>リーダーは起動時に UDP ブロードキャストにより LAN 上のライターを探索、ライターはこれに呼応する
<li>ライターはダミーの RSA 秘密鍵 PEM データを 200 文字ごとに分割しそれを格納した QR コードを順次生成・表示する
<li>QR コードリーダーはライターの表示するコードをカメラ経由で順次読み取る 
<li>ライターは生成するコードに毎回連番情報とランダム文字列を挿入、読み取りを終えたリーダーがそれに一致する文字列をネットワーク通信でライターへ返した場合のみライターは次のコードを生成・表示する
<li>リーダーは最後のコードの読み取りを終えると受信した秘密鍵情報を表示する
</ul>
</font>

<p>
<center>
<img src="http://livedoor.blogimg.jp/klab_gijutsu2/imgs/9/d/9de84305.png">
</center>


<h3>デモ動画</h3>
<p>
動作の様子です。奥の端末で QR コードライター、手前の端末でリーダーを動かしています。
<center>
<object type="application/x-shockwave-flash" data="/data/swf/player_flv_maxi.swf" width="640" height="360">
&#8194;<param name="movie" value="player_flv_maxi.swf" />
&#8194;<param name="allowFullScreen" value="true" />
&#8194;<param name="FlashVars" value="flv=/data/qr_secret/QRTest5.flv&autoplay=0&showtime=1&showvolume=1&showstop=1&showfullscreen=1&showplayer=always&startimage=/data/qr_secret/QRTest5.jpg"/>
</object>
</center>

<h3>リソース</h3>
<p>
今回試作したソフトウェア一式を公開します。興味のある方はお試し下さい。

<p>
<center>
<hr size="0" width="60%">
QR コードライター・リーダーのソースコード
<br>
<a href="https://github.com/mkttanabe/MyQRCodeReaderEx">MyQRCodeReaderEx - github</a>
<hr size="0" width="60%">

QR コードライターのビルドずみ apk
<br>
<img src="http://livedoor.blogimg.jp/klab_gijutsu2/imgs/2/f/2f202c4d.gif">
<br>
<font size=-1>
http://dsas.blog.klab.org/data/qr_secret/QR_writer.apk
</font>

<p>
QR コードリーダーのビルドずみ apk
<br>
<img src="http://livedoor.blogimg.jp/klab_gijutsu2/imgs/1/5/155b3c72.gif">
<br>
<font size=-1>
http://dsas.blog.klab.org/data/qr_secret/MyQRCodeReaderEx.apk
</font>
</center>
<hr>
(tanabe)

<img src="http://counter2.blog.livedoor.com/c?ro=1&act=rss&output=no&id=1623805&name=klab_gijutsu2&pid=52109828" width="1" height="1" />
]]>
</content:encoded>
</item>
<item rdf:about="http://dsas.blog.klab.org/archives/52109160.html">
<title>MySQL 5.6 では innodb_flush_log_at_trx_commit の意味が MySQL 5.5 と違う</title>
<link>http://dsas.blog.klab.org/archives/52109160.html</link>
<description>innodb_support_xa と binlog の危ない関係
で、 MySQL がトランザクションログのコミットをシングルスレッドでシーケンシャルに fsync していると書いたのですが、誤解だったのでその補足です。

タイトルの通り、 innodb_flush_log_at_trx_commit=1 の場合も、トランザクシ...</description>
<dc:creator>songofacandy</dc:creator>
<dc:date>2013-04-26T18:27:19+09:00</dc:date>
<dc:subject>mysql</dc:subject>
<content:encoded><![CDATA[<a href="http://dsas.blog.klab.org/archives/52109070.html">innodb_support_xa と binlog の危ない関係</a>
で、 MySQL がトランザクションログのコミットをシングルスレッドでシーケンシャルに fsync していると書いたのですが、誤解だったのでその補足です。
<p>
タイトルの通り、 innodb_flush_log_at_trx_commit=1 の場合も、トランザクションログが fsync されません。トランザクションがディスクに書かれるシーケンスは次のようになります。
<pre class="prog">
1. prepare (fsync)
2. write binlog (grouped, fsync)
3. commit
</pre>
<p>
このうち 1 は従来通り各スレッドで並列に実行され、 2 と 3 が昨日紹介した sql/binlog.cc の MYSQL_BIN_LOG::ordered_commit() の中のでグループ化されてシーケンシャルに実行される処理です。
この ordered_commit() は先頭で
<pre class="prog">
     thd->durability_property= HA_IGNORE_DURABILITY;
</pre>
というようなフラグを立てています。このフラグは MySQL のソースコードの中で参照しているのは storage/innobase/trx/trx0trx.cc だけで、 HA_IGNORE_DURABILITY の時は flush_log_at_trx_commit=0 のように振る舞い、フラッシュ (fsync) を実行しません。
<p>
この場合、データの永続性は prepare されたトランザクションの内容と binlog で担保されます。
クラッシュリカバリの時は、 binlog を読み込んで、そこに書かれているprepare済みトランザクションをコミットしていきます。
(このため、クラッシュしたマシンからDBをコピーしてMySQLを再起動する場合など、binlogのコピーをサボるとコミットしたはずのトランザクションが消えてしまうので注意が必要です。今のところリカバリに読まれるのは最後の binlog だけで、 binlog のローテート時はトランザクションログにも fsync します)
<p>
最終的に、トランザクションごとの fsync の数は、 MySQL 5.5 の場合は (sync_binlog=0 の場合) 2回だったのに対して、 MySQL 5.6 では2回のうち1回は負荷が高くなるほどグループ化されて複数のコミットを1度で  fsync されることになります。この点で MariaDB の方が速そうというのは勘違いでした。
<p>
この辺りはドキュメントが整ってなくて、 MySQL-internals に質問のスレッドが立っているのでそこが参考になります。
<blockquote class="twitter-tweet" lang="ja"><p>これKristianがMonty Program ABの人で、MatsがOracleの人で、「お前の設計はおかしい」って喧嘩してるスレッドじゃないか。面白すぎる <a href="http://t.co/tRglidc3GT" title="http://lists.mysql.com/internals/38705">lists.mysql.com/internals/38705</a></p>&mdash; SH2さん (@sh2nd) <a href="https://twitter.com/sh2nd/status/327587263733182465">2013年4月26日</a></blockquote>
<blockquote class="twitter-tweet" lang="ja"><p>さらにZardoshtがTokuDBの人だった RT @<a href="https://twitter.com/sh2nd">sh2nd</a>: これKristianがMonty Program ABの人で、MatsがOracleの人で、「お前の設計はおかしい」って喧嘩してるスレッドじゃないか。面白すぎる <a href="http://t.co/tRglidc3GT" title="http://lists.mysql.com/internals/38705">lists.mysql.com/internals/38705</a></p>&mdash; SH2さん (@sh2nd) <a href="https://twitter.com/sh2nd/status/327614346593193984">2013年4月26日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<hr>
<div style="margin: 1px 3px 1px 0px; text-align: right;">@methane</div><script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<img src="http://counter2.blog.livedoor.com/c?ro=1&act=rss&output=no&id=1623805&name=klab_gijutsu2&pid=52109160" width="1" height="1" />
]]>
</content:encoded>
</item>
<item rdf:about="http://dsas.blog.klab.org/archives/52109070.html">
<title>innodb_support_xa と binlog の危ない関係</title>
<link>http://dsas.blog.klab.org/archives/52109070.html</link>
<description>

昨日の記事 で innodb_support_xa = 0にすると RDS が速くなることを紹介したのですが、その後 Twitter で innodb_support_xa = 0 にするとクラッシュ時だけでなく通常時も binlog とトランザクションログの一貫性が無くなる（コミットする順序が前後する）可能性があるこ...</description>
<dc:creator>songofacandy</dc:creator>
<dc:date>2013-04-25T20:41:58+09:00</dc:date>
<dc:subject>mysql</dc:subject>
<content:encoded><![CDATA[<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>
<a href="http://dsas.blog.klab.org/archives/52108950.html">昨日の記事</a> で innodb_support_xa = 0にすると RDS が速くなることを紹介したのですが、その後 Twitter で innodb_support_xa = 0 にするとクラッシュ時だけでなく通常時も binlog とトランザクションログの一貫性が無くなる（コミットする順序が前後する）可能性があることを指摘していただきました。
<blockquote class="twitter-tweet" lang="ja"><p>innodb_support_xa=0すると、トランザクションがコミットされた順番でバイナリログに載ることが保証できなくなるんだけどいいのかな？ DSAS開発者の部屋:AWS RDS の書き込み性能チューニング <a href="http://t.co/uia41LOo9O" title="http://dsas.blog.klab.org/archives/52108950.html">dsas.blog.klab.org/archives/52108…</a></p>&mdash; ts. yokuさん (@yoku0825) <a href="https://twitter.com/yoku0825/status/327064875593523200">2013年4月24日</a></blockquote>

<p>
実際に、 MySQL 5.5 と 5.6 両方で、 innodb_support_xa の説明にそう書かれています。

<ul>
<li>
<a href="http://dev.mysql.com/doc/refman/5.5/en/innodb-parameters.html#sysvar_innodb_support_xa">
MySQL 5.5 の innodb_support_xa の解説
</a>
<li>
<a href="http://dev.mysql.com/doc/refman/5.6/en/innodb-parameters.html#sysvar_innodb_support_xa">
MySQL 5.6 の innodb_support_xa の解説
</a>
</ul>

もともと、 innodb_support_xa = 0 を設定した時は、
<pre class="prog">
// innodb_support_xa = 1 のとき
1. prepare (sync)
2. lock
3. write binlog (sync if sync_binlog)
4. commit (sync)
5. unlock

// innodb_support_xa = 0 のとき
1. lock
2. write binlog (sync if sync_binlog)
3. commit (sync)
4. unlock
</pre>
となることを期待していました。こうであれば、 fsync が prepare の分だけ減り、コミットに失敗しない限りは binlog とコミットログの一貫性は保たれるはずです。
<p>
しかし、 MySQL 5.5.31 のコードを見ると、実際には次のようになっていました。
<pre class="prog">
// innodb_support_xa = 1 のとき
1. prepare (sync, lock)
2. write binlog (sync if sync_binlog)
3. commit (unlock, sync)

// innodb_support_xa = 0 のとき
1. prepare (do nothing)
2. write binlog (sync if sync_binlog)
3. commit (sync)
</pre>
XA を OFF にすると、 prepare 時に取られていたロックが取られなくなり、複数スレッドで実行された時に binlog の書き込みとコミットの順序が守られなくなってしまいます。

<p>
しかし、 MySQL 5.5 と 5.6 では大幅に書きなおされているらしいです。
<blockquote class="twitter-tweet" lang="ja"><p>prepare_commit_mutexがMySQL 5.6に見当たらないんです</p>&mdash; SH2さん (@sh2nd) <a href="https://twitter.com/sh2nd/status/327078474630184960">2013年4月24日</a></blockquote>
<blockquote class="twitter-tweet" lang="ja"><p>@<a href="https://twitter.com/methane">methane</a> 了解です。ha_innodb.ccのinnobase_xa_prepareでmutex取ってた部分がMySQL 5.6では空になっていて、だいぶリファクタリングされた感じです</p>&mdash; SH2さん (@sh2nd) <a href="https://twitter.com/sh2nd/status/327079711249416192">2013年4月24日</a></blockquote>

<p>
MySQL 5.6 のソースを呼んでみたところ、 sql/binlog.cc の MYSQL_BIN_LOG::ordered_commit() という関数で、 binlog とトランザクションの順序を守る処理が入っていました。 (というか、 5.5 で呼び出し側がそれを保証しないせいで innodb 側でロックをとると言う設計が無理矢理過ぎですよね)
<p>
この関数は binlog の書き込み、 sync, トランザクションのコミットまで順番に行う関数で、複数スレッドで実行されても大丈夫なようにしつつ、 binlog をグループコミットするような実装になっています。

<pre class="prog">
1. トランザクションを flush キューに入れる
2. lock(log)
3. (stage1) flush キュー内の全てのトランザクションを binlog に書き、  sync キューに入れる
4. lock(sync) & unlock(log)
5. (stage2) sync キュー内の全てのトランザクションを取り出し、
    必要であれば最後のトランザクションまでのbinlogを sync してから、 commit キューに入れる
6. lock(commit) & unlock(sync)
7. (stage 3) commit キューの中身をすべて取り出し、順番にコミットしていく
8. unlock(commit)
</pre>

<p>
この動作の解説とベンチマークが <a href="http://mysqlmusings.blogspot.jp/2012/06/binary-log-group-commit-in-mysql-56.html">Binary Log Group Commit in MySQL 5.6</a> にありました。
XA を OFF にしてもトランザクションが失敗しない限りは binlog とトランザクションの一貫性が崩れないとはいえ、 innodb_support_xa=1 の時の性能が大幅に上がっているので、危険を冒してまで XA を OFF にする必要性は無さそうです。

<p>
この改善により、高負荷時は複数のトランザクションの binlog がまとめて書かれ sync されるのですが、残念なのは innodb 側のコミットは順番に1つずつ実行してしまうことです。
せっかく複数のトランザクションをコミット順に並べたのですから、トランザクションログへの書き込みも1回の fsync にまとめられたら性能が上がりそうです。

<p>
そういう改善がされていないのか検索してみたところ、 MySQL ではなくて MariaDB の方に見つけました。
<p>
<a href="https://mariadb.atlassian.net/browse/MDEV-232">[MDEV-232] Remove one fsync() inside engine's commit() method</a><p>
<a href="http://bazaar.launchpad.net/~maria-captains/maria/5.5-mdev232/revision/3459#sql/log.cc">該当のコミット</a>
<p>
この MDEV-232 により、各 commit ではトランザクションログを書くだけで fsync せず、最後にまとめて fsync するようになります。
最近いくつかのLinuxディストリビューションで採用されたことで話題の MariaDB ですが、 AWS の Multi-AZ のように fsync が遅い環境では MySQL よりも高い性能を出せそうです。また機会があれば、 MySQL 5.6 と Maria DB のベンチマークを取ってみたいと思います。
<hr>
<div style="margin: 1px 3px 1px 0px; text-align: right;">@methane</div><script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<img src="http://counter2.blog.livedoor.com/c?ro=1&act=rss&output=no&id=1623805&name=klab_gijutsu2&pid=52109070" width="1" height="1" />
]]>
</content:encoded>
</item>
<item rdf:about="http://dsas.blog.klab.org/archives/52108950.html">
<title>AWS RDS の書き込み性能チューニング</title>
<link>http://dsas.blog.klab.org/archives/52108950.html</link>
<description>4/25追記: innodb_support_xa=0 はクラッシュ時以外にも binlog と innodb の整合性が取れなくなる問題がありました。 innodb_support_xa と binlog の危ない関係 もご覧ください。

KLab でも最近は AWS を使ったプロジェクトがかなり増えてきました。
AWS で問題になりがち...</description>
<dc:creator>klab_gijutsu2</dc:creator>
<dc:date>2013-04-24T21:17:32+09:00</dc:date>
<dc:subject>mysql</dc:subject>
<content:encoded><![CDATA[<p>4/25追記: innodb_support_xa=0 はクラッシュ時以外にも binlog と innodb の整合性が取れなくなる問題がありました。 <a href="http://dsas.blog.klab.org/archives/52109070.html">innodb_support_xa と binlog の危ない関係</a> もご覧ください。
<p>
KLab でも最近は AWS を使ったプロジェクトがかなり増えてきました。
AWS で問題になりがちなのが、 RDB の性能が DSAS 環境に比べて低いことです。
<p>
DSAS ではバッテリーバックアップ付きのRAID + 非同期レプリケーションを使っているのですが、 RDS では Multi-AZ を使って耐障害性を確保しています。
<p>
この違いによって書き込み性能のチューニングのポイントが変わってきます。RAIDカードはデータが書き込みバッファに乗っている間は fsync が高速なのに対して、 Multi-AZ では別のAZにあるブロックデバイスに対して同期書き込みが実行されるので、 fsync のレイテンシが増えてしまいます。そこで、 fsync の数を減らすことと、書き込み並列度を上げることがより重要になってきます。
<p>
と、いうことは理屈でわかるのですが、実際にパラメータチューニングでどれくらい性能が上がるのかを実験してみました。対象となるパラメータは innodb_support_xa (デフォルト=1)と innodb_write_io_threads (デフォルト=4) です。
<p>
innodb_support_xa は2層コミットを有効にするオプションで、 mysql の内部でトランザクションログとbinlogの整合性をとるために利用されています。具体的には両方のログを書いて同期し、それが終わってからコミットして同期します。 これをオフにするとトランザクションログを書いてコミットして同期するだけで済む (デフォルトで sync_binlog=0 なので binlog 側は同期されない) ので、 fsync の数が減ります。
<p>
innodb_write_io_threads はバックグラウンドの書き込みスレッド数らしく、並列に同期する数ではないので、数字を上げてもどれくらい効果があるのかわからないのですが、とりあえず上限は16なのでこちらも設定してみます。
<p>
ということで、実際に試してみたときのスクリプトと結果がこちらです。<br />
<a href="https://gist.github.com/methane/5451299">RDSベンチマーク結果</a>
<p>
autocommit=1 の状態で簡単な update 文をひたすら並列に発行してトランザクション数を数えた結果、秒間トランザクション数が最大で2倍になりました。
<p>
注意点として、 innodb_support_xa を無効にすることで、フェイルオーバー時に binlog の整合性が保たれないので、 read replica を作り直す必要があります。これはDBのサイズによっては結構時間がかかるので、フェイルオーバー後は数時間サービスを停止するか、一時的にアプリのスレーブ参照をマスターに向けるか、（スレーブ参照はもともとレプリケーション遅延を見込んでいるはずなので）古い read replica をレプリケーションが止まったまま参照し続けるかする必要があります。
<p>
障害時の動作も試してみたかったのですが、電源ケーブルを抜いたりLANケーブルを抜いて突然死させられないのが RDS の難点ですね。
<hr>
<div style="margin: 1px 3px 1px 0px; text-align: right;">@methane</div>
<img src="http://counter2.blog.livedoor.com/c?ro=1&act=rss&output=no&id=1623805&name=klab_gijutsu2&pid=52108950" width="1" height="1" />
]]>
</content:encoded>
</item>
<item rdf:about="http://dsas.blog.klab.org/archives/52107940.html">
<title>「ZXing QR コードスキャナー」の内部処理を追う</title>
<link>http://dsas.blog.klab.org/archives/52107940.html</link>
<description>ZXing (&quot;Zebra Crossing&quot;) Team による「QR コードスキャナー」 （以下、&quot;ZXing スキャナ&quot;と略記） は操作性が良く人気の高い定番 Android アプリのひとつです。同アプリでは ZXing Team 自らが開発を継続しているオープンソースのバーコード処理用ライブラリが使用されてい...</description>
<dc:creator>klab_gijutsu2</dc:creator>
<dc:date>2013-04-15T17:00:54+09:00</dc:date>
<dc:subject>Android</dc:subject>
<content:encoded><![CDATA[ZXing ("Zebra Crossing") Team による「<a href="https://play.google.com/store/apps/details?id=com.google.zxing.client.android">QR コードスキャナー</a>」<font size=-1> （以下、"ZXing スキャナ"と略記）</font> は操作性が良く人気の高い定番 Android アプリのひとつです。同アプリでは ZXing Team 自らが開発を継続しているオープンソースのバーコード処理用ライブラリが使用されています。

<blockquote>
<center>
<font size=-1>
<a href="http://code.google.com/p/zxing/">zxing Multi-format 1D/2D barcode image processing library with clients for Android, Java</a>
</font>
</center>
</blockquote>

このライブラリの優秀さはスマートフォンでバーコード／QR コードを処理する際の実質標準の座にある状況からも裏打ちされていますが、ZXing スキャナの<b>「使いやすさ」</b>は本ライブラリの性能のみに依るものではなくアプリの実装に大きく支えられています。<a href="http://code.google.com/p/zxing/source/browse/#svn%2Ftags%2F2.1%2Fandroid%2Fsrc%2Fcom%2Fgoogle%2Fzxing%2Fclient%2Fandroid">ZXing スキャナのソースコード</a>は公開されているので、それに学べば本家と同等の使いやすさを備えた QR コードリーダーの自作が可能となるはずですね。操作性の良いリーダーを自作できるのであれば QR コード読み取り機能をアプリへ組み込む際にわざわざ ZXing スキャナをインテントで呼び出す必要はなく、独自の処理を柔軟に組み込むこともできるでしょう。また、上記ライブラリを知り尽くした ZXing 謹製スキャナのコードはライブラリの性能を最大限に引き出すための最良のお手本となりそうです。


<p>
ZXing スキャナのソースコードを正面から分析した情報はほとんど見当たらないようですが、手元での調査を通じて得られた情報と、そのエッセンスを小さくまとめた形で試作した自作リーダーのリソース一式を公開します。なお、この記事では <a href="http://code.google.com/p/zxing/downloads/detail?name=ZXing-2.1.zip&can=2&q=">ZXing 2.1 Release</a> 中の zxing-2.1/android/ 配下のソースコードを対象としています。



<h3>注目すべき要素</h3>

<p>
なぜ ZXing スキャナは QR コードリーダーとして使いやすいのでしょう？その要素こそが実装を調べる上で注目すべきポイントとなるでしょう。特長をみっつピックアップしてみます。

<p>
<ul style="padding: 20; margin:1;">
<li><b>コードの認識が早い</b><br>
ターゲットにレンズを向けてじっとしていればすぐに認識が完了する
<li><b>対象とするコードをファインダ枠内に留める以外の操作が不要</b><br>
フォーカスを合わせたり画面をタップするといった操作をする必要がない
<li><b>コード識別パターン検出位置を示すポイントが描画される</b><br>
プレビュー表示にコード識別パターンを発見した位置を示すポイント (ResultPoint) がリアルタイムで描画されるため端末の位置・角度を加減し易い
</ul>

<center>
<font size=-1>
ResultPoint の描画</font>
<br>
<object type="application/x-shockwave-flash" data="/data/swf/player_flv_multi.swf" width="300" height="200">
&#8194;<param name="movie" value="player_flv_multi.swf" />
&#8194;<param name="allowFullScreen" value="true" />
&#8194;<param name="FlashVars" value="flv=/data/zxing_qr_scanner/ResultPoint.flv&&autoplay=0&showtime=1&showvolume=1&showstop=1&startimage=http://livedoor.blogimg.jp/klab_gijutsu2/imgs/7/5/75c99267.jpg" />
</object>
</center>



<h3>ソースコードの追跡とまとめ</h3>

<p>
コード読みの途中で迷子にならないための道具としてホワイトボード代わりにエクセルシートを使いました。あくまでも作業用なので決して見た目の良いものではありませんが記録としてそのまま掲載します。

<p>
<center>
<font size=-1>
<a href="http://dsas.blog.klab.org/data/zxing_qr_scanner/CodeReading.xls"><img src="http://livedoor.blogimg.jp/klab_gijutsu2/imgs/c/0/c0c3ea33.png"></a>&nbsp;&nbsp;&nbsp;<a href="http://dsas.blog.klab.org/data/zxing_qr_scanner/CodeReading.xls">コードリーディング時のメモ</a>
</font>
</center>

<p>
以下、ソースコードから得られた情報を整理してみます。

<p>
<center>
<font size=-1>
※クリックすると大きな図が開きます<br>
</font>
<a href="http://livedoor.blogimg.jp/klab_gijutsu2/imgs/2/a/2ab88bdc.png"><img src="http://livedoor.blogimg.jp/klab_gijutsu2/imgs/a/e/aea8b961.png"></a>
</center>

<p>
<ul style="padding: 20; margin:1;">

<li><font color="blue">プレビュー表示中に裏側で走っている太い処理の内容</font><br>
<font size=-1>
※カメラには 2 秒ごとに autoFocus() が適用される
<ol style="padding: 20; margin:1;">
<li>現在プレビュー表示中のフレームイメージを取得
<li>取得したイメージをバックグラウンドスレッドへ渡す
<li>バックグラウンドスレッドはイメージを ZXing ライブラリ処理に渡す
<li>ライブラリはコードの検出過程で QR コード画像の識別パターンである可能性のある箇所（ResultPoint）を見つけるとその座標を UI 側へ逐次通知する
<li>ResultPoint を受け取とった UI 側はそれを表示中のプレビュー画面に重ねて描画する
<li>ライブラリ側処理が今回のフレームイメージから QR コードを検出しなかった場合、1. からの処理が繰り返される
</ol>
つまり、ZXing スキャナ は QR コードを見つけるまで絶えずフレームイメージの取得とその画像分析を繰り返している
</font>

<p>
<li><font color="blue">重要なクラスとその処理の概要</font>
<font size=-1>

<br>
 - com.google.zxing.client.android
<ul style="padding: 20; margin:1;">
<li><a href="http://code.google.com/p/zxing/source/browse/tags/2.1/android/src/com/google/zxing/client/android/CaptureActivity.java">CaptureActivity</a><br>
QR コードスキャナーの Activity クラス
<li><a href="http://code.google.com/p/zxing/source/browse/tags/2.1/android/src/com/google/zxing/client/android/CaptureActivityHandler.java">CaptureActivityHandler</a><br>
CaptureActivity のハンドラ。DecodeThread インスタンスを生成し DecodeHandler からライブラリ処理による QR コード認識結果を受け取る。コードが認識されなかった場合はこのクラスが CameraManager.requestPreviewFrame() を叩くことで、次のフレームイメージ取得～QR コード認識という全体のループを継続させる
<li><a href="http://code.google.com/p/zxing/source/browse/tags/2.1/android/src/com/google/zxing/client/android/DecodeThread.java">DecodeThread</a><br>
プレビュー中のフレームイメージから QR コードを検出するための手続きを連続的に繰り返すバックグラウンドスレッド
<li><a href="http://code.google.com/p/zxing/source/browse/tags/2.1/android/src/com/google/zxing/client/android/DecodeHandler.java">DecodeHandler</a><br>
DecodeThread のハンドラ。ZXing ライブラリの MultiFormatReader クラスの QR コード検出メソッドを呼び、認識結果を CaptureActivityHandler へ伝える
<li><a href="http://code.google.com/p/zxing/source/browse/tags/2.1/android/src/com/google/zxing/client/android/ViewfinderView.java">ViewfinderView</a><br>
View の継承クラス。プレビュー画面の描画、ファインダ矩形上に捕捉したイメージについての識別パターン検出点（ResultPoint）の描画を onDraw() メソッド内で実施
<li><a href="http://code.google.com/p/zxing/source/browse/tags/2.1/android/src/com/google/zxing/client/android/ViewfinderResultPointCallback.java">ViewfinderResultPointCallback</a><br>
ZXing ライブラリ内に宣言のある「com.google.zxing.ResultPointCallback」インターフェイスの実装クラス。DecodeThread 経由でライブラリ側処理へ登録され、ライブラリが ResultPoint 認識時にこのクラスの foundPossibleResultPoint() メソッドをコールバックする。同メソッドは ViewfinderView クラスへ ResultPoint を伝達する
</ul>
 - com.google.zxing.client.android.camera
<ul style="padding: 20; margin:1;">
<li><a href="http://code.google.com/p/zxing/source/browse/tags/2.1/android/src/com/google/zxing/client/android/camera/CameraManager.java">CameraManager</a><br>
カメラのオープン・クローズや PreviewCallback へのフレームイメージ取得指示など
<li><a href="http://code.google.com/p/zxing/source/browse/tags/2.1/android/src/com/google/zxing/client/android/camera/PreviewCallback.java">PreviewCallback</a><br>
Camera.PreviewCallback の実装クラス。onPreviewFrame() 発生時に DecodeHandler へキャプチャイメージを渡す
<li><a href="http://code.google.com/p/zxing/source/browse/tags/2.1/android/src/com/google/zxing/client/android/camera/AutoFocusManager.java">AutoFocusManager</a><br>
バックグラウンドで 2 秒ごとにカメラに autoFocus() を適用
<li><a href="http://code.google.com/p/zxing/source/browse/tags/2.1/android/src/com/google/zxing/client/android/camera/CameraConfigurationManager.java">CameraConfigurationManager</a><br>
カメラまわりの解像度や各種パラメータの取得・設定
</ul>
</font>

<p>
<li><font color="blue">使いやすさを支えているもの</font>
<ul style="padding: 20; margin:1;">
<li><b>「コードの認識が早い」</b><br>
<font size=-1>
→ プレビュー表示中、コードを検出するまで絶えずフレームイメージの取得とバックグラウンドスレッドでの分析を繰り返している
</font>
<li><b>「対象とするコードをファインダ枠内に留める以外の操作が不要」</b><br>
<font size=-1>
→ カメラへのオートフォーカスの適用を効果的に利用している
</font>
<li><b>「コード識別パターン検出位置を示すポイントが描画される」</b><br>
<font size=-1>
→ 検出位置を直ちに通知するためにライブラリの深部に用意されたコールバック機構と UI への描画処理を適切に組み合わせて使用している
</font>
</ul>

</ul>


<h3>リーダーの試作</h3>
<p>
以上のように、全体像が見えてしまえば ZXing スキャナの操作性を支えているのは意外なほどシンプルなしくみであることがわかります。それを自作のコードに組み込むことは難しくなさそうですね。そこで ZXing スキャナの実装に倣いつつできるだけ短いコードでざっくりとリーダーを作ってみることにしました。認識結果はダイアログ表示のみとしています。動作確認は一部の環境でのみ行っており、不具合があれば適宜手を入れて下さい。
<p>
<center>
<a href="https://github.com/mkttanabe/MyQRCodeReader">MyQRCodeReader - github</a>
</center>

<p>
ソースコードの一覧と概要を以下に示します。

<p>
<ul style="padding: 20; margin:1;">
<li><a href="https://github.com/mkttanabe/MyQRCodeReader/blob/master/src/jp/klab/myqrcodereader/MyActivity.java">MyActivity.java</a><br>
<font size=-1>
本アプリの Activity クラス。implements SurfaceHolder.Callback, Handler.Callback, Camera.PreviewCallback
</font>
<li><a href="https://github.com/mkttanabe/MyQRCodeReader/blob/master/src/jp/klab/myqrcodereader/MyCameraConfigurationManager.java">MyCameraConfigurationManager.java</a><br>
<font size=-1>
ZXing スキャナの CameraConfigurationManager より。カメラパラメータの設定を決め打ちに
</font>
<li><a href="https://github.com/mkttanabe/MyQRCodeReader/blob/master/src/jp/klab/myqrcodereader/MyDecodeThread.java">MyDecodeThread.java</a><br>
<font size=-1>
ZXing スキャナの DecodeThreadより。対応コードフォーマットを決め打ちに
</font>
<li><a href="https://github.com/mkttanabe/MyQRCodeReader/blob/master/src/jp/klab/myqrcodereader/MyDecodeHandler.java">MyDecodeHandler.java</a><br>
<font size=-1>
ZXing スキャナの DecodeHandlerより。コード認識成功時に MyActivity へ Bitmap は送らず検出したテキストの情報のみに
</font>
<li><a href="https://github.com/mkttanabe/MyQRCodeReader/blob/master/src/jp/klab/myqrcodereader/MyFinderView.java">MyFinderView.java</a><br>
<font size=-1>
ZXing スキャナの ViewfinderView および ViewfinderResultPointCallback より。オリジナルの ViewfinderView はプレビュー画面全体を覆っているが単純化のためここではファインダ矩形と一対一に変更。ResultPoint が 4 以上になるとファインダ内に「Warning!」と表示
</font>
</ul>

<center>
<font size=-1>
試作リーダーの動作の様子</font>
<br>
<object type="application/x-shockwave-flash" data="/data/swf/player_flv_multi.swf" width="320" height="240">
&#8194;<param name="movie" value="player_flv_multi.swf" />
&#8194;<param name="allowFullScreen" value="true" />
&#8194;<param name="FlashVars" value="flv=/data/zxing_qr_scanner/MyQRCodeReader.flv&&autoplay=0&showtime=1&showvolume=1&showstop=1&showfullscreen=1"/>
</object>

<p>
<font size=-1>
ビルドずみの apk はここにあります
</font>
<br>
<img src="http://livedoor.blogimg.jp/klab_gijutsu2/imgs/8/c/8cedcc62.gif">
<br>
<font size=-1>
http://dsas.blog.klab.org/data/zxing_qr_scanner/MyQRCodeReader.apk
</font>
</center>
<hr>
(tanabe)

<img src="http://counter2.blog.livedoor.com/c?ro=1&act=rss&output=no&id=1623805&name=klab_gijutsu2&pid=52107940" width="1" height="1" />
]]>
</content:encoded>
</item>
<item rdf:about="http://dsas.blog.klab.org/archives/52107477.html">
<title>グリーン破壊の破壊度をアップしました</title>
<link>http://dsas.blog.klab.org/archives/52107477.html</link>
<description>負荷試験ツール「グリーン破壊」を公開しました
で紹介したグリーン破壊ですが、その後も KLab 内の案件で利用されつつ
地道に強化されています。
最近強化された点を2つ紹介します。
グリーン破壊(KLab/green-hakai)
分散攻撃
以前紹介した時のグリーン破壊は fork して複数...</description>
<dc:creator>klab_gijutsu2</dc:creator>
<dc:date>2013-04-11T16:59:07+09:00</dc:date>
<dc:subject>Python</dc:subject>
<content:encoded><![CDATA[<p><a href="http://dsas.blog.klab.org/archives/52083342.html">負荷試験ツール「グリーン破壊」を公開しました</a>
で紹介したグリーン破壊ですが、その後も KLab 内の案件で利用されつつ
地道に強化されています。
最近強化された点を2つ紹介します。</p>
<p><a href="https://github.com/KLab/green-hakai">グリーン破壊(KLab/green-hakai)</a></p>
<h3>分散攻撃</h3>
<p>以前紹介した時のグリーン破壊は fork して複数プロセスから攻撃する方式だったのですが、
<a href="http://codespeak.net/execnet/">execnet</a>
というライブラリを用いて実際に攻撃を行う外部プロセスを作成するようにしました。</p>
<p>execnet は fork&amp;exec だけでなく、 ssh 経由でリモートマシン上に外部プロセスを
作ることができます。グリーン破壊もこれを利用して分散攻撃ができるようになりました。</p>
<p>設定ファイル (YAML) に次のようなセクションを書くと、ローカルに2プロセス、
<code>attacker</code> ホスト上に 4 プロセスの合計6プロセスから攻撃を仕掛けることができます。</p>
<pre class="prog"><code>#破壊ノード
nodes:
    - host: localhost  # localhost の場合は ssh ではなくて popen します
      proc: 2  # この host で起動するプロセス数
    - host: ghakai@attacker   # ssh先
      proc: 4
</code></pre>

<p>注意点として、外部ホスト上で攻撃プロセスを立ち上げる時も、グリーン破壊を起動したマシンと同じ
ディレクトリにある Python を利用するので、グリーン破壊をインストールしたディレクトリを
rsync かなにかで同期しておく必要があります。</p>
<p>グリーン破壊を AWS で使う場合、1インスタンス当たりの性能は物理マシンほどでない
ことが多いので、 Spot Instance と組み合わせて使うのがお勧めです。</p>
<h3>名前解決</h3>
<p>過去のグリーン破壊は普通に、名前を問い合わせて、結果を上から順番に利用するという形で名前解決をしていました。</p>
<p>しかし、 Keep-Alive が無効のサービスに対して負荷試験するときに名前解決がボトルネックになったり、
AWS の ELB を利用したプロジェクトに対して負荷試験するときにローカルのDNSキャッシュのせいで
攻撃先IPアドレスが分散しなかったりすることがありました。</p>
<p>そこで、最初に名前解決を実行し、解決結果を全て覚えておき、接続する時は上から順ではなくて
ランダムに利用するという方式に変更しました。</p>
<p>ただし、長時間攻撃を継続する場合、 ELB がスケールアウトしてもグリーン破壊は追従しません。
もともと可能な限り Keep-Alive する上に、接続が切れても再接続時に名前解決をしないからです。
ELB 経由で負荷試験を行う場合は、一度グリーン破壊を実行してウォームアップして ELB
をスケールアウトさせてから、グリーン破壊を再実行してください。</p>
<p>また、思ったように負荷がかからないでレスポンスタイムが低下するときに ELB の問題と
アプリの問題を切り分けるとか、 ELB のウォームアップが面倒なときのため、負荷分散を
通さず直接攻撃する機能も搭載しました。</p>
<p>設定ファイルに <code>domain</code> と <code>addresslist</code> の両方を定義すると、接続先は <code>addresslist</code>
からランダムに選ばれ、 HTTP の Host ヘッダには <code>domain</code> の内容が記述されます。</p>
<pre class="prog"><code>#攻撃先のドメイン. これ以外のドメインは攻撃しない.
# Host ヘッダにこのドメインが書かれる.
domain: &quot;http://localhost:8889&quot;

#接続先アドレスリスト. 省略した場合は domain を利用する.
addresslist:
    - 127.0.0.1:8889
    - localhost:8889
</code></pre>
<hr>
<div style="margin: 1px 3px 1px 0px; text-align: right;">@methane</div>
<img src="http://counter2.blog.livedoor.com/c?ro=1&act=rss&output=no&id=1623805&name=klab_gijutsu2&pid=52107477" width="1" height="1" />
]]>
</content:encoded>
</item>
<item rdf:about="http://dsas.blog.klab.org/archives/52105107.html">
<title>gitでバイナリファイルを気軽に扱えるフィルターを作りました</title>
<link>http://dsas.blog.klab.org/archives/52105107.html</link>
<description>ネイティブアプリの開発とかしてると、ついつい git にスプライトの png とか一緒にコミットしてしまって、気づいたらリポジトリサイズが 1GB 超えてたとかありますよね。
git annex とか、本格的なアセット管理システムとか使えば良いんだけど、普通のgitコマンド覚えるだけ...</description>
<dc:creator>klab_gijutsu2</dc:creator>
<dc:date>2013-03-21T21:10:32+09:00</dc:date>
<dc:subject></dc:subject>
<content:encoded><![CDATA[<p>ネイティブアプリの開発とかしてると、ついつい git にスプライトの png とか一緒にコミットしてしまって、気づいたらリポジトリサイズが 1GB 超えてたとかありますよね。</p>
<p>git annex とか、本格的なアセット管理システムとか使えば良いんだけど、普通のgitコマンド覚えるだけでいっぱいいっぱいな人にさらに他のツールまで覚えてもらうのは大変です。</p>
<p>そこで、登録しておいた拡張子のファイルはハッシュ値だけをリポジトリに格納し、ファイルの内容は別のディレクトリやAmazon S3に格納する <a href="https://github.com/methane/git-largefile">git-largefile/gits3</a> を作りました。</p>
<p>git-largefile/gits3 は git の filter として動きます。
filter は通常改行コードの変換をしたり $Id$ のようなキーワードを変換したり行末のスペースを消す、文字通りフィルターなのですが、ここでファイル本体からハッシュ値へ、ハッシュ値からファイル本体への変換をしてしまいます。</p>
<p>これで、事前に設定ファイルと実行バイナリを配置しておいてもらうだけで、新しいコマンドを覚えることなく、 SourceTree for Windows などの GUI ツールもそのまま使いながら、リポジトリサイズの爆発を抑えることができます。</p>
<h3>それ、 Go でできるよ！</h3>
<p>gits3 は Python でプロトタイプを作った後、 go で作りなおしました。</p>
<p>Go はシステムコールを発行する所がアセンブラで書かれていて、 libc にすら依存しない静的リンクされた実行ファイルが作れますし、クロスコンパイルも簡単です。msvcrt のバージョンとかでハマることもありませんし、 cygwin 上でシェルスクリプトや Perl スクリプト動かすのに比べて起動速度も早いです。</p>
<p>Go に興味はあるけど Go のメリットが活かせるアプリを開発する機会がなくて、、、という方は、 Windows ユーザーにも使ってもらいやすいコマンドラインツールの開発言語として使いはじめるのはいかがでしょうか？</p>
<hr>
<div style="margin: 1px 3px 1px 0px; text-align: right;">@methane</div>
<img src="http://counter2.blog.livedoor.com/c?ro=1&act=rss&output=no&id=1623805&name=klab_gijutsu2&pid=52105107" width="1" height="1" />
]]>
</content:encoded>
</item>
<item rdf:about="http://dsas.blog.klab.org/archives/52104348.html">
<title>WebSocket アプリの負荷分散</title>
<link>http://dsas.blog.klab.org/archives/52104348.html</link>
<description>最近 SPDY と WebSocket がアツいですね。
再来週の SPDY &amp; WS 勉強会 も、定員100名に対して
参加者が 247 名とかなりアツいことになっています。
その予習というわけでもないですが、最近 WebSocket を実サービスへの
導入方法を考えながら遊んでいたので、 WebSocket の負...</description>
<dc:creator>klab_gijutsu2</dc:creator>
<dc:date>2013-03-14T18:33:15+09:00</dc:date>
<dc:subject>golang</dc:subject>
<content:encoded><![CDATA[<p>最近 SPDY と WebSocket がアツいですね。
再来週の <a href="http://connpass.com/event/1732/">SPDY &amp; WS 勉強会</a> も、定員100名に対して
参加者が 247 名とかなりアツいことになっています。</p>
<p>その予習というわけでもないですが、最近 WebSocket を実サービスへの
導入方法を考えながら遊んでいたので、 WebSocket の負荷分散方法について
考えていることを書いておこうと思います。</p>
<h3>ステートフルな WebSocket アプリケーション</h3>
<p>HTTP サービスは基本的にステートレスな実装になっており、リクエストが来るたびに
DBサーバーや memcached などのバックエンドから情報を取得して返していました。</p>
<p>この構成では Web アプリ自体は完全にステートレス化することができているので、
負荷分散機はラウンドロビン等のアプリケーションを無視した負荷分散をすることができました。</p>
<p>しかし、 WebSocket が登場してリアルタイム Web が普及し、それがリッチ化してくると、
ステートレス型では効率が悪くなる事があります。</p>
<p>たとえば複数のチャットルームを持つチャットアプリを作る場合、チャットの内容を Redis に格納し、
Redis の pubsub 機能を使って他の Web サーバーに更新を通知することができますが、
Redis は subscribe している Web サーバー全てに通知を送り、チャットログを取得するリクエストを
さばかなければなりません.</p>
<p>MMO ゲームのようにアプリサーバーのメモリ上にチャットログを格納し、同じチャットルームにいる
ユーザーが全員同じアプリサーバーに接続するようにすればどうでしょうか？
アプリサーバーはバックエンドから通知を受け取ったりメッセージを取得しなくても全員に
メッセージを配信できます。これならバックエンドとの通信はログを保存する1回で済みます。</p>
<p>正攻法でこの構成を組む場合、アプリをステートレスなフロントWebアプリとステートフルな
バックエンドアプリの2段構成にすることができます。
でも、この程度ならリバースプロキシで直接リクエストの振り分けをやってしまったほうが
楽だし低コストですよね。</p>
<h3>redis を使った動的な負荷分散</h3>
<p>そこで、 redis に URL のパスごとに分散先を格納しておき、それを使って動的に
リバースプロキシする構成を考えてみました。</p>
<p>効率や応答速度のことを考えたら、リバースプロキシは WebSocket のデコード＆エンコードをする
よりも、HTTP サーバーが Upgrade ヘッダを見つけると TCP プロキシとして動作するほうがいいはずです。</p>
<h4>Go</h4>
<p>最初に目をつけたのは Go です。nginx よりはコードを読み書きしやすいからです。
(node.js でも良いのですが個人的には JavaScript よりも Go の方が好きです)</p>
<p>Go の標準ライブラリ "net/http" にはそのものズバリな revserseproxy があります。
ただしこれは WebSocket に対応していないので、ちょっと改造して Upgrade ヘッダを見つけると
TCP プロキシになる機能を追加しました。  (<a href="https://github.com/methane/rproxy">methane/rproxy</a>)</p>
<p>あとは <a href="https://github.com/garyburd/redigo">redigo</a> という Redis クライアント(名前がカッコイイ！)
と組み合わせればお手軽に賢いリバースプロキシの完成です。</p>
<h4>nginx + lua</h4>
<p>そういえば nginx も最近 WebSocket に対応したって話題になってたなーと思って調べてみると、
これも Upgrade ヘッダを見て TCP プロキシとしてふるまうようです。
さらに調べてみたら Redis + Lua を使って動的な負荷分散するサンプルもいくつかみつかりました。</p>
<p>ただし、 nginx のサブリクエストは基本的に HTTP 用であまり memcached や redis に格納した
生の文字列を扱うのに向いていないので、 <a href="https://github.com/agentzh/lua-resty-redis">lua-resty-redis</a>
という pure Lua のライブラリを使って書きなおしてみました。</p>
<p>これもちゃんと nginx の非同期機能を使ってくれるので Redis に問い合わせしている間
ブロックしたりはしませんし、コネクションプールも可能です。</p>
<p>せっかく作ったので Go 版を紹介したものの, nginx が使えるならもう nginx でいいですね。
でも、毎回 Redis に問い合わせるのではなく expire 付きの LRU キャッシュをインメモリでやるとか、
Socket.IO のセッションを解析して自分で Redis に格納するとか複雑なことをするなら
Go の強みが生きてくるかもしれません。</p>
<h3>サンプル</h3>
<p>お待たせしました。サンプルはこちらになります。</p>
<p><a href="https://github.com/KLab/websocket-reverseproxy-demo">KLab/websocket-reverseproxy-demo</a></p>
<p>このサンプルでは、 Tornado を使ったオンメモリで動くチャットアプリを2つのポートで立ち上げ、
Redis にチャットルームごとのバックエンドを格納した上で、 nginx と go によるリバースプロクシの動作を確認しています。</p>
<p>Go も nginx も開発版を使っているので少しハードルが高いかもしれませんが、 SPDY &amp; WS 勉強会の
参加者はぜひ予習として試してみてください。</p>
<hr>
<div style="margin: 1px 3px 1px 0px; text-align: right;">@methane</div>
<img src="http://counter2.blog.livedoor.com/c?ro=1&act=rss&output=no&id=1623805&name=klab_gijutsu2&pid=52104348" width="1" height="1" />
]]>
</content:encoded>
</item>
<item rdf:about="http://dsas.blog.klab.org/archives/52097996.html">
<title>親指サイズの USB 赤外線リモコンが面白い</title>
<link>http://dsas.blog.klab.org/archives/52097996.html</link>
<description>2013.01.29 追記   
Mac OS X 用の試作コードを掲載しました




昨年末、調べごとをしていた時にちょっと気になる商品が目に留まりました。
株式会社ビット・トレード・ワン 様の「USB 接続 赤外線リモコン KIT」という製品です。

特徴をざっくりまとめてみるとこんな感...</description>
<dc:creator>klab_gijutsu2</dc:creator>
<dc:date>2013-01-18T11:09:41+09:00</dc:date>
<dc:subject>win</dc:subject>
<content:encoded><![CDATA[<font color="red">2013.01.29 追記</font>&nbsp;&nbsp;&nbsp;
Mac OS X 用の試作コードを<a href="#mac">掲載</a>しました

<hr size=0>

<p>
昨年末、調べごとをしていた時にちょっと気になる商品が目に留まりました。
<a href="http://bit-trade-one.co.jp/">株式会社ビット・トレード・ワン</a> 様の「<a href="http://bit-trade-one.co.jp/BTOpicture/Products/005-RS/index.html">USB 接続 赤外線リモコン KIT</a>」という製品です。
<p>
特徴をざっくりまとめてみるとこんな感じです。

<blockquote>
<font size=-1>
<ul style="padding-left:20;  margin:1;">
<li>[パソコンから家庭用機器をリモコン操作]、[リモコンでパソコンを操作] の２つの機能を持つ
<li>赤外線送信用のライブラリやツール・ファームウェアのソースコードが<a href="http://a-desk.jp/modules/forum_hobby/index.php?cat_id=8">公開されている</a>
<li>家電協/ NEC/ SONY の各<a href="http://ja.wikipedia.org/wiki/%E3%83%AA%E3%83%A2%E3%82%B3%E3%83%B3#.E8.B5.A4.E5.A4.96.E7.B7.9A.E3.83.AA.E3.83.A2.E3.82.B3.E3.83.B3.E3.81.AE.E3.83.87.E3.83.BC.E3.82.BF.E3.83.95.E3.82.A9.E3.83.BC.E3.83.9E.E3.83.83.E3.83.88">リモコンコードフォーマット</a>に対応
<li>某清涼菓子のケースにぴったり収まるサイズ
<li>キットは 1,680 円、組立ずみ製品でも 2,480 円と低価格
<li>PC 側対応 OS はWindows 7, Vista, XP
</ul>
</font>
</blockquote>

PC から制御可能な学習型赤外線リモコンといえば 2006 年の発売以来ロングセラーを続ける <a href="http://buffalo.jp/products/catalog/item/p/pc-op-rs1/index.html">PC-OP-RS1</a> がとても有名ですが、このキットは昨年（2012年）発売された製品とのことで、ソフトウェア要素の多くがオープンであることに魅力を感じました。一方で <a href="http://a-desk.jp/modules/forum_hobby/index.php?forum_id=13">公式フォーラム</a>を覗いてみるとエアコンまわりをはじめいろいろ制約もあるようで、それをどう考えるかは価格とのバランスの解釈次第でしょう。そういった話題も含めて好奇心をそそられ、年明け早々に入手しました。画像は「フリスク」と並べてみた様子です。

<p>
<center>
<img src="http://livedoor.blogimg.jp/klab_gijutsu2/imgs/0/4/04e131da.jpg">
</center>

<p>
PC とは A－miniB タイプの USB ケーブルで接続。Windows 上でヒューマンインターフェイスデバイスとして認識され標準の HID ドライバが使用されます。


<p>
<center>
<img src="http://livedoor.blogimg.jp/klab_gijutsu2/imgs/2/6/2689978f.png">
</center>

<h3>とりあえず使ってみると・・</h3>

<p>
さっそく専用の <a href="http://bit-trade-one.co.jp/BTOpicture/Products/005-RS/REMOCON_CT_TRANS.exe">送信用設定ツール</a> に手元のいくつかの機器のリモコンコードを学習させ本キットから信号を出力し、それを元の機器が認識できるか否かを試してみると下の図の結果となりました。

<a href="http://dsas.blog.klab.org/archives/52097996.html">続きを読む</a>
<img src="http://counter2.blog.livedoor.com/c?ro=1&act=rss&output=no&id=1623805&name=klab_gijutsu2&pid=52097996" width="1" height="1" />
]]>
</content:encoded>
</item>

</rdf:RDF>
