ブログを半移転(?)しました!

このブログで、株式会社wktkという会社を作るエントリを書きました。今のところペーパーカンパニーまっしぐらです。何か活動しなきゃいけないなー、と考え、とりあえずブログを作ってみました。

はてなのほうが適している話題については、引き続きこのブログで書いていこうと思います。宜しくお願いいたします。

ftraceとtrace-cmdを使って、Linux Kernelのイベントログを簡単に取得する

Linuxには、ftraceというトレーサがあります。
カーネル内の全関数タイムスタンプつき呼び出し履歴などを、それなりに高速に取得できます。


詳しくは、@ITにある以下の記事をどうぞ。
http://www.atmarkit.co.jp/flinux/rensai/watch2008/watch10a.html
http://www.atmarkit.co.jp/flinux/rensai/watch2009/watch03a.html


ためしにftraceを使ってみました。2010年5月時点にて、Debianでの使用方法をメモします。


Debianの現行testingにおいて、kernelのftrace機能は無効とされています。ftrace機能が有効かどうかは、以下の操作で確認できます。

# mount -t debugfs nodev /sys/kernel/debug
# cat /sys/kernel/debug/tracing/available_tracers
blk sched_switch initcall nop

まず、debugfsをマウントします。そこにあるtracing/available_tracersというエントリが、現在利用できるトレーサの一覧です。tracing/available_tracersの内容に、「function_graph」「function」などがなければ、ftraceが有効とされていないkernelです。

Debianでftraceを有効としたkernelをビルドする

Debianでのカーネルコンパイル方法ですが、インターネットで情報を探すとさまざまな情報があります。毎回調べるのですが、毎回やり方を忘れますし、どの流儀がよりよいのかも理解していません。


今回はmake-kpkgを使いました。CONCURRENCY_LEVEL環境変数を設定し、8並列でmakeします。設定はmenuconfigで行います。

> sudo aptitude install kernel-package linux-source-2.6.32 libncurses5-dev
> mkdir kernel-2.6.32-ftrace
> cd kernel-2.6.32-ftrace
> tar xvfj /usr/src/linux-source-2.6.32.tar.bz2
> cd linux-source-2.6.32
> CONCURRENCY_LEVEL=8 fakeroot make-kpkg --append-to-version=-9-amd64 --revision ftrace1 \
--initrd --config menuconfig kernel_image kernel_headers

menuconfigでは、以下の2つの項目を選択します。

Kernel hacking
 -> Tracers
   -> Kernel Function Tracer
   -> Trace syscalls

「Kernel hacking -> Compile the kernel with debug info」も必要があれば選択しましょう。


以上の操作で、カレントのいっこ上のディレクトリに、カーネルパッケージが生成されます。あとはこれをdpkg -iで導入するだけ…でいいと思ったのですが、ちょっと詰まりました。


カーネルパッケージのインストールの際、通常であればinitrdが自動的に作成されます。ですが、現在のtestingでは、initrdを作ってくれません*1。今回は、明示的にupdate-initramfsを呼び出すことによって問題を回避しました。GRUBの設定もしてくれます。

> cd ..
> su
# dpkg -i linux-image-2.6.32-ftrace_2.6.32_amd64.deb
# update-initramfs -c -t -k 2.6.32-9-amd64
# dpkg-reconfigure linux-image-2.6.32-9-amd64

再起動後、uname -rなどで新しいカーネルが使われていることを確認します。


再度debugfsをマウントして、tracing/available_tracersをチェックします。function_graphとfunctionが入っていることがわかります。

# mount -t debugfs nodev /sys/kernel/debug
# cat /sys/kernel/debug/tracing/available_tracers
blk function_graph function sched_switch initcall nop


ftraceをする場合には、debugfsのエントリをよく参照・更新します。/etc/fstabに以下のようなエントリを追加して自動的にマウントさせましょう。

debugfs       /sys/kernel/debug          debugfs defaults        0       0

さらに、/debugにシンボリックリンクを張るとよいでしょう。

ln -s /sys/kernel/debug /debug

trace-cmdの導入

ftraceに関する操作のほとんどは、debugfs経由で行うことができます。しかし、これがまた少々めんどくさいのです。echo 1 > /debug/tracing/misc的なことを頻繁に行う必要があるからです。その操作を支援するツールがあります。trace-cmdです。ネットワーク経由で、別のマシンのトレースなども取れちゃいます。


trace-cmdはバージョン1.0が先月にリリースされたばかりです。usageを見たらまだバージョンが0.7ってなっているのはご愛嬌。導入は簡単です。

> git clone git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/trace-cmd.git trace-cmd-stable-v1
> cd trace-cmd-stable-v1
> make
> sudo make install

ためしに、trace-cmdでどのようなトレースができるのか一覧を表示してみましょう。trace-cmdにlistというコマンドを与えると、event/plugin/optionの一覧を表示できます。

> trace-cmd list
events:
skb:kfree_skb
skb:skb_copy_datagram_iovec
syscalls:sys_enter_socket
syscalls:sys_exit_socket
...

plugins:
blk function_graph function sched_switch initcall nop

options:
print-parent
nosym-offset
...

eventは、ftraceで取得できるイベントです。凡例は「イベント種別:イベント名」です。pluginは、available_tracersと同じようです。optionsは、トレースする際に指定できる各種オプション一覧です。「no」を頭につけることで、オプションをオフにすることができます。

プロファイリングする(草薙葵)

プロファイリングをする前に、/proc/sys/kernel/ftrace_enabledが1であることを確認します。なっていなければ、sysctl kernel.ftrace_enabled=1などをしておいてください。この値の設定については、trace-cmdでは扱ってくれないようです。


まずは、lsを実行した場合に、どのようなカーネル関数が呼ばれ、なおかつ実行時間はどうか、ということを調べたいとしましょう。

# trace-cmd record -p function_graph ls

上記のコマンドを実行すると、カレントディレクトリに「trace.dat」というファイルが作成されます。ここに、トレースされたデータが入っています。ファイル名を指定したい場合には、「-o」オプションを指定しましょう。


トレースされたデータは独自のバイナリ形式です。これを解釈して表示してみましょう。

> trace-cmd report | less

うお、ごっちゃりとデータが出てきました。trace-cmd自身が実行したものも含む、カーネル内のすべてのイベントが表示されるからです。適当にgrepしましょう。

> trace-cmd report | grep -E "^\s+ls-" | less

これで、lsに関わるシステムコールの様子がわかります。function_graphを用いると、カーネル関数のネストがインデントされてわかりやすいです。さらに実行時間まで計算してくれます。実行実行は、ネストしない関数であればfuncgraph_entryの行に、ネストしている関数であればfuncgraph_exitの行に書かれます。


trace-cmd自身にもフィルタ機能が存在します。たとえば、funcgraph_exitにて、1,000,000ナノ秒(1,000マイクロ秒)以上実行にかかったものだけを抽出したい場合には、以下のようにします。

