Twitter のウラで動いているメッセージング Starling

Rubyforge にのってた。もう一カ月も経ってるのに今日知った。

RubyForge: Starling: Project Info
Starling is a light-weight persistent queue server that speaks the MemCache protocol. It was built to drive Twitter's backend, and is in production across Twitter's cluster.

http://rubyforge.org/projects/starling/

まだここしか見てない。

ワークフローとメッセージング

ワークフローってまさに伝票のやりとりなので、メッセージングの上でやると良いんじゃないかなぁ、と思いつつ、ずっと思っているだけだ。ステータス管理、エラーリカバリー、非同期呼び出しなど被るところは多そう。柔軟性を求めると、永続化を自前でやったほうが良いのかもしれないけど。
メッセージング側で考慮すべき点は、fork-join 型をどうメッセージにマップするかが大きいかなぁ。逆にワークフロー側は、分散してステータス管理が出来るかどうかか。

伝票 = メッセージ

2008-02-04 - 2008年のはぶにっき
仕事]ふと思った 16:13 このエントリーを含むブックマーク このエントリーのブックマークコメントCommentsAdd Star

伝票モデルにはMQがぴったりなんじゃないか。

http://d.hatena.ne.jp/habuakihiro/20080204#1202109239

Message-oriented middleware(MOM) の導入ドキュメントでは、メッセージを伝票に例えてあることは良くあるように思う。IBM かどこかのでそんなんあった。とても分かりやすいし、その通りだ。そういう意味では、MOM の要件ってのはかなり枯れてる。あまり面白みが無いくらいに。
残りの面白い部分もいくつかある。ひとつは性能で、一部の MOM サーバはスピード狂だ。fiorano とか。それからメッセージ層に、どれだけの機能を入れ込むか、というのもある。あらゆるデータに対してコンテンツベースルーティング(CBR)をできるようにするとか。point-to-many のメッセージに永続的な購読を可能にするとか。
AP4R は開発/(単体)テスト/運用を含めて使い易さを第一に考えたい。CBR はいざとなればサーバ側のスクリプトを書き換えてでも出来るだろう。単にぼくが、メッセージの中身まで覗いてなにかやる MOM の利点が分からないというのもあるけど。

最後は宣伝だけど、AP4Rデベロッパーズサミット2008 で話させていただきますので、お楽しみに!
http://codezine.jp/devsumi/2008/ 2/13 15:25 - 16:15

Developers Summit 2008 - デブサミ2008>タイムテーブル
AP4R とは、Ruby による非同期メッセージングライブラリです。AP4R を活用したシステムでは、クライアントへの素早いレスポンスと負荷分散によるスケーラブルな構成を実現できます。 このセッションでは、信頼性と水平分散をサポートする実装と、Ruby on Rails とのシームレスな連携を含めた API を解説します。また、実際のシステムへの適用事例をご紹介します。
http://www.seshop.com/event/dev/2008/timetable/Default.asp?mode=detail&eid=105&sid=553&tr=08%5FDevelopmentStyle%28Ruby%29#553

Leopard の入力ソース選択

InputSwitcher ユーザへのお願い - Windchase
Leopard で無くなった「ウィンドウごとに入力ソースの状態を保持する」オプションを復活させるように、Apple にバグレポートを送ってください。

いまのままでは、10.6 まで改善される見込みがないそうです。みなさんの声が多ければ多いほど、Apple 内部の開発者が改善に動きやすく

http://d.hatena.ne.jp/Psychs/20080125/1201246318

InputSwitcher 重宝している。これが無いと本当に困る。ので、送った。

rest-discuss ML の message queues スレッド

http://comments.gmane.org/gmane.comp.web.services.rest/6149

最初のメッセージではこんなことを書いている

  • まず、ActiveMQ の(その当時の) REST API の抜粋: POST で in, GET or DELETE で out
  • GET が read-only なのは、REST じゃなくて HTTP
  • キューを表す URL への DELETE は、キュー全体の削除を意味する
  • これはリストに投げたのは、面白いケースで、即座にはより良い方法を思いつかなかったからだ

