2013の15日目の記事です。さんが開発しているPerl製のWAF*1です。Plackを軽くwrapしたような軽量でシンプルなWAFです。3.50からwebsocketのサポートが入り、その関係でPSGIの遅延レスポンス/ストリーミングレスポンスのインターフェースに対応しています。Amon2で非同期レスポンスを使うAmon2::Plugin::Web::Streamingを使う事により非同期でレスポンスを返す事が出来ます。index.txを5秒後にrenderして返す場合は以下のようになります。right;}このように$c->streamingにcallbackを渡すとそれがそのまんまPSGIの非同期レスポンスとして使えてあとは$responderをすきに料理すればいいというスンポーです。簡単ですね!ハマりどころブロックする処理を混ぜてはいけない現実的に、現状は非同期レスポンスを返すアプリケーションを書く場合はAnyEventのイベントループの上で動くことになる為、イベントループを止めるような処理を書いてはいけません。ネットワークIOがあるものなどはAnyEvent::Socketを使うライブラリを使い、sleepやwait(pid)?の代わりにAnyEvent->timer/AnyEvent->childを使うなど、イベントループを止めずに終了を通知させるAPIを使う必要があります。イベントループを止めてしまうとその間他の処理が一切出来ないため、たとえばDBに1秒かかるクエリを投げた場合、1秒間リクエストの受付すら出来なくなってしまうという状態が起こりえます。非同期レスポンスが中心になるアプリケーションでは同時接続数が非常に膨らむ為、問題になります。非同期レスポンスではこれはハマりどころになります。'/'などに登録したcallbackが終わるまでの間*2だからです。$c->streaming()の中ではcontextは基本的にundefになります。同時に複数のリクエストを捌いているケースではタイミングによっては他のリクエストのcontextを参照してしまう為気付きにくいです。シーケンスで表現すると以下のような感じです。*3解決策Object::Containerなどを使い、globalにリソースを持つglobalにリソースを持つ事によって、それを複数リクエストで共有する事が出来ます。トランザクションなど、リソースに状態変化が起こる処理を行うと問題になりますが、そのような処理を行わない場合は検討しても良いかもしれません。トランザクションが必要な処理はGearmanなどのWorkerに任せてAnyEvent::Gearmanなどでタスクとして投げてその終了をcallbackで受けるなど、別プロセスで同期的に処理するのが良いかと思います。シンプルにやる方法もあるとベターかとは思いますが現状ではなかなか辛そうな印象です。Framework*2:もっと厳密に言えばAmon2::Web#handle_requestが終了するまでの間*3:seqdiag.jsを使っています。Entries最近の人気記事Archiveはてなブログをはじめよう!karupaneruraさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。