libevent奮闘記

とあるきっかけから、libeventを現在調査中。

このlibeventは、ここ最近各処のサーバ構築に導入されていることも多いらしく、
メモリキャッシュ系のmemcache導入時に次いでに案件に入れたりしている所もあるとか。

何故かといえば、memcache等の有名オープンソースライブラリにもlibeventが使われる程人気があるからだ。

また、ユーザが求める応答速度も徐々に速くなり、それに対応するため、
裏で動くアプリケーションサーバを用意しつつ、
フロントエンドのサーバとソケット接続しながら情報をやり取りしたり、
DBアクセス用の仲介サーバがあったりと、
スケーラビリティ向上のためにWebサービス系のシステムは複雑になってきた。
そのため、サーバ間やクライアント-サーバのアクセスをすばやく捌ききる必要性も高まってきたため
・・・というのもある。

それはさておき、簡単にlibeventの紹介を行おう。

その1

libeventは、スケーラブルなサーバ構築をコンセプトに用意されたイベント通知ライブラリだ。
Windowsでいう、callback関数の位置づけに近い。
具体的には、各種ファイルディスクリプタの操作(ファイル更新やネットワーク通信(ソケットなど))
を「イベント」ととして監視・通知するという物だ。

その2

マルチプラットフォーム。
OSに依存せず、LinuxやUnixは勿論、Windowsでも使用することが可能だ。
特にUnix系、Linux系はOS毎でアーキテクチャが異なることが多く(epollやpoll,kqueue等)、
サーバを変える時にいちいち実装方法を検討する必要があった。
その差異を吸収しているこのAPIは、非常に重宝する、というわけだ。

その3

高級APIから、低級APIまで揃っていること。
ユーザのニーズに合わせて、イベントの管理をlibeventに任せたり、自前で管理出来るように実装したりと、
状況に合せて取捨選択が出来る柔軟性を持っている。

その4

ライセンスは三条項BSDライセンス
三条項というのは、

  1. 著作権表示
  2. ライセンス条文
  3. 無保証

以上の物を指す。
この3つをドキュメントに表記することで、ソースコード非公開でソフトウェアに組み込み可能と言う物だ。

その他

HTTPデーモン用APIも用意されている。
単なる非同期I/Oライブラリだけでなく、HTTPデーモン用APIが用意されている。
(とはいえ、こちらは特に用事が無いため触っていないが・・・)


こんな、皆嬉しい非同期I/O系のAPIだが、使用上の注意点もある。
マルチスレッド使用、かつ、スレッド別にイベント監視するような場合だ。

というのも、libeventでは、イベント監視・通知にsocketpairを利用している。
そのため、使用するマシンの設定によりけりだが、
無尽蔵にスレッド別にイベント監視を立ち上げるとファイルディスクプリタを食い尽す場合がある。
(とはいえ、よほど酷い使い方しなければ問題は起きないと思うが)
とにかく、どこでイベント監視する必要があるのか、
同時に複数纏めて監視が出来ないかよく確認・設計すると幸せになれるかもしれない。

とりあえず、手っ取り早く使ってみたいという場合は、以下のサイトさんが非常に参考になるだろう。
ninxit.blog「libevent + 使い方」

libeventでは、一つのイベント監視に対し、主に以下の二つの構造体のオブジェクトが必要となる。

(libevent ver1.4.14より抜粋)

(libevent ver1.4.14より抜粋)

event_base構造体の場合は、上記で紹介した手っ取り早く使用する方法を使うと、
libevent内部で管理が行われるため、event構造体のみ注意を払えば良い状態である。

しかし、この「libevent内部での管理」がクセ者なのである。
event_base構造体の実体は、イベント監視およびイベント監視に使用するリソースと関連があり、
event_base構造体のオブジェクトが(libeventのライブラリを使って)解放されるまではlibevent内で保持されるのだ。

これが、ファイルディスクリプタを食らい尽す要因の一つとなる場合があるのだ(libevent1.x系の場合のみ)。
※現在、libevent2.x系が出ており、そちらの詳細は現状不明。
※リソースとは別だが、libeventの各関数(API)はスレッドセーフでは無いことも注意されたし。

よって、イベント監視場所をスレッド別など複数作成する場合には、
自前でevent_base構造体のオブジェクトを生成・破棄する等、管理が必要。

雑で申し訳ないが、ざっくりと「イベント監視は自前で行うよプログラム」の一例を以下に示す。

このプログラム内で、event_base構造体を自前で取得しているが、
このevent構造体とevent_base構造体のオブジェクトがイベント監視(リソース)-イベント内容とを結びつける。

自分自身のメモ殴り書き目的もあり、
筆不精で非常に読みにくい記事となってしまったこと、誠に申し訳ない。
だが、こんな記事でも、技術資料として少しでもお役にたてれば幸いである。