trace-cmd report -F "funcgraph_exit:(rettime - calltime) > 1000000" | less

…と書いたものの、実はこのフィルタの文法、よくわかっていません。


条件式では、C言語チックな+ - * / % >> << & | ^ ~ == != < > <= >=に加え、正規表現のマッチとその否定である=~ !~も演算子として使えるようです。条件に使える変数については、trace-cmdのソースコード中にあるget_field_val()関数呼び出しの第4引数を参照してみてください。


「-e」でイベント名を書くことにより、関数呼び出し以外のイベントについても情報を取得することができます。今回は、コンテキストスイッチについてのイベントを取得してみましょう。イベント名は、trace-cmd listのevents項に表示されるものを指定することができます。今回はsched_switchですね。

# trace-cmd record -e sched_switch -p function_graph ls

funcgraph_entry/funcgraph_exitと同じ項に、sched_switchと書かれているのが、コンテキストスイッチのイベントです。どのプロセスからどのプロセスにスイッチしたのかがわかります。

まとめ

エントリの最後のほうは歯切れ悪いじゃねーか、オイ!とツッコミたくなったでしょう。僕も使い始めたばかりで、まだまだ勝手がよくわかってないからです。


みんなtrace-cmdを試してみて、その情報をblogなどに書いてくれるとうれしいよ、という想いでメモを公開してみました。ftraceの公式なドキュメントは、ソースツリー中Documentation/trace/ftrace.txtです。

*1:/etc/kernel/postinst.d/initramfs-toolsを見ると、「kernel-package passes an extra arg; hack to not run under kernel-package」っていう部分で止められちゃう

インターネットを活用した、ひきこもりのための株式会社の創り方

この度、株式会社wktk(ワクテカ)という法人を設立いたしました。


30歳の誕生日に何か面白いコトをやろう!と思い立って、2週間くらいで法人設立にこぎつけました。あ、会社勤めは辞めてないし、辞めるつもりもないですよ、念のため。僕の勤め先は、そういうところに融通が利くところなのです。起業を促進してます。うんうん。


株式会社の作り方と、基本的な開業準備について、「ひきこもり気質でインターネット大好きな人」向けに情報を公開します。


世の中には、会社設立のガイドがあふれかえっています。重複することを書いても仕方ないので、本や他のサイトに載っていない情報を主に書いていきます。情報は2010年4月現在のものです。

前提条件

  • 一人発起で、代表取締役のみの株式会社を東京都xx区に設立する。
  • .co.jpドメインを取得する。
  • 公告方法を官報にしつつ、財務諸表のみをWebページに載せて官報掲載代を節約する。
  • 役員報酬は0円とする。
  • 設立日を確定させたい。
  • 極力お外に出ない。インターネット>郵便>対面の順番で手段を選択する。

事前準備

定款作成

定款とは、会社の法律みたいなものです。事業目的などが書いてあり、法人設立の際に必要となります。定款は、公証人と呼ばれる人に認証してもらう必要があります。法律なので、あんまりいいかげんなことは書けないわけですね。


定款は通常は紙として認証を受けるわけですが、実はPDFファイルを認証してもらうこともできます。このPDFファイルとして認証される定款を、電子定款と呼びます。実は、電子定款を使うと、設立費用を4万円節約できます。


紙ベースの定款の原本は、「印紙税法」と呼ばれる法律で「課税物件」とされており、収入印紙を貼る必要があります。電子定款の場合には、紙じゃないので上記の法律にあてはまらない、というわけです。


電子定款の認証を受ける場合には、行政書士にお願いしました。「自分で電子定款の認証はできないの?」とツッコミを受けるかもしれません。電子定款の認証を受けるためには、そのためのソフトウェア購入などの初期費用がかかるんです。初期費用は4万円をゆうに超えます。


僕は、以下の「日本電子定款作成センター」にて電子定款の認証をお願いしました。費用は6,000円。
http://e-teikan.org/
東京都・神奈川県の場合には、行政書士の方が公証役場にまで行ってくれます。


上記「日本電子定款作成センター」からリンクされている、「自分でできる会社設立」というサイトの「株式会社設立ナビゲーション」という項目に、株式会社の設立についてひととおりの手続が書いてあります。
http://kaisya-tsukuro.net/
本エントリでは重複した記述を避け、上記サイトに書いていない情報を記します。

.co.jpドメインの取得

会社を作るんだったら、.co.jpドメインを取得したいですよね。value-domainで安くかつ手軽に.co.jpドメインを取得することができます。
http://www.value-domain.com/
なぜここでドメインの話が出るのか、その理由は次の項目で明らかになります。


.co.jpドメインは、設立登記の前に取得することができます。
http://internet.watch.impress.co.jp/cda/news/2003/09/16/461.html
しかし、value-domainでは設立日が現在の日付以降でないと、申し込みを受け付けてくれません。


よって、設立に必要な書類をすべて準備し終わり、実際に法務局に書類を提出する日の朝に登録を行いましょう。


ドメイン取得代金について、厳密には定款で定めておかなければ法人の負担とすることができません。が、value-domainでのドメイン代程度だったら、法人が負担することで問題ないと考えます。面倒なので、僕は個人負担としました。

公告方法を官報にしつつ、財務諸表のみをWebページに載せて官報掲載代を節約する

先ほどの「自分でできる会社設立」のテンプレートのまま法人を設立すると、公告を行う際に官報を通じなければいけません。株式会社は、その公共性から毎年決算の内容について公告を行わなければいけません。官報での決算公告にかかる費用は、1回およそ6万円です。


定款で、公告方法を「電子公告」とすることもできます。電子公告では、自社のWebページに公告する内容を掲示するだけでOKです。んじゃ、公告方法を電子公告にしたほうがいい、と思いますよね。


実は、「電子公告をちゃんとしているかどうかチェックする機関」というものがありまして、そこにお金を払ってチェックしてもらわないと、電子公告をしたことにならないのです。これはこれで結構いいお値段がします。


たとえば、日本公告調査という会社では、1件75,000円にて「チェック」をしてくれます。
http://www.n-koukoku.com/
公告する内容の長さが長い場合には電子公告のほうが有利ですが、短い内容であれば官報のほうが安くなります。やはり、官報で決算公告したほうがよいのでしょうか。


実は、決算公告だけに限り、上記のチェックが必要ないのです。ラッキー。よって、「チェックが必要な通常の公告は官報でいいけど、決算公告だけ電子公告したい」ということになります。


決算公告だけ電子公告を行うためには、決算公告を行うためのURLを登記する必要があります。この登記、設立登記とは別に行うと、なんと30,000円もの費用がかかります。.co.jpドメインも取得できたことですし、設立時にURLも登記してしまいましょう。


