SocketChannelブロッキングモードのタイムアウト設定が見つからなくて諦めた
Tokyo Tyrant接続機能を作ってて、当初はmemcachedクライアントを使ってたんだけど、キー一覧取得とか色々使いたくなって、どうせならTokyo Tyrant独自プロトコルの方が速いかもとか若干暴走気味にクライアントを作ってたら、タイトル通りはまったのでまとめておく。
パフォーマンス重視のプログラム書くならnio使うだろJK
…と、大して検討せずにSocketChannel使って書来だした。
途中で「タイムアウト設定してねーや、まー、ちょいとJavadoc調べたらあんだろ、まー後でいいや。」と放置。
大体動いたところで、いざ探してみると無い。よくあるsetTimeout()っぽい何かが全然無い!!うーん…
Javadoc見ても見あたらない。ぐぐる先生に聞くとSocketChannelのConnectionタイムアウトはノンブロッキングだったらできるよ!って書いてある。
めんどくせーと思いつつ、ノンブロッキングでfinishConnectメソッド呼びつつThread.sleepで待って判定するだるいプログラムを書き…
って、コレ全通信で書くの???そーいやぐぐる先生で見つけたのって「Connection」タイムアウトって書いてあった…そーだよ!きっと普通の読み込み待ちはもっと簡単なヤツがあるんだよきっと!!!
…無かったorz
更に愚痴ってたら同僚にSocketChannel#socket().setSoTimeout()を教えられ、試して見るも効かず。
spymemcachedのソース見たときにSocketChannelって単語があった事を思い出し、見てみると全部ノンブロッキングで書いてある…
まー、spymemcachedの方法を見てパク…参考にすれば良いかとも思ったんだけど、でかいデータのときはStreamのままデータ渡したかったんで、ライブラリ内だけならともかく、呼び出し元の外部プログラムにノンブロッキングのまま渡すとかあり得んと思い挫折。
結局、全部Socketで描き直しましたわ…
一瞬諦めるかと悪魔の誘惑が頭をよぎるも、読み込み待ちになったらスレッド一本+コネクション一本が永遠に終了とかウェブアプリではあり得ないのでここで試合終了。残念。
ちなみにSocketの場合は
- 通常の読み込み待ち:Socket#setSoTimeout(int)
- 接続時:Socket#connect(SocketAddress,int)
参考:Oracle Technology Network for Java Developers | Oracle Technology Network | Oracle
でタイムアウトが有効になりました。
しかしホントにブロッキングモードでタイムアウト設定無いなら実運用で全然使えなく無いか?
大体ブロッキング動作をする旧Socketでできるのにnioでできないとおかしくね?
とはまだ思ってるので、もしご存じの方いたら教えて頂けるとありがたいです。