このエントリでは、キューへ突っ込むのを in, 取り出すのを out と書くことにする。POST/GET は HTTP メソッドのこと。

次のエントリでは、POST-GET-DELETE という提案がある。http://permalink.gmane.org/gmane.comp.web.services.rest/6150

  1. POST /queue/
    • 201, Location /queue/snapshotIDxxxx
  2. GET /queue/shapshotIDxxxx
    • 200, state of the snapshot, with links to elements
  3. DELETE /queue/snapshotIDxxxx/1
    • 200, deleted resource

これはトランザクションモデルである。その意味は、マルチコンシューマーで、スナップショットを作ると、キュー内の全て(everything in the queue) は消える

全ては消える、の意味が分からん。2番目の GET で頭から数個のメッセージを返すとすると、複数コンシューマーが並列アクセスすると無駄が発生しそうでちょっと嫌なかんじ。out をトランザクショナルにするところは参考になる。というか嬉しい。reliable-msg では、トランザクションに入ったメッセージを他のコンシューマーに見えないようにしているので、そこは HTTP でも入れておきたい機能。最低限、begin-out-commit という程度はサポートしたい。2 番目が GET なのがちょっと微妙か。

話が逸れるが、in 側では、サーバ側で GUID を発行するシーケンスもサポートは必要かもしれない。これは、ActiveMQ の send to queue http://activemq.apache.org/restful-queue.html で自然かな。リソース中心でいくなら、GUID をリソースにするのが良いな。

その後、HTTPLR http://www.dehora.net/doc/httplr/draft-httplr-01.html#rfc.section.9 が引用される。が、メッセージ持ってくるだけなのに、3 回もやり取りするの嫌だ、と一蹴(?)されてる。その流れで、「クライアントがちゃんと処理できたかを伝えなくてはいけないよね」といっている。そこでは ack を送信しているけど、いわゆるトランザクションのコミットだな。

Re: Message queues
The sanest approach to modeling queues I know of over HTTP is syndication technology; ie force the data structure towards a list. And if you need to do pubsub, give everyone their own URL to pop.

訳: 知っているかぎり、HTTP 上でキューをモデル化する一番まっとうな方法は、データ構造をリストだとする syndication テクノロジーだ。pub/sub したかったら、ポップするために、それぞれに固有の URL を与えれば良い。
http://article.gmane.org/gmane.comp.web.services.rest/6164

キューの取り出しの競合が考慮されていない。ちょっと受け入れ難い。

Re: Message queues
> I don't see a single-request solution except to use POST or maybe PUT,
> and then it smells more like some flavor of POX or RPC.

Don't feel bad about it:

http://article.gmane.org/gmane.comp.web.services.rest/6189

といって、(結局?) Roy T. Fielding さんの引用を 3 つしている。1 つだけ引用。

Fielding Dissertation: CHAPTER 5: Representational State Transfer (REST)
Like most architectural choices, the stateless constraint reflects a design trade-off. The disadvantage is that it may decrease network performance by increasing the repetitive data (per-interaction overhead) sent in a series of requests, since that data cannot be left on the server in a shared context. In addition, placing the application state on the client-side reduces the server's control over consistent application behavior, since the application becomes dependent on the correct implementation of semantics across multiple client versions.

訳: 多くのアーキテクチャの選択と同様に、ステートレス性も設計のトレードオフである。不利な点は、[中略]ネットワークの性能低下につながるかもしれない。加えて、アプリケーションの状態をクライアント側に置くことは、一貫したアプリケーションの振る舞いに対するサーバーの制御を限定するので、多様なクライアントの種類に渡る意味論の正しい実装に依存するようになる。
http://roy.gbiv.com/pubs/dissertation/rest_arch_style.htm#sec_5_1_3

