14歳の自分に衝撃の事実を告げてください

会社のftpサービスプログラムの負荷テストを任せられました。
このftpサービスはAndroidアプリからのアップロードを対象にしているのですが、
自社には、Android端末が2台しか無いので、
PCからプログラムでどうにか成らないか、試行錯誤をしております。

200kb くらいのデータを200 ユーザーから同時接続・アップロードの
試験をプログラミングで行いたいのです。
当方はJavaの初心者です。
Commons Net のライブラリを使用して
下記のマルチスレッドプログラムを作りました。
/*-------------------------------------------------------------------
import java.io.*;

import org.apache.commons.net.ftp.*;

public class CommNetFtp_Thread extends Thread {

// コンストラクタ 引数の count はローカルの一つのアップロード対象ファイルを
// 番号ファイル名としてリモートへアップロードするための整数値
public CommNetFtp_Thread( int count ) throws Exception{
FileInputStream istream = null;

// 以降は基本的な アップロードのコード (省略のため)
FTPClient ftpclient = new FTPClient();

try {
// サーバに接続
ftpclient.connect( "192.168.0.xxx" );
(省略)
//ログイン
if ( ftpclient.login("username", "password") == false ) {
System.err.println("login fail. Cont: "+ count );
}

// バイナリモードに設定
(省略)
// ファイル送信
istream = new FileInputStream( "D0000111111111111111.wav" );
ftpclient.storeFile( count +".wav", istream );

} catch(Exception e) {
e.printStackTrace();
(例外処理コードも省略させていただきます)
}
}

public void run() {

}
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {

CommNetFtp_Thread th1 = new CommNetFtp_Thread( 1 );
CommNetFtp_Thread th2 = new CommNetFtp_Thread( 2 );
// このコードを th200 まで書く(省略)

th1.start();
th2.start();
// このコードを th200 まで書く(省略)
}
}

このようなコードで、同時に複数のコネクションを張り、アップロードが行われたと考えてよろしいのでしょうか?
このプログラムの実行と同時に
リモート側で、"netstat -an" コマンドで、21ポートが複数の ESTABLISH状態を確認できたので、
複数のコネクションが張れてる、と想像しましたが。

どなたか明確な答えをお持ちではないでしょうか?

A 回答 (2件)

> 4 ,5つのftp接続が同時に行われていることを確認しました。


ということですから、同時に4,5スレッドからのリクエストが発生している状況は作れているでしょう。

無限ループでというのは、

public void run() {
System.out.println("Thread-" + count + ": start.");
while(isStop) {
ログイン処理
転送処理
ログアウト処理
}
}

としておけば、常にスレッド数分のリクエストが投げられている状態になるという事です。

ついでに、スレッドを起動する側で
int MAX_THREAD = 200;
TestFtp testFtp[] = new TestFtp[MAX_THREAD];
for (int i=0; i<MAX_THREAD; i++){
TestFtp testFtp[i] = new TestFtp(i);
testFtp[i].start();
Thread.sleep(30000);// 30秒毎にスレッド追加
}
Thread.sleep(10*60*1000);//10分放置

for (int i=0; i<MAX_THREAD; i++){
testFtp[i].isStop = true; // 停止要求
}

for (int i=0; i<MAX_THREAD; i++){
testFtp[i].join(); // 終了待ち
}
とでもしておけば、スレッド数の増加による影響も見れるんじゃないかな?
(ただし、クライアントが十分な性能を持っている場合)

なお、上記コードはコンパイルすらしていないのであしからず。
    • good
    • 0
この回答へのお礼

アドバイスありがとうございます

なるほどです。分かりやすい解説です。
ちなみに、 10コくらいの21ポートEstablish で同時接続を確認しました。
別の質問サイトで回答して頂いた方が仰るには、
『200KBのファイルぐらいなら直ぐに処理が終わるので、
同時に200接続が行われることは無いだろう』とのことでした。
しかし、今回はその完全同時200接続に拘ることはしないつもりです。
まず、スレッド処理の基本から学ぶつもりです。

長い質問にお付き合いいただき、本当に感謝してます。

お礼日時:2011/02/10 22:02

このコード、コンストラクタで転送してませんか?


スレッドを実行する前の、インスタンス生成時に、
転送終わっちゃってると思うんですが。

仮に、スレッドの実行時に転送するように書き換えても、
そのテストプログラムで保障できるのは、
一定期間内に、200リクエストの処理ができたという事であって、
同時に200リクエストを処理している訳ではありません。
(200リクエスト投げる前に、最初のリクエストが終わってたり、
コネクトについては逐次処理だろうし)

ログインから転送までの処理を無限ループにして、
最大200リクエストの並列処理ができるような
テストプログラムにした方が良いかもしれませんね。

クライアントPCの性能上、同時に200リクエスト投げるのが難しければ、
2台のPCから100スレッドずつとか、10台のPCから20スレッドずつとか
分散するのも手です。

ただし、同時に200転送するようにしたとしても、
ログイン部分は200リクエスト並列にさせるのは
難しいと思います。

200リクエスト分の転送には耐えられるはずなのに、
ログインの負荷には耐えられなくてエラーになる可能性まではテストできません。

蛇足になりますが、FTPの負荷試験程度なら、
JMeterとか使えば、コーディングしなくてもできますよ。

この回答への補足

import java.io.*;
import org.apache.commons.net.ftp.*;

public class TestFtp extends Thread {

int count ; // スレッド処理内で使用する数

// コンストラクタ
public TestFtp( int Cnt ) { // 戻り値にvoid を入れてはダメ
this.count = Cnt;

}
public void run() {
FileInputStream istream = null;

FTPClient ftpclient = new FTPClient();

try {
// サーバに接続
ftpclient.connect( "xxx.xxx.xxx.xx7" );
int reply = ftpclient.getReplyCode();
(省略)
//ログイン
(省略)
}

// バイナリモードに設定
ftpclient.setFileType(FTP.BINARY_FILE_TYPE);

// ファイル送信
istream = new FileInputStream( "D0000000000000000000.wav" );
ftpclient.storeFile( count +".wav", istream );

} catch(Exception e) {
e.printStackTrace();
}
finally {
if ( ftpclient.isConnected() )
try {
ftpclient.disconnect();
} catch (IOException e1) {

e1.printStackTrace();
}

if ( istream != null ) {
try {
istream.close();
}
catch(Exception e) {
e.printStackTrace();
}
}
}


} // run()終了


public static void main(String[] args) {



TestFtp th1 = new TestFtp( 1 );
TestFtp th2 = new TestFtp( 2 );
(このコードを 50まで書く)

th1.start();
th2.start();
(このコードを 50まで書く)
}

}

アップロードが失敗した回数分、
「java.net.SocketException: Connection reset 」がeclipseのコンソールに表れます。
以上

補足日時:2011/02/09 19:50
    • good
    • 0
この回答へのお礼

ありがとうございます。

貴交の仰る『ログインから転送までの処理を無限ループにして、』について、
今私は理解できていないのですが。

補足に書いたコードで、再度テストしてみました。
すると、なかなかの確率でアップロードに失敗していました。
一回のプログラム実行で、50のスレッドを生成しアップロードするテストにレベルを下げました。
( ちなみに、アップロード成功率は 83% )

上記のコードで、プログラム実行したと同時に、
サーバ側で > netstat -an をしましたら、
4 ,5つのftp接続が同時に行われていることを確認しました。
( 初期のコードでは、多くても 2つだった )

上記のコードは、同時に接続・リクエストしているプログラムと考えられますでしょうか?
恐縮ですが、ご回答頂けないでしょうか?

お礼日時:2011/02/09 19:49

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


おすすめ情報