FTP同時複数接続の負荷テスト方法と動作確認について

このQ&Aのポイント
  • 会社のftpサービスプログラムの負荷テストを任せられ、同時複数の接続方法と動作確認について質問があります。
  • 200kbのデータを200ユーザーから同時接続・アップロードの試験を行いたいと考えています。
  • Javaの初心者ですが、Commons Netのライブラリを使用してマルチスレッドプログラムを作成しましたが、実際に複数のコネクションが張られたかどうかについて明確な回答が欲しいです。
回答を見る
  • ベストアンサー

ftp 同時複数接続の負荷テスト方法は?

会社の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状態を確認できたので、 複数のコネクションが張れてる、と想像しましたが。 どなたか明確な答えをお持ちではないでしょうか?

  • brosis
  • お礼率94% (100/106)
  • Java
  • 回答数2
  • ありがとう数3

質問者が選んだベストアンサー

  • ベストアンサー
回答No.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(); // 終了待ち } とでもしておけば、スレッド数の増加による影響も見れるんじゃないかな? (ただし、クライアントが十分な性能を持っている場合) なお、上記コードはコンパイルすらしていないのであしからず。

brosis
質問者

お礼

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

その他の回答 (1)

回答No.1

このコード、コンストラクタで転送してませんか? スレッドを実行する前の、インスタンス生成時に、 転送終わっちゃってると思うんですが。 仮に、スレッドの実行時に転送するように書き換えても、 そのテストプログラムで保障できるのは、 一定期間内に、200リクエストの処理ができたという事であって、 同時に200リクエストを処理している訳ではありません。 (200リクエスト投げる前に、最初のリクエストが終わってたり、 コネクトについては逐次処理だろうし) ログインから転送までの処理を無限ループにして、 最大200リクエストの並列処理ができるような テストプログラムにした方が良いかもしれませんね。 クライアントPCの性能上、同時に200リクエスト投げるのが難しければ、 2台のPCから100スレッドずつとか、10台のPCから20スレッドずつとか 分散するのも手です。 ただし、同時に200転送するようにしたとしても、 ログイン部分は200リクエスト並列にさせるのは 難しいと思います。 200リクエスト分の転送には耐えられるはずなのに、 ログインの負荷には耐えられなくてエラーになる可能性まではテストできません。 蛇足になりますが、FTPの負荷試験程度なら、 JMeterとか使えば、コーディングしなくてもできますよ。

brosis
質問者

お礼

ありがとうございます。 貴交の仰る『ログインから転送までの処理を無限ループにして、』について、 今私は理解できていないのですが。 補足に書いたコードで、再度テストしてみました。 すると、なかなかの確率でアップロードに失敗していました。 一回のプログラム実行で、50のスレッドを生成しアップロードするテストにレベルを下げました。 ( ちなみに、アップロード成功率は 83% ) 上記のコードで、プログラム実行したと同時に、 サーバ側で > netstat -an をしましたら、 4 ,5つのftp接続が同時に行われていることを確認しました。 ( 初期のコードでは、多くても 2つだった ) 上記のコードは、同時に接続・リクエストしているプログラムと考えられますでしょうか? 恐縮ですが、ご回答頂けないでしょうか?

brosis
質問者

補足

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のコンソールに表れます。 以上