URLを登記する場合には、「発起人の決定書」と「登記すべき事項のTXTファイル」の両方にURLなどを記載する必要があります。以下のような記述をしましょう。「登記すべき事項のTXTファイル」での制約から、URLは全角でなければなりません。

1.貸借対照表に係る情報の提供を受けるために必要な事項を次のとおりとする。
http://wktk.co.jp/


実は、多くの株式会社が決算公告をシカトしています。「NPO決算公告推進協議会」ってのがあるくらいです。シカトすると「100万円以下の過料」を取られる可能性があります。気をつけましょう。


また、電子公告の場合には、貸借対照表とその注記を全文掲載しなければなりません。官報の場合は、貸借対照表の要旨のみを掲載すればOKです。紙面に限りがあるからです。貸借対照表の公開に耐えない会社は、官報で決算公告をしたほうがよいでしょう。

法務局にいく

僕の場合は、「30歳の誕生日に会社を作りたい!」という野望があったため、法務局をわざわざ訪れました。しかし、設立日なんでどうでもよければ、郵送で済ますこともできます。郵便って便利!

  • 提出書類の1枚目の、発起人の名前欄のあたりに、連絡先の携帯電話番号を鉛筆で書いておいてください。
  • 銀行通帳のコピーは、出資額の預入(もしくは振込)のところに蛍光ペンでマークしておいてください。


要は、読んで審査する人の気持ちに立って親切にしたほうがいいよ、ってことですね。


法務局に、相談窓口みたいなものがあります。僕は念のため行きました。「電子定款」と「登記すべき内容」が入ったCD-Rの中身を読む設備がないので、あまり意味のあるアドバイスをいただけませんでした。というわけで、直接窓口に書類一式を提出しちゃうのがいいと思います。


なお、電子定款とは「PDFファイル」だけではなく、「鑑定文書」と呼ばれるXMLファイルと、「電子証明書」であるXSLファイルのセットです。よって、この3つのファイルと、あとは「登記すべき内容」が入ったテキストファイルの、計4つのファイルをCD-Rに入れて持っていく必要があります。


け、決してPDFファイルとテキストファイルだけを提出して、電話で呼び出しを食らい、「補正場所」なるトコロで新しいCD-Rを提出したりはしていないぞ。雰囲気的に、職員室に呼び出されたような感じでした…

登記情報提供サービスで設立を確認する

通常は、登記の申請をしてから1週間ほどで登記が完了します。実は、いまや登記もインターネットで確認できるんです!それが、「登記情報提供サービス」です。
http://www1.touki.or.jp/
平日の8:30-21:00しか使えないけどな!


このサービス、昔は「いにしえのWebページ」的なデザインだったのですが、トップページがキレイになっています。


トップページ右には、2つの大きなボタン画像があります。それぞれ「登記情報を請求する」「登記情報と照会番号を請求する」と書いてあります。ここでは「登記情報と照会番号を請求する」をクリックしてください。


すると次の画面に…昔とデザインが変わっとらんやないか!

「一時利用(クレジットカード即時決済)」のリンクをたどり、各種動作確認後、「動作確認終了 一時利用する」を押してください。


一時利用では、住所氏名生年月日、そしてクレジットカード番号を入力しないと、検索を行うことすらできません。個人情報を入力後、商業・法人登記情報のリンクをクリックし、「法人登記簿請求」の検索を行います。検索時に「照会番号の発行通数」を指定しますが、「1」とでも入れておいてください。


検索結果に自分の会社がない場合には、まだ登記されていません。じっくり待ってください。検索結果の表示までは無料ですが、検索結果をクリックするとその時点で手数料が発生します。


検索結果に、自分の会社が見つかったら、検索結果をクリックして登記情報を請求しましょう。請求した登記情報について、まず照会番号を控えてください。税務署への届出の際に必要となります。また、会社法人等番号も控えておいてください。印鑑カードをスムースに受け取ることができるでしょう。

法務局に行って印鑑カードを受け取る。

設立登記が終わっていることを確認したら、法務局に行きましょう。印鑑カードというものを受け取ることができます。


ここで、登記事項証明書のうち履歴事項証明書を最低1部もらっておく必要があります。後で、都税事務所への届出の際に、それをスキャンしたものが必要となるからです。銀行口座も作成するため、印鑑証明書ももらっておきます。

e-Taxを通じた、税務署への届出

東京都での法人設立の場合、税務署と都税事務所に届出が必要となります。なんと、これらの届出はインターネットでできちゃいます。ひゃっほーい!!!!…と喜びたいところなのですが。


実は、税務署で「設立セット」なる書類セットをもらい、それに記入をして郵送したほうが楽です。が、インターネット大好きな俺としては茨の道でもインターネットで手続きをしたかったのです。


さて、e-Taxの利用にはICカードリーダーと、住民基本台帳カードが必要となります。これらのセットは、個人の確定申告の場合にも使えます。ぜひ購入しておきましょう。住民基本台帳カードの発行時に、電子証明書の発行も一緒にしてもらう必要があります。


パソコンには、ICカードリーダーのドライバを導入したり、政府共用認証局ルート証明書をインストールしたり、さらにe-Taxソフトなるソフトを導入したり…いろいろやっておく必要があります。ここらへんの手続きは複雑なので、詳細はe-Taxサイトを見てください。


準備が終わったら、「開始届出」なるものをWeb経由で提出します。ここで、1点気をつけておく場所があります。「参考事項等(日中の連絡先等)」という入力フォームに、「オンライン登記情報提供制度」で取得した登記情報の「照会番号」及び「発行年月日」を書かなければなりません。フォームには「参考となる事項(日中の連絡先(携帯番号等)など)を入力してください。」とだけ書かれているので、注意していないと書き忘れます。


「開始届出」を行うと、「利用者識別番号」なるものが発行されます。これで、e-Taxソフトにて法人設立届出書等を提出する準備がととのいました(ねづっち)。


e-Taxソフトでは、「追加インストール」という帳票等をダウンロードする機能があります。今回「追加インストール」が必要なのは、「共通」の「プログラム」と「共通帳票」、「申告」の「法人税」の2つです。


e-Taxソフトでは、4つの書類を提出します。法人設立届出書・青色申告の承認申請書・給与支払事務所等の開設届出書・源泉所得税の納期の承認に関する申請書の4つです。


必ず提出しなければならないのは、法人設立届出書です。青色申告のメリットを得たいのであれば、青色申告の承認申請書を出しましょう。今回は従業員が0、役員報酬が0なので、給与支払事務所等の開設届出書・源泉所得税の納期の承認に関する申請書は提出する必要がないように思えます。


もし、これらの書類を提出しなかった場合を考えます。外形的に見れば、給与支払事務所等の開設届出書をサボって、さらに源泉所得税を払っていない法人に見えてしまいます。「0円の役員報酬だから、払う源泉所得税はないんじゃい」ということを明確にしておく必要があるわけですね。よって、給与支払事務所等の開設届出書・源泉所得税の納期の承認に関する申請書も提出します。