含蓄深いな。ちゃんと自分の問題を理解して設計しろ、と。まぁ、そりゃそうだ。
というわけでやりたいことをまとめよう。

  1. out: (複数クライアントの)競合が一番あるところなので、いきなり(1 つの request/response で)メッセージ取得ができるようにする
  2. out: トランザクションも使えるようにする、複数の out や、in/out 混在は「出来れば」くらいで、begin-out-commit のシーケンスは必要
  3. in: ひとつ入れる分には、out との対称性、簡単さを重視
  4. in: クライアント側で UUID(GUID) を発行しなくても良いように、サーバ側で発行できるようにする、これも「出来れば」かな

TODO: point to many は未だ

FIFO なデータ構造へのアクセスはどうするんだろう

RESTful な HTTP の使いかたという文脈で、特に構造を持たないような集合をリソースとして、CRUD を行うという話はよくある。(cf. http://yohei-y.blogspot.com/2005/04/rest-5-get-post-put-delete.html)
では、キュー(FIFO なデータ構造)を扱うにはどのように構成したらよいのか? と考えはじめて分からなくなった。

  1. head には突っ込むことだけが出来る
  2. tail からは取り出しだけが出来る
  3. その他の要素には(管理とかは置いといて)アクセスできない

PUT/DELETE の羃等を知らなかったときには、キュー(queue.hoge という名前だとする)をリソースと見立てて、

  1. PUT /queue.hoge で head に突っ込む
  2. DELETE /queue.hoge で tail から取り出す

でいいのかなぁ、と思っていた。が、PUT と DELETE を羃等にしようとすると、この構成ではダメ。

「RESTful Web サービス」をパラパラながめてみたけど、わからん。あまり良い案が思いうかばないのだけど、いまの頭にあるのは以下。
キューではなくて、head/tail をリソースと見立てる。

  1. POST /queue.hoge/tail で突っ込む
  2. POST /queue.hoge/head で取り出す

一般的に、構造を持ったリソースに対する、リッチな(内部が隠蔽された)操作は、どのように HTTP へマップすれば良いかというのは難しい質問になりそうなので置いとく。

2007-02-23 追記
はてなブックマークid:teahut さんより情報をいただいた http://b.hatena.ne.jp/teahut/20080118#bookmark-7127896

また、コメントにて、id:m_seki から "「queue への依頼を表す伝票」リソースの新規作成とかんがえて POST で" 、id:yohei さんからは "subscription 導入が好み" というご意見と設計の指針をいただきました。ありがとうございました。

個人的には、何度も行き来するのは無駄な気がするので、単純に POST を使うのが好みかもしれない。もう一度、ML スレッドを読みこんでみて、制限を考えることにする。

HTTP メソッドの羃等

Web+DB Press を見て、羃等なメソッドという概念を知った。

Studying HTTP 経由で

[Studying HTTP] HTTP Method
メソッドは、(エラーや期限切れ発行とは別に) 同一のリクエストの N > 0 の副作用が単一のリクエストにおけるものと同じであるような際には "冪等{idempotence}" の性質を持つ事もできる。 GET, HEAD, PUT, DELETE 各メソッドはこの性質を共有する。 また、OPTIONS と TRACE 各メソッドは副作用を持つべきではないし、本来冪等であるものである。
しかしながら、[...]

http://www.studyinghttp.net/method#Idempotent_Methods

原文へ。

9.1.2 Idempotent Methods
Methods can also have the property of "idempotence" in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request. The methods GET, HEAD, PUT and DELETE share this property. Also, the methods OPTIONS and TRACE SHOULD NOT have side effects, and so are inherently idempotent.
However, [...]
http://www.ietf.org/rfc/rfc2616.txt

PUT, DELETE は複数回発行しても、サーバ側の(リソースの、と言ったほうが良い?)状態を変えてはいけない。すると、破壊的(safe http://www.studyinghttp.net/method#Safe_Methods ではない)で、羃等じゃないんだったら、POST しか残らないということで。