TCP使用時の通信エラーについて

57 views
Skip to first unread message

syuu

unread,
Sep 9, 2009, 12:10:15 AM9/9/09
to Overlay Weaver (Japanese)
こんにちは、Genkidamaの驟雨です。

本当はSourceforge.netのBug trackerに書くべきなのかもしれませんが、英語で書くのがしんどいのでこちらから失礼します。

GenkidamaではDHTライブラリとしてOverlay Weaverを使わせて頂いているのですが、通信エラーが多発する為色々テストをおこ
なってみた所、MessagingTransportとしてTCPを指定している時にある程度通信を行うとリクエストを受け付けなくなる現象が発生して
いるらしい事がわかりました。

テストには以下のコードを使用しました:
http://syuu.dokukino.com/owtest/OWServerSimpleTest.java

これを使って5ノード程度でネットワークを作り、数分ほど通信を続けていると以下のようなExceptionが発生します:
ow.routing.RoutingException
at ow.dht.impl.ChurnTolerantDHTImpl.put(ChurnTolerantDHTImpl.java:
290)
at ow.dht.impl.BasicDHTImpl.put(BasicDHTImpl.java:294)
at owtest.OWServerSimpleTest.main(OWServerSimpleTest.java:41)
.ow.routing.RoutingException

リクエストに対するレスポンスが帰って来ないのが原因のようですが、詳しい理由を突き止めるには至っていません。
通信エラーが散発する程度なら問題はないのですが、どうも一度通信エラーが起きた接続先は何度繋ぎにいっても繋がらないようで、これが原因になって後か
ら立ち上げたノードでjoinしに行ってもRoutingExceptionが発生して繋がらない、という現象が発生していたみたいです。

条件を幾つか変えて試してみたのですが、以下の条件では同じ現象が発生しました:
・RoutingAlgorithmをChordからKademliaに
・ImplmentationNameをBasicDHTに
・ソースコードをCVSの最新版に

一方、MessagingTransportをUDPに変更すると正常に通信出来ました。

Masahiko KIMOTO

unread,
Sep 11, 2009, 2:11:57 AM9/11/09
to overlayw...@googlegroups.com
こんにちは、創夢の木本です。

TTLまわりで不具合が出たので、OverlayWeaverの0.9と0.9.4を比較してみたところ、
TTLを保持する変数がlongからintに変更になっていました。
TTLはミリ秒でカウントされておりINTMAX/1000で頭打ちするようになっているようで、
最大のTTLが24日程度で頭打ちになってしまいます。

現在私どもで作っているシステムでは、30日程度のTTLでputするようになっており、
ow0.9を使っていた頃は動いていたのですが、0.9.4を使うようになってoverflow
するようになってしまいました。

この変更は意図したものでしょうか?
特に理由がないのであれば、元のlongで処理していただけたほうが利用者と
してはうれしいのですが。

----------------------------------------------------------------------
木本 雅彦 / Masahiko KIMOTO, Ph. D.
E-mail: kim...@ohnolab.org URL: http://www.ohnolab.org/~kimoto

Tomonori Sano

unread,
Sep 11, 2009, 10:11:53 AM9/11/09
to overlayw...@googlegroups.com
驟雨さん、こんにちは。佐野です。

ご質問の原因について、確定ではないのですがご報告します。
TCP で発生して UDP で発生しない、とのことなので
ow.messaging.tcp.ConnectionPool を中心に流れを追ってみました。

ConnectionPool は接続が一定数(初期値 3)を越えるとランダムに接続を
捨てます。この捨て方が問題で、現状の ConnectionPool では close せずに
捨てます。
こうなるとガベージコレクトされるまで当然ですが繋がったままになります。

5 ノードが Chord で通信する場合、各ノードが他のすべてへと接続します
ので、初期値 3 のコネクションプールは常にあふれてしまいます。
そのため、接続しては捨て、を繰り返して多くの TCP コネクションが
張られた状態が発生します。

このような場合、受信(accept)した側はどうなるかというと、同じく
多くのスレッドが作成されます。送信側で close しない限り受信スレッド
は生き残りますので、close されずに ConnectionPool で捨てられると
受信スレッドもどんどん溜まります。

このような状態で put しようとします。put は
RoutingService.routeToRootNode にて格納先ノードを探しますが、この際に
メッセージを送信して探すことになります。運よく接続済みのコネクション
があればよいのですが、常にあふれている ConnectionPool では以下が
発生します。
(1)次の転送先へ接続、かつ ConnectionPool に登録。
(2)受信側が受信スレッド作成。このとき、デフォルトでは
 ConcurrentNonBlockingThreadPoolExecutor というスレッドプールにて
 スレッドを作成。
(3)受信スレッドは動かない。ow.util.concurrent.GlobalThreadPoolExecutors
 の初期値では 32 を越えるスレッドの場合、待機状態になるため。
 常に ConnectionPool があふれているような状態では既に多くの受信スレッド
 で埋まっているため。
(4)デフォルト値の 3 秒間を過ぎて停止させられるスレッドが出るまで
 待機させられる。
 ConnectionPool により受信スレッドがあふれている状態では、50 個近くまで
 スレッドが作られるため実際には 10 秒近く待つこともありえる。
(5)ここでやっと次のノードへメッセージを転送。しかし次のノードでも
 (2)~(4) が発生。
(6)最終的に、put のための routeToRootNode を行っている Querier が
 タイムアウト。
(7)タイムアウトのため put 先見つからず。
 ow.dht.impl.ChurnTolerantDHTImpl.put にて空の結果が返って
 例外発生。

このような流れになっていると思われます。