法人設立届出書について、添付書類が必要となります。それは、定款の写しです。厳密には、設立時の貸借対照表や、株主名簿の写しなどが必要ですが、1人が全額金銭出資をしている法人については不要なようです。設立趣意書とかは確実にイラネ。


定款なら電子定款のPDFファイルがあるぜ、これ添付して送れば楽だなゲヘヘ…と思うことなかれ。実は、e-Taxでは電子定款のファイルを添付書類とすることができません。「電子定款のPDFファイルを印刷して別途郵送」する必要があります。さらに、「添付書類を別途郵送しますよ」という内容の電子書類である「電子申告及び申請・届出による添付書類送付書」を電子証明して送る必要があります。うげげ。PDFとかアップロードできるようにせんかい!といいたいところですが、しょうがないので郵送しましょう。

eLTAXを通じた、都税事務所への届出

e-Taxパチモノみたいな名前ですが、こちらは地方税のシステムです。利用者の立場からすれば、システムがなんで別なんだよ…と言いたくなりますが、ガマンしてください。


ちなみに、紙ベースの設立届出書では、税務署提出用の書類を書くと、自動的に都税事務所への提出書類が完成するのです。なぜなら、カーボンコピーになってるから。ぐおお…


eLTAXを利用するためには、「利用届出」というものをWebサイト上のJavaアプレットから提出する必要があります。届出を出してから利用者IDが発行されるまで、およそ数日かかります。じっくり待ってください。


「利用届出」の提出先は「東京都」です。「東京都xx区」ではありません。ご注意ください。eLTAXでの「利用届出」フォームでは、「上記の提出先に法人の設立をしていない方は、チェックしてください」という文言とともに、チェックボックスが設けられています。e-Taxとは違い、「オンライン登記情報提供制度」の照会番号等は必要ありません。


さて、eLTAXのWebサイトは、Internet Explorer 6もしくは7でしか動作しません。Internet Explorer 8には対応しないぜ!とサイトにはっきり書いてあります。Internet Explorer 8を使っている人はどうすればよいのでしょうか。


IETesterというソフトを使えば問題が解決できます。
http://www.my-debugbar.com/wiki/IETester/HomePage
IETesterは、いろんなバージョンのInternet Explorerを1つのウィンドウ内に表示できるというすばらしいソフトです。なお、eLTAXにて、IETesterで「IE7」のタブを用いた場合には、添付ファイルのアップロードにて不具合が生じました。IETesterでは「IE6」のタブを開いて、そこでeLTAXを利用しましょう。


eLTAXがe-Taxに比べてすばらしいところは、あらゆる書類を添付して送れちゃうところです。「別途郵便で書類を送るよ」という電子文書を電子認証して送付する、とかいうことをしなくていいわけですね。まあ、こっちのほうが普通だと思いますが…


書類添付する場合、注意すべきことがあります。デカいファイルをアップロードすると、Webサーバが無愛想な英語のエラーメッセージを返してくることです。スキャナーが吐き出すPDFなどは、Adobe AcrobatのPDF圧縮機能などを使って圧縮しておきましょう。


登記事項証明書(履歴事項証明書)は、事前にスキャンしてPDFにしておいてください。電子定款は、PDFファイルをそのまま送ることができます。


eLTAXのサイトを見ていると、専用のクライアントソフトであるPCdeskをダウンロードしなければならないような気がします。実は、法人の設立申請の場合には、PCdeskは必要ありません。なぜこんなことをわざわざ書くのか。それは、PCdeskのダウンロードがめんどくさいからです。論より証拠、画像をお見せしましょう。


うひょー!

社会保険事務所労働基準監督署・公共職業安定署(ハローワーク)には用なし!

役人のみで従業員がおらず、役員賞与の支払いが0のため、社会保険事務所で手続きをする必要はありません。


会社勤めの人がうっかり社会保険事務所で手続きをしてしまうと、「所属選択届」や「2以上事業所勤務届」などを提出しなければならなくなり、大変面倒です。ただし、役員賞与を払う場合には面倒でもちゃんと手続する必要がありますよ。


同様の理由で、労働基準監督署・公共職業安定署への手続きも不要です。こちらは、役員のみで従業員がいない場合であれば手続しなくてよいようです。

銀行口座を作成する

ネット大好きならネットバンク!


小額資本金の法人が都市銀行にて口座を開設するのは、一種の「すわりの悪さ」を感じます。ネット通販で買った自転車を近所の自転車で防犯登録するような感じ。では、どこの銀行で口座を開設すればよいのでしょうか。


ジャパンネット銀行はどうでしょうか。

ジャパンネット銀行で法人口座を開設する場合には、会社のWebページ内容を審査されます。株式会社wktkみたいにふざけた内容のサイトだと、まず審査に落ちるでしょう。


楽天銀行(旧イーバンク銀行)の場合はどうでしょうか。

楽天銀行では、他の銀行で法人口座を開いたあとでないと口座を開設できません。


住信SBIネット銀行では、口座開設の手続きがネットと郵便だけで済みます。ひゃっほーい!今回は、住信SBIネット銀行で口座を作成しました。


さて、銀行口座開設の際には、「印鑑証明書」「登記事項証明書」に加えて、「定款の写し」が必要となります。電子定款のPDFを印刷したものは、厳密には「定款の写し」ではありません。しかし、多くの場合はPDFを印刷したもので代用できるようです。「ホンモノの電子定款の写し」を手に入れるのはちょっと面倒なのですが、本稿では触れません。


「日本電子定款作成センター」で電子定款を作成した場合には、「ホンモノの電子定款の写し」が2部ついてきました。大事に使いましょう。

FAX番号を取得する

家にFAXがあると邪魔ですが、法人ではFAX番号が必要となるケースも多くあります。D-FAXという便利なサービスを利用しましょう。このサービスを利用すると、FAX番号を取得することができます。FAXが送られると、その内容をTIFFファイルとして電子メールで送付してくれます。PDFを希望する場合には、オプションが必要です。
http://www.d-fax.ne.jp/


ただし、FAXが必須となるASKULの登録において、D-FAXの番号は登録することができません。残念ですね…

会社のロゴを作る。

Lancersというサイトで、コンペ形式にてロゴの作成を依頼することができます。

http://www.lancers.jp/


株式会社wktkのロゴ製作は以下のように依頼しました。商標登録を行う予定がないので、既存のフォントの使用を許可しています。商標登録する予定があれば、その旨を依頼内容に書いておく必要があります。

http://www.lancers.jp/work/detail/5490


力作ロゴが多数提案されました。下記のリンクからご覧になれます。

http://www.lancers.jp/work/proposals/5490


freefrogさんの提案と、


inazumaさんの提案と、


2つの提案で悩んだ結果、freefrogさんの提案を採用させていただきました。