関連するQ&A

  • commons-netでのFTP送信について

    いつもお世話になっております。 commons-netを利用してのFTP送信を作成しています。 FTPClient fp = new FTPClient(); FileInputStream is = null; fp.setDefaultPort(21); fp.connect("XXX.XX.XXX.XX"); fp.login("ID", "PASS"); boolean isRemotePassive = fp.enterRemotePassiveMode(); fp.enterLocalPassiveMode(); fp.setFileType(FTP.BINARY_FILE_TYPE); is = new FileInputStream("送信ファイル"); fp.storeFile("送信先", is); fp.disconnect(); is.close(); と行っていますが、送信されません。 ログが見れないのでどこで落ちているのかわからない状況ですが、 firewallの設定がされている場合、上記方法で送信は可能でしょうか? 宜しくお願い致します。

    • ベストアンサー
    • Java
  • [C#]FTPでの複数のファイルのアップロード

    ネットで調べたところ1つのファイルであれば、 下記の記述でアップロードできることがわかったのですが、 別々のフォルダにあるにファイルを複数同時にアップロードするプログラムがわかりません。 どなたかご教示ください。よろしくお願いいたします。 using System; using System.Net; using System.IO; class FtpWebPut {  static void Main()  {   string uri = "ftp://servername/Upload/secret.png";   string myFile = "tmp.png";   WebRequest req = WebRequest.Create(uri);   req.Credentials = new NetworkCredential("user01", "mypassword");   req.Method = WebRequestMethods.Ftp.UploadFile;   using (Stream st = req.GetRequestStream())   using (FileStream fs = new FileStream(myFile, FileMode.Open))   {    Byte[] buf = new Byte[1024];    int count = 0;    do    {     count = fs.Read(buf, 0, buf.Length);     st.Write(buf, 0, count);    }    while (count != 0);   }  } }

  • commons-net-2.0の使用が出来ない

    commons-net-2.0の使用が出来ない javaでFTP接続をしようとし、とあるサイトの説明を見ながらやったのですが (1)Commons Netのダウンロードページからバイナリーのアーカイブをダウンロードする。(commons-net-2.0.zip) はい、まず「commons-net-2.0.zip」というのをダウンロードしました。 (2)適当な場所にアーカイブを展開する。 展開はされるのですが、最後の最後に 「commons-net-2.0¥commons-net-2.0-javadoc.jar」 - 正常に解凍でいません。CRCが一致しないか、出力先ファイルが使用中です。 と、出ます。原因がよくわかりません。 (3)展開したディレクトリーの「commons-net-2.0」の直下にあるcommons-net-2.0.jarを適当な場所にコピーする。 まず、「commons-net-2.0」の直下にcommons-net-2.0.jarというものがありません。 commons-net-2.0-javadoc.jarというものならあるのですが・・・。 なので、「commons-net-2.0-javadoc.jar」というのを外部jarの追加をしたのですが、 ソース中に「import org.apache.commons.net.ftp.FTPClient;」とやってもエラーがでて使用できません。 他に、「commons-net-2.0.zip」を「commons-net-2.0.jar」と、拡張子を変えて、 この「commons-net-2.0.jar」をクラスパスの設定で外部jar追加したけどやっぱりだめでした。 かれこれ3時間以上格闘してるのですが、さっぱりです。 どうか、 「commons-net-2.0.jar」を追加し、 「FTPClient ftpClient = new FTPClient();」 ↑これを使えるようにできるにはどうしたらいいかご教授願えないでしょうか? jarの追加とかクラスパスの追加に関して疎いもので・・・。 (ちなみにsun.net.ftp.FtpClient;の方は使う気はありません)

    • ベストアンサー
    • Java
  • オブジェクトのシリアル化について

    serializableを使ってオブジェクトの入出力を2つのファイルで行ないたいのですが、出力の部分が分からなくて困っています。どなたか教えてください。プログラムは下のように書いてみました。 シリアル化のプログラム import java.io.*; public class serialin implements Serializable { public static void main(String[] args) throws Exception { //シリアル化して書き出す FileOutputStream fs = new FileOutputStream("output"); ObjectOutputStream os = new ObjectOutputStream(fs); os.writeObject("Hello"); os.close(); } } ------------------------------------------------- 復元のプログラム import java.io.*; public class serialout { public static void main(String[] args) throws Exception { //シリアル化ストリームを読み込んでオブジェクトを復元 FileInputStream fs = new FileInputStream("output"); ObjectInputStream os = new ObjectInputStream(fs); } }

    • ベストアンサー
    • Java
  • 日本語名でエラーになる

    InputStream is = new FileInputStream("C:\\kiku.jpg"); アルファベットのときは問題ありませんが InputStream is = new FileInputStream("C:\\菊.jpg"); このようにファイル名に日本語が入るとエラーになります。 Exception in thread "main" java.lang.RuntimeException: java.io.FileNotFoundException いろいろ調べてみたんですが、分かりません。

    • ベストアンサー
    • Java
  • javaで大きなファイルを解析できますか?

    100MBくらいのアクセスログをjavaを使って解析しようと思うのですが、どうしても、エラーが出ます。 読み込み方が間違っているのでしょうか? まったくわかりません。 教えていただけないでしょうか? また、これを知ったきっかけも教えていただけましたら幸いです。 宜しくお願い致します。 読み込みの部分↓↓↓ class kaiseki { public static void main(String[] args) throws Exception { InputStream is = new FileInputStream("log.txt"); BufferedReader br = new BufferedReader(new InputStreamReader(is));

    • ベストアンサー
    • Java
  • ソースコードの流れについて

    下記ソースコードの流れを詳しく解説していただけませんか。表示結果が理解できません。 class Th extends Thread{ public void run(){ for(int i = 0; i < 2; i++)System.out.print(" "+ Main4_1_49.count + i); } } public class Main4_1_49{ static int count = 0; public static void main(String[] args){ Th[] tr = new Th[6]; for(int i = 0; i < 5; i++){ count++; tr[i] = new Th(); tr[i].setPriority(i * 2 + 1 ); tr[i].start(); } } }

  • Javaのサーブレットについて(マルチスレッド)

    サーブレットについて質問です。 サーブレットは1インスタンス・複数スレッドという形態で、 サーブレットコンテナにより管理されていると思います。 では、このコンテナ内では、どのように1インスタンス・複数スレッドを 実現しているのでしょうか? 以下、自分なりに考えたプログラムです。 たぶん、このようにすれば、1インスタンス・複数スレッドになるのかと思うのですが。 どなたかご教授願いますでしょうか。 よろしくお願いいたします。 【1インスタンス・複数スレッドプログラム例】 public class TestThread extends Thread { public void run() { System.out.println("TestThread.run()"); } public static void main(String[] args) { Thread tt = new TestThread(); Thread th1 = new Thread(tt); Thread th2 = new Thread(tt); th1.start(); th2.start(); } }

  • 「プログラミング」JAVAのエラーが解決できません。

    ホームページを見たり、メールチェックをしたり、数分間このプログラムを走らせると、 Address already in use: connect java や Connection refused: connect といったエラーメッセージが出ます。 どうすれば、解決するでしょうか? やさしいJAVAやインターネットで調べたのですが良い方法が分かりません。ぜひ、ご教示宜しくお願い致します。 import java.net.*; import java.io.*; import java.util.*; import java.text.*; class Test { public static void main(String[] args) throws Exception { String helloURL; for(int a=1; a<3000; a++) { helloURL = "http://shopping.yahoo.co.jp/"; Th th1 = new Th(helloURL); th1.start(); Thread.sleep(100); } } } class Th extends Thread { String helloURL = null; String line; Th(String str) { this.helloURL = str; } public void run() { try { URL url = new URL(helloURL); BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream(),"JISAutoDetect")); while ((line = in.readLine()) != null) { try { OutputStream os = new FileOutputStream("log.txt",true); BufferedWriter fr = new BufferedWriter(new OutputStreamWriter(os)); if(line.indexOf("ヤフー") != -1) { fr.write(line); } if(line.indexOf("あ") != -1) { fr.write(line); } fr.close(); os.close(); } catch(Exception e){System.out.println("エラー1 : "+e.getMessage());} } in.close(); } catch(Exception ex){System.out.println("エラー2 : "+ex.getMessage());} } }

    • ベストアンサー
    • Java
  • ファイルロック後の書き込みについて

    ファイルAをロックしファイルBを読み込み ファイルAに書き込むプログラムを作成しています。 単体起動では問題無く動くのですが 複数起動するとファイルの書き込みが行われなくなってしまいます。 ロックしたプログラム以外はロックエラーになり ロックについては正常に動いているように見えます。 なぜ書き込みが行われなくなってしまうかご教授いただけますか? import java.io.* ; import java.nio.*; import java.nio.channels.*; public class CopyFile { public static void main(String[] args) throws Exception { try{ FileInputStream fis = null; FileOutputStream output = null; FileChannel outChannel = null; FileLock outFileLock = null; byte buf[] = new byte[2048]; int len; int count = 0; if (args.length != 2) { System.out.println("使用法: java CopyFile ファイル名1 ファイル名2"); System.exit(0); } //if String source= args[0]; String target= args[1]; File sourceFile = new File(source); File targetFile = new File(target); fis = new FileInputStream(sourceFile); output = new FileOutputStream(targetFile); outChannel = output.getChannel(); outFileLock = outChannel.tryLock(); if (outFileLock == null) { System.out.println("rock error!!"); System.exit(0); } else { while ((len = fis.read(buf)) != -1) { output.write(buf, 0, len); count += len; } Thread.sleep(5000); output.flush(); output.close(); fis.close(); } }catch(Exception e){ System.out.println(e); } } } // Class CopyFile

    • ベストアンサー
    • Java

専門家に質問してみよう