解決法ですが、ConnectionPool で捨てる際にちゃんと close をすれば
10分経過してもこのような事態にならないようです。

SocketChannel sc = connectionMap.remove(removedKey);
if (null != sc) {
try {
sc.close();
} catch (Exception e) {
}
}

こんなのを入れてやると良いようです。

以上です。


syuu さんは書きました:


__________ ESET Smart Security からの情報, ウイルス定義データベースのバージョン 4343 (20090817) __________

このメッセージは ESET Smart Security によって検査済みです。

http://canon-its.jp


Kazuyuki Shudo

unread,
Sep 12, 2009, 4:31:47 AM9/12/09
to overlayw...@googlegroups.com
驟雨さん、佐野さん、皆様、首藤です。

> Message-ID: <e9682100-f5fd-4d47...@x6g2000prc.googlegroups.com>
> From: syuu <uram...@gmail.com>
> Date: Tue, 8 Sep 2009 21:10:15 -0700 (PDT)

> こんにちは、Genkidamaの驟雨です。
>
> 本当はSourceforge.netのBug trackerに書くべきなのかもしれませんが、英語で書くのがしんどいのでこちらから失礼します。

いえ、そんなにたくさんの報告があるわけではないので、どんな形でも大丈夫です。
というか、bug tracker の方は見落としがちだったり..

> GenkidamaではDHTライブラリとしてOverlay Weaverを使わせて頂いているのですが、通信エラーが多発する為色々テストをおこ
> なってみた所、MessagingTransportとしてTCPを指定している時にある程度通信を行うとリクエストを受け付けなくなる現象が発生して
> いるらしい事がわかりました。
>
> テストには以下のコードを使用しました:
> http://syuu.dokukino.com/owtest/OWServerSimpleTest.java
>
> これを使って5ノード程度でネットワークを作り、数分ほど通信を続けていると以下のようなExceptionが発生します:
> ow.routing.RoutingException

はい、再現しました。

> Message-ID: <4AAA5AA9...@yahoo.co.jp>
> From: Tomonori Sano <omot...@yahoo.co.jp>
> Date: Fri, 11 Sep 2009 23:11:53 +0900

> 驟雨さん、こんにちは。佐野です。
>
> ご質問の原因について、確定ではないのですがご報告します。
> TCP で発生して UDP で発生しない、とのことなので
> ow.messaging.tcp.ConnectionPool を中心に流れを追ってみました。

御指摘の修正で、上の問題は発生しなくなりました。
ありがとうございます。

これだけ詳細に中身・挙動を把握して下さって、感激です。

首藤一幸

Kazuyuki Shudo

unread,
Sep 12, 2009, 4:56:41 AM9/12/09
to overlayw...@googlegroups.com
木本さん、皆様、首藤です。

> Message-Id: <20090911.151157...@ohnolab.org>
> From: Masahiko KIMOTO <kim...@ohnolab.org>
> Date: Fri, 11 Sep 2009 15:11:57 +0900 (JST)

> こんにちは、創夢の木本です。
>
> TTLまわりで不具合が出たので、OverlayWeaverの0.9と0.9.4を比較してみたところ、
> TTLを保持する変数がlongからintに変更になっていました。
> TTLはミリ秒でカウントされておりINTMAX/1000で頭打ちするようになっているようで、
> 最大のTTLが24日程度で頭打ちになってしまいます。

2009年 4月 25日、
0.9.1 と 0.9.2 の間で変更したようです:

2009-04-25 Kazuyuki Shudo <sh...@computer.org>
...

* src/ow/{dht/{*,impl/*},directory/{*,expiration/*}}.java
The type of TTL for key-value pairs on a DHT was changed
from long to int.
It saves memory usage.

おっしゃる通り、
int (32 bit 符号あり整数) → 24.x 日が上限になってます。

また、ow.dht.DHTConfiguration にて、TTL の上限を 7日間に設定してます:
... int DEFAULT_MAXIMUM_TTL = 7 * 24 * 60 * 60 * 1000; // 7 days
もっとも、こちらは、
この行の書き換え or DHTConfiguration オブジェクトに対する設定で変更できます。

たしかに、24.x 日というのは上限としては小さいように感じます。
少し考えます。

御意見ありがとうございます。

Kazuyuki Shudo/首藤一幸 私をたばねないで あらせいとうの花のように
20...@shudo.net http://www.shudo.net/

Masahiko KIMOTO

unread,
Sep 16, 2009, 1:22:45 AM9/16/09
to overlayw...@googlegroups.com, 20...@shudo.net
> > 最大のTTLが24日程度で頭打ちになってしまいます。
>
> 2009年 4月 25日、
> 0.9.1 と 0.9.2 の間で変更したようです:
>
> 2009-04-25 Kazuyuki Shudo <sh...@computer.org>
> ...
>
> * src/ow/{dht/{*,impl/*},directory/{*,expiration/*}}.java
> The type of TTL for key-value pairs on a DHT was changed
> from long to int.
> It saves memory usage.
>
> おっしゃる通り、
> int (32 bit 符号あり整数) → 24.x 日が上限になってます。
>
> また、ow.dht.DHTConfiguration にて、TTL の上限を 7日間に設定してます:
> ... int DEFAULT_MAXIMUM_TTL = 7 * 24 * 60 * 60 * 1000; // 7 days
> もっとも、こちらは、
> この行の書き換え or DHTConfiguration オブジェクトに対する設定で変更できます。
>
> たしかに、24.x 日というのは上限としては小さいように感じます。
> 少し考えます。

よろしくお願いします。
とりあえずこちらの実験は0.9.1で進めることにします。

Reply all
Reply to author
Forward
0 new messages