ロゴのデザインをお願いする場合、1点気をつけるところがあります。著作権のうち、「著作者人格権」は譲渡できません。「著作者人格権」のひとつに「同一性保持権」があります。ロゴを使う場合に、用途に応じて少し改変して利用したい場合があるでしょう。このような改変が、同一性保持権によって禁止させる可能性があります。「少し改変して使うかもしれませんが、よろしいでしょうか」とたずね、ロゴデザイナの方から了解をとっておくとよいでしょう。


Lancersでは、仕事を頼むだけではなく、仕事を請け負うこともできます。iPhoneアプリの開発のお仕事など、プログラマ向けの案件も出ていました。プログラマやデザイナの方、登録どうでしょうか?

名刺を作る

法人で何かの契約を行う場合、名刺の提示が求められるケースがあります。携帯電話の契約や、greeの開発者アカウントの登録などですね。会社のロゴも作成してもらったことですし、それを活かした名刺を作成してみましょう。


名刺は、SuperPrintにて注文しました。会員登録時に、紹介コード「82944392」を入力すると、ずっと注文が5%引きになるので、入力を忘れずに。
http://www.superprint.jp/


さて、SuperPrintでは、Adobe Illustratorのaiファイルで名刺データを入稿する必要があります。ここで、Illustratorを持っていない方に朗報があります。


Adobe Adobe Creative Suite 4 Web Standardの購入をオススメします。なんとCS5 Web 「Premium」に無料でアップグレードできます。つまり、PhotoshopIllustratorがタダで手に入っちゃうわけです。下記のリンク先から、「Amazon.co.jpの詳細ページへ」のボタンをクリックすると購入できるわけですが、一応補足。Amazon.co.jpのページに遷移したあと、右中ほどにある「こちらからも買えますよ」コーナーにある、「Amazon.co.jp」の「ショッピングカードに入れる」ボタンを押して購入するのがエントリ執筆時点では一番安価でした。


Adobe Creative Suite 4 Web Standard 日本語版 Windows版 (旧製品)

Adobe Creative Suite 4 Web Standard 日本語版 Windows版 (旧製品)


名刺作成の際に気をつけることは、以下の点です。

  • 文字はアウトライン化しておく必要があります。
  • カラーモードは、RGBではなくCYMKにする必要があります。TMNTじゃないよ!
  • 黒1色のモノクロの場合には、色のうちC/Y/Mを念のため0%にしておいてください。ディスプレイでの見た目は変わりませんが…
  • カラー印刷の場合には、黒はC/Y/M 30%、K100%くらいにしておいてください。深みが出るらしいよ!


Illustratorの操作に慣れていなくても、それなりの見た目の名刺を作ることができる「ある操作」があります。それは、「文字と文字の間の詰め」を調整する操作です。テキスト編集中にAltキーを押しながらカーソルキーの左右を押すことにより、文字の詰めを調整できます。適当なフォントを選んで、文字を入力し、詰めを調整すれば、それなりの見た目の名刺が出来上がるのではないでしょうか。

会計ソフトで仕訳する。

会計ソフトとして、弥生会計を導入しました。


まず、発起人が立て替えた設立費用を仕訳しましょう。


設立費という勘定科目があるので、定款の認証にかかる仕訳などはすべて借方をコレにします。貸方は「未払金」でよいでしょう。

(設立費) xxx,xxx / (未払金) xxx,xxx

たまった「未払金」について、会社から発起人に銀行振込をして処理するもよし、

(未払金) xxx,xxx / (普通預金) xxx,xxx
(支払手数料) xxx / (普通預金) xxx

役員からの借入金として振り替えてもよいでしょう。

(未払金) xxx,xxx / (役員借入金) xxx,xxx

役員からの借入金について、借用書を書く必要はありません。気になる人は書いておくとよいでしょう。ただし、借用書を作る場合には収入印紙が必要となります。


設立費は会計的には繰延資産といって、5年間かけてジワジワと費用処理する必要があります(繰延資産は、勘定科目が3文字のは5年償却、5文字のは3年、という会計受験知識もありますねー…)。税法上は1年目で全額費用処理してOKなようです。

(営業外費用) xxx,xxx / (設立費) xxx,xxx

また、ずっと設立費を費用処理せずに、法人が黒字となった時点で費用処理することもできます。


今回は、設立費を繰延資産として扱い、費用処理しませんでした。どうせ売上たたないしね。


新設法人は、何の届出もしていなければ「消費税の免税事業者」となります。この場合、全ての仕訳は「税込」の額で行います。実は、儲からない法人を設立する場合には、消費税の課税事業者になったほうがお得です。払った消費税を還付してもらえるからです。今回は、届出が面倒だったので免税事業者のままにしました。


仕訳について、簿記の3級程度の知識はもっておくと便利です。ついでに資格取得はいかがでしょうか。簿記は楽しいですよ。この本1冊しっかり勉強すれば、簿記3級は取得できるでしょう。

10日で合格るぞ!日商簿記3級 光速マスターテキスト

10日で合格るぞ!日商簿記3級 光速マスターテキスト

必要なお金の総額

必要なお金の総額について気になる方がいるようなので、まとめてみました。筆記用具代・法務局への交通費・プリンタ代・インターネット通信費・パソコン代・ICカードリーダ代などは除きます。


法人設立登記までは、最低206,000円 + 資本金 + 代表印代 のお金が必要となります。資本金1円、代表印が1,280円だと、207,281円かかるわけですね。

項目 金額
電子定款認証 56,000円
登録免許税 150,000円
代表印 1,280円
資本金 1円

法人登記以降でかけたお金は、以下のとおりです。

項目 金額
登記情報の照会番号取得 465円
印鑑証明書@500円x1 500円
履歴事項証明書@1,000円x1 1,000円
定款の写しを税務署に送る切手代 80円
.co.jpドメイン代(1年) 3,000円
ロゴデザイン代 50,000円
名刺 モノクロ 100枚 900円
D-FAX 2,625円

というわけで、ロゴのデザインに50,000円もかけても、総額265,851円で株式会社を作ることができました*1

まとめ

以上のように、法務局に2回行くだけで株式会社を設立できます。設立日にこだわりがなければ、法務局に1回行くだけで済みます。事業の開始に必要な準備も、インターネット上で行えます。


ぜひ皆々さまのお役に立ちますことを。


ちなみに、法人名の最初の候補は「株式会社蟹工船」でした。もっと前向きな名前をつけようよ、と上司に諭されたのでした。そりゃそーだよな!
イブセマスジー!!

*1:代表印代が抜けていたので、追記しました。

どーしてもFTPサーバを立てなければいけない時に使う、使い捨てFTPサーバ

「最近ブログ書かないんですか?」と客先で聞かれることがあったので、生存確認の意味でブログを書いてみたいと思います。


FTPといえば、最近着目を浴びたプロトコルですね。FTPは、そもそもセキュアではないプロトコルです。追い撃ちをかけるように、FTPクライアントがローカルに保存したパスワードを盗むコンピュータウイルスが発生しました。ローカル保存されたパスワードが盗まれたことについては、FTPというプロトコル自体の責任ではありません。しかし、世間でのFTPの印象は悪くなったようです。僕も、普段はFTPを使うことはありません。


しかし、外部の方とやりとりする場合に、「どどどーーしてもFTPじゃないとヤダー!!!」と言われるケースがあります。そのような場合、FTPサーバを必要なときのみだけ起動するという方法を取ることができます。具体的には、以下のような方法ですね。

  • ファイルの受け渡しをしたいという連絡を電話などで受ける。
  • ftpサーバを立ち上げる。
  • ファイルをftp経由でアップロードしてもらう。
  • 完了次第ftpサーバを葬る。

しかし、僕がいままで経験したことのあるFTPサーバの設定は、
意外と面倒くさく、しかも柔軟性に欠けたものしか行えない印象があります。
ちょっとだけのファイルの受け渡しのためだけに、
普段使わない上にメンドクサイFTPサーバ設定をする気なんて起きねー!


このような、生存期間が短いFTPサーバをカンタンに作ることができる、pyftpdlibというものがあります。
Windows/Linux/Mac OS X全てで動作する、ラクラクFTPサーバ作成ライブラリです。
今回は、このpyftpdlibの使い方について簡単な解説を試みます。


なお、実行のためにはプログラミング言語Pythonの実行環境が必要となります。
最近のLinuxディストリビューションだったら標準で実行環境が入っていると思います。

pyftpdlibのダウンロード

pyftpdlib、何がすごいって「ファイル1個だけのライブラリ」ということです。扱いが楽ですね。(2013年3月26日追記:pyftplibバージョン1.0.0以降は、ファイルが複数に別れています。バージョン0.7.0を使う前提で以下記述されています。)


ダウンロードは、
http://code.google.com/p/pyftpdlib/
から行うことができます。


ダウンロードしたパッケージは、インストールする必要がありません。
動作に必要となるのは、解凍して得られる「pyftpdlib-x.x.x/pyftpdlib/ftpserver.py」という1ファイルのみです。
これをカレントディレクトリに置いてください。

anonymous ftpを立てる

全てのIPアドレスの10021番ポートにて、
/var/ftp/以下のディレクトリをanonymous ftpにて公開するのは、
以下のように書けます。

#!/usr/bin/python
import ftpserver

FTP_ROOT = "/var/ftp/"
ADDRESS = ("0.0.0.0", 10021)

authorizer = ftpserver.DummyAuthorizer()
authorizer.add_anonymous(FTP_ROOT)

ftp_handler = ftpserver.FTPHandler
ftp_handler.authorizer = authorizer

ftpd = ftpserver.FTPServer(ADDRESS, ftp_handler)
ftpd.serve_forever()

ADDRESSというタプルの1つめの要素に"0.0.0.0"を指定すると、
全てのIPアドレスで接続を待ち受けます。
ポート番号が1024未満でFTPサーバを立ち上げたい場合には、管理者権限が必要となります。


認証が存在しないため、anonymousユーザはファイルの読み込みしかできないようになっています。
実際に使うことはあまりないでしょう。

ユーザを追加する

pyftpdlibは、ユーザを複数追加することができます。ユーザごとにhomeディレクトリや権限を指定することもできます。


FTP_ROOT以下すべてにアクセスできるgunyaというユーザを作成してみましょう。
パスワードは「password_de_gozaimasu」です。


先ほどの、

authorizer.add_anonymous(FTP_ROOT)

という1行を、以下のようにadd_user関数に置換しましょう。

authorizer.add_user("gunya", "password_de_gozaimasu", FTP_ROOT,
                    perm="elradfmw")

add_user関数の引数は、それぞれユーザ名・パスワード・homeディレクトリ・権限です。
権限について、それぞれの文字は以下のような意味を持ちます。

  • e: ディレクトリ変更
  • l: ファイル一覧の取得
  • r: ファイルのダウンロード
  • a: 既存のファイルへの追記
  • d: ファイルの削除
  • f: ファイル名変更
  • m: ディレクトリ作成
  • w: ファイルのアップロード

今回は、権限が全て付与されたユーザを作成したことになります。


もちろん、add_user関数を複数呼べば、複数のユーザを作成することができます。

パスワードを動的に変更

pyftpdlibのいいところは、Pythonというプログラミング言語上で動作するということです。
たとえば、起動のたびに違ったパスワードを設定することもできます。


先ほどのユーザ「gunya」のパスワードを、「password」と「年月日」を連結した文字列にしてみましょう。


まずは、日付・時刻を扱うライブラリを読み込みます。

import ftpserver

の次の行に、

from datetime import datetime

を追記します。


そして、add_user関数の第二引数を変えることにより、「password」と「年月日」を連結した文字列をパスワードとして設定します。

authorizer.add_user("gunya",
                    "password" + datetime.now().strftime('%Y%m%d'),
                    FTP_ROOT, perm="elradfmw")

これで、立ち上がった日付によって違ったパスワードを要求するFTPサーバができました。
もちろん、ユーザIDだって動的に生成することができます。

他にも

  • FTPS
  • 帯域制限
  • IPごとの接続制限
  • IPv6対応

などと機能盛りだくさんなpyftpdlib。
詳しくは、以下のチュートリアルをご覧ください。
http://code.google.com/p/pyftpdlib/wiki/Tutorial

すぐ殺すFTPサーバに使うのには勿体ないともいえます。ぜひ使ってみてください!


僕が持っているWebカメラには写真を定期的にアップロードしてくれる機能があり、
留守中の猫画像をアップロードしたいな!と思ったにもかかわらず、
その機能が対応しているプロトコルFTPだけだった、けどFTPサーバなんて立てるのはメンドクセー、
という経緯の副産物のエントリでした。

はてなのようなキーワードリンクをRubyで付与する実例

hrjn: はてなとかニコニコ大百科キーワードリンクってどうやってんのかなぁ。正規表現だと死んでしまうので、専用のパーサ作ったりしてんのかな。

ニコニコ大百科では、キーワードリンク専用のRubyモジュールを書いています。「SENNA」というキーワードがあったら、「senna」とか「SENNA」とかにリンクさせたりとかもできます。


Senna 1.1.4 + Ruby 1.8.6で、UTF-8専用ですが、使いたい人はどぞー。あと、いつもどおりいい加減な書き方なので気をつけて。とりあえず、以下のtest.rb, wordsym.rb, extconf.rb, sen_np_api.cをどこかに放りこんで

ruby extconf.rb
make
sudo make install
ruby test.rb

的な操作で動くはず!だと期待したい。なぜなら公開のためにコードをいじったから。


ライセンスはRuby's Licenseで。

test.rb

$KCODE = 'u'
require 'sen_np_api'
require 'wordsym'

sym = WordSym.new('test.sym')
sym.add('リンク')
sym.add('リンクの冒険')
sym.add('冒険')
sym.add('ガッ')
sym.add('MUTEKI')
puts sym.add_link_str('muTEki リンクの冒険 ミリバール ガッ', 'http://dic.nicovideo.jp/a/', '_blank')
sym.close

wordsym.rb

$KCODE = 'u'
require 'sen_np_api'
require 'uri'
require 'cgi'

class WordSym
  def initialize(path)
    @sym = SennaNP::Sym.open(path)
    raise NicoDHException, '(内部エラー)記事名を保持するSymが作成できません。' unless @sym
  end

  def add(word)
    nword = SennaNP::normalize(word, 0)
    @sym.add(nword)
  end

  def del(word)
    nword = SennaNP::normalize(word, 0)
    @sym.del(nword)
  end

  def count_array(word_array)
    word_array.map {|word|
      nword = SennaNP::normalize(word, 0)
      @sym.at(nword).nil? ? 0 : 1
    }
  end

  def prefix_search(word)
    @sym.prefix_search(word)
  end

  def add_link_tag(ret, str, url_prefix, title, target = nil)
    ret << '<a href="' <<
        url_prefix << # don't escape
        CGI.escape(title).gsub('+', '%20') <<
        '">' <<
        CGI.escapeHTML(str) <<
        '</a>'
  end

  def add_link_str(str, url_prefix = '', target = nil)
    pos = 0
    prestart = preend = -1
    ret = []

    @sym.scan(str) {|word, start, length|
      # puts "word: #{word}, start: #{start}, length: #{length}"
      next if start == prestart or start < preend
      ret << str[pos...start]
      pos = start + length
      prev = add_link_tag(ret, str[start...pos], url_prefix, word, target)
      prestart = start
      preend = start + length
    }
    return ret.join('')
  end

  def getall
    @sym.getall
  end

  def close
    @sym.close
    @sym = nil
  end
end

extconf.rb

require 'mkmf'
dir_config("senna", `senna-cfg --prefix`.chomp)
$LOCAL_LIBS << ' ' + `senna-cfg --libs`.chomp
$CFLAGS << ' ' + `senna-cfg --cflags`.chomp
if have_header("senna.h") and have_library("senna", "sen_init")
  create_makefile("sen_np_api")
end

sen_np_api.c

#include <ruby.h>
#include <senna/senna.h>

typedef struct _sen_np {
  sen_sym *sym;
} sen_np;

#define KEY_BUF_SIZE 2048
VALUE normalize(VALUE self, VALUE rb_str, VALUE rb_flags)
{
  VALUE r;

  char *str;
  long str_len;
  int flags;
  int buf_size;
  char nstrbuf[KEY_BUF_SIZE];

  str = rb_str2cstr(rb_str, &str_len);
  flags = NUM2INT(rb_flags);

  buf_size = sen_str_normalize(str, (unsigned int)str_len, sen_enc_utf8, flags, nstrbuf, KEY_BUF_SIZE);
  if (buf_size > KEY_BUF_SIZE) {
    return Qnil;
  }

  r = rb_str_new(nstrbuf, buf_size);
  return r;
}

VALUE sym_close(VALUE self) {
  sen_np *np;

  Data_Get_Struct(self, sen_np, np);
  sen_sym_close(np->sym);
  np->sym = NULL;

  return Qtrue;
}

void free_np(sen_np *np) {
  sen_sym_close(np->sym);
  np->sym = NULL;
}

VALUE sym_open(VALUE self, VALUE rb_path) {
  VALUE obj;
  sen_np *np;
  sen_sym *sym;
  char *path;

  path = StringValuePtr(rb_path);
  if (!(sym = sen_sym_open(path))) {
    if (!(sym = sen_sym_create(path, 0, SEN_INDEX_NORMALIZE, sen_enc_utf8))) {
      return Qnil;
    }
  }
  obj = Data_Make_Struct(self, sen_np, NULL, free_np, np);
  np->sym = sym;
  return obj;
}

VALUE sym_add(VALUE self, VALUE rb_key) {
  sen_id sym_id;
  const char *key;
  sen_np *np;

  Data_Get_Struct(self, sen_np, np);
  key = StringValuePtr(rb_key);

  if (!(sym_id = sen_sym_get(np->sym, key))) {
    return Qnil;
  }
  return INT2NUM(sym_id);
}

VALUE sym_at(VALUE self, VALUE rb_key) {
  sen_id sym_id;
  const char *key;
  sen_np *np;

  Data_Get_Struct(self, sen_np, np);
  key = StringValuePtr(rb_key);

  if (!(sym_id = sen_sym_at(np->sym, key))) {
    return Qnil;
  }
  return INT2NUM(sym_id);
}

VALUE sym_del(VALUE self, VALUE rb_key) {
  sen_rc rc;
  const char *key;
  sen_np *np;

  Data_Get_Struct(self, sen_np, np);
  key = StringValuePtr(rb_key);

  rc = sen_sym_del(np->sym, key);
  return INT2NUM(rc);
}

VALUE sym_prefix_search(VALUE self, VALUE rb_key) {
  sen_set *set;
  sen_np *np;
  const char *key;
  sen_set_cursor *cur;
  VALUE ret = Qnil;

  Data_Get_Struct(self, sen_np, np);
  key = StringValuePtr(rb_key);

  if ((set = sen_sym_prefix_search(np->sym, key))) {
    if ((cur = sen_set_cursor_open(set))) {
      unsigned int set_size;
      sen_set_info(set, NULL, NULL, &set_size);
      if ((ret = rb_ary_new2((long)set_size))) {
        long i;
        for (i = 0; i < set_size; i++) {
          VALUE rb_str;
          sen_id *key_id;
          char buf[SEN_SYM_MAX_KEY_SIZE];

          sen_set_cursor_next(cur, (void **)&key_id, NULL);
          sen_sym_key(np->sym, *key_id, buf, SEN_SYM_MAX_KEY_SIZE);
          if ((rb_str = rb_str_new2(buf))) {
            rb_ary_store(ret, i, rb_str);
          }
        }
      }
      sen_set_cursor_close(cur);
    }
    sen_set_close(set);
  }
  return ret;
}

#define SH_SIZE 32
VALUE sym_scan(VALUE self, VALUE rb_str) {
  int found;
  int offset;
  const char *str;
  const char *rest;
  long str_len;
  sen_np *np;
  sen_sym_scan_hit sh[SH_SIZE];
  char buf[KEY_BUF_SIZE];

  Data_Get_Struct(self, sen_np, np);
  str_len = RSTRING(rb_str)->len;
  str = StringValuePtr(rb_str);
  offset = 0;
  do {
    int i;
    if (!(found = sen_sym_scan(np->sym, str, (unsigned int)str_len, sh, SH_SIZE, &rest))) {
      break;
    }
    for (i = 0; i < found; i++) {
      int key_len;
      key_len = sen_sym_key(np->sym, sh[i].id, buf, KEY_BUF_SIZE);
      if (key_len > 0) {
        VALUE args =
          rb_ary_new3(3, rb_str_new(buf, key_len - 1), INT2NUM(sh[i].offset + offset), INT2NUM(sh[i].length));
        rb_yield(args);
      }
    }
    offset += (rest - str);
    str_len -= (rest - str);
    str = rest;
  } while (rest < (str + str_len));

  return Qtrue;
}

VALUE sym_getall(VALUE self) {
  VALUE ret;
  sen_np *np;
  unsigned int nrec;
  sen_id id = SEN_SYM_NIL;

  Data_Get_Struct(self, sen_np, np);
  if (!sen_sym_info(np->sym, NULL, NULL, NULL, &nrec, NULL)) {
    if ((ret = rb_ary_new2(nrec))) {
      int i = 0;
      while ((id = sen_sym_next(np->sym, id)) != SEN_SYM_NIL) {
        VALUE rb_str;
        char buf[SEN_SYM_MAX_KEY_SIZE];

        if (sen_sym_key(np->sym, id, buf, SEN_SYM_MAX_KEY_SIZE)) {
          if ((rb_str = rb_str_new2(buf))) {
            rb_ary_store(ret, i++, rb_str);
          }
        }
      }
      return ret;
    }
  }
  return Qnil;
}

void
void_sen_fin(void) {
  sen_fin();
}

void Init_sen_np_api(void) {
  VALUE rb_cSennaNP;
  VALUE rb_cSennaNP_Sym;

  sen_init();

  rb_cSennaNP = rb_define_class("SennaNP", rb_cObject);
  rb_define_singleton_method(rb_cSennaNP, "normalize", normalize, 2);

  rb_cSennaNP_Sym = rb_define_class_under(rb_cSennaNP, "Sym", rb_cObject);
  rb_define_singleton_method(rb_cSennaNP_Sym, "open", sym_open, 1);
  rb_define_method(rb_cSennaNP_Sym, "close", sym_close, 0);
  rb_define_method(rb_cSennaNP_Sym, "add", sym_add, 1);
  rb_define_method(rb_cSennaNP_Sym, "at", sym_at, 1);
  rb_define_method(rb_cSennaNP_Sym, "del", sym_del, 1);
  rb_define_method(rb_cSennaNP_Sym, "scan", sym_scan, 1);
  rb_define_method(rb_cSennaNP_Sym, "prefix_search", sym_prefix_search, 1);
  rb_define_method(rb_cSennaNP_Sym, "getall", sym_getall, 0);
  atexit(void_sen_fin);
}

Web+DB press Vol.50にkey-valueストアの記事を書きました!

いまさらながら告知ですが、WEB+DB press Vol.50にて、key-valueストア入門という記事を執筆させていただきました。やっほーい!皆さんも、Software Design 2009年5月号が売り切れたくらいのイキオイで、100冊くらい買うといいと思います。

WEB+DB PRESS Vol.50

WEB+DB PRESS Vol.50

ま、執筆中は毎日「死にたい、あー死にたい」とつぶやいていたので、日本語やらコードやらが怪しい部分なども多いと思います。第1章で書きたいことが書けたので満足しています。決して、「WEB+DB press Vol.50ではGit特集がよかったです!」というBlogを発見しては伏目がちになる毎日を暮らしていませんよ…


さて、上記記事でも紹介したgroongaですが、memcachedのバイナリプロトコルをほとんど実装してみました。casも実装してみたのですが、もともとのmemcachedのcasがいい加減な実装なので、あまり実用性ない気がしています。むしろcasは削除したい気が満々です。


memcachedのバイナリプロトコルを実装してみて分かったのですが、libmemcachedには初期値付きのincr/decrを行う関数が無かったんです…というわけで、libmemcachedに初期値付きincr/decrを実現するmemcached_increment_with_initial/memcached_decrement_with_initialという関数を追加してみました。


現在リリースされているlibmemcached 0.29では、
上記関数にてバイナリプロトコルを用いた初期値付のincr/decrが出来るようになっています。
ぜひgroongaと併せて試してみてください。

ニコニコ大百科アラートでのメッセージキュー設計について。

お風呂でメモ。

要件

ニコニコ大百科で起こったイベントのうち、
ユーザが指定したものだけを通知するクライアントアプリケーションを作成したい。

なお、すべてのイベントは漏れなくユーザに伝わることとし、
すべてのユーザに送られる情報は同一とする。
イベントが起こった「直後」にイベントが通知されることが望ましい。
計算負荷・ネットワーク負荷が軽い方法がよい。
サーバ側はRuby、クライアント側はPythonを用いる。

さて、どのような通信方式でデータをやりとりすべきか。

RSS/ATOM

まず考えられるのが、RSSATOMなどの採用。クライアント側でもライブラリなどがあってお手軽。

  • feedのエントリ数が固定だと、pollingの間にすべてのイベントが流れてしまう恐れがある。
  • よって、feedのエントリ数は可変とし、一定の時間内に起こったイベントを全て記録することとする。
  • 一定の時間内に起こったイベントを全て記録すると、feed内のエントリ数が増える。
  • そうしたらファイルサイズが大きくなってネットワーク負荷がかかる。
  • 漏れをなくす方法として、たとえばTwitterのpublic timeline取得APIのsince_idパラメータのように、取得したい情報の位置をクライアントから与えてもらう方法がある。
  • でも、Twitterはそのパラメータを無視するようになった。スケールしないんだろう。キャッシュやりにくいしね。
  • そもそも、RSS/ATOMはblogのエントリなどの更新頻度が少ないもの向けじゃね?
  • メリットとしては、staticなファイルにできるってところかな。

XMPP PubSub

while true
  event = queue.get_next_event()
  #loop
  Subscriptions.find_by_node(:all,
    event.pubsub_nodes ).each do |subscriber|
    #send new message
    subscriber.send_xmpp_message(event.to_xmpp)
  end
end
  • スケールするかどうか要検証。あとは実装の充実度。

AMQP

  • AMQPでも同様のことはできるはず。
  • だんだん話がでかくなってきたぞ…
  • AS3ライブラリがある!これは便利だなー。
  • わはは、どこもかしこも「Polling sucks!」Bay Area Functional Programmers の RabbitMQ について。 - Twisted Mind
  • 上記スライドでのXMPPとAMQPの比較表、ACKは今回の用途ではいらない。binaryのほうがいいよなー。Addr/Authもいらない。
  • やっぱ要検証
  • AMQP + XMPPという選択肢もあるらしい。RabbitMQにejabberdを埋め込むとかなんとか。

結論

XMPPとAMQPで実際にサーバ・クライアント書いてみるかー…
話ふくらみすぎだよな。
AMQPはちょっとオーバースペック感がしている。