2017-06-15 12 views
1

私はHTTPリクエストを受け取るJavaアプリケーションを作っています。入ってくるリクエストごとに、私は新しいスレッドを開始し、そのスレッドではリクエストを読んで必要なアクションを実行しています。しかし、私はユーザーが "Loris Attack"を実行しないようにしたいので、スレッドにmaxTimeという値を与えることを考えていました。スレッドがmaxTimeよりも時間がかかる場合、スレッドは何を終了しても終了します。したがって、遅い接続もブロックされます。ではなく、に問題があります。Java - メインスレッドをブロックせずに時間の経過とともにtheadを停止

しかし、これを行うには正しい方法がわかりません。私は次のコードを試しましたが、このコードは私のメインスレッドをブロックしています。私はメインスレッドをブロックすることなく、このような何かをする方法を探しています。

コード:

/** 
* Executor which is used for threadpools. 
*/ 
private ExecutorService executor; 

/** 
* Constructor for the class RequestReceiver. 
* Initializes fields. 
*/ 
public RequestReceiver() { 
    this.executor = Executors.newFixedThreadPool(200); 
} 

@Override 
public void run() { 
    try { 
     this.serverSocket = new ServerSocket(port); 
    } catch (IOException ex) { 
     Logger.getInstance().logText("Could not start server on port: " + port); 
     return; 
    } 

    Logger.getInstance().logText("Server running at port: " + port); 

    try { 
     while (shouldContinue) { 
      Socket client = serverSocket.accept(); 
      HTTPRequestHandler handler = new HTTPRequestHandler(client); 
      Thread t = new Thread(handler); 
      executor.submit(t).get(10, TimeUnit.SECONDS); //This line is blocking 
     } 
    } catch (IOException ex) { 
     Logger.getInstance().logText("Server is shutdown"); 
    } catch (InterruptedException | ExecutionException | TimeoutException ex) { 
     Logger.getInstance().logText("Thread took too long, it's shutdown"); 
    } 
} 
+0

executor.shutdown ; '文をブロックした直後' executor.submit(t).get(10、TimeUnit.SECONDS); ' – harshavmb

+0

@harshavmbこれが私の問題をどのように解決するのか分かりません。私はそれを試みました、そして、私が予想したように、それは墜落しました。なぜなら、2番目のHTTPリクエストを送信すると、プールはシャットダウンされているからです。 'java.util.concurrent.RejectedExecutionException' – Guido

+0

あなたのメインスレッドにFuture#を呼び出すのはなぜですか?あなたはそれで何もしません。さらに、TimeOutExceptionはタスクを停止しません。 – matt

答えて

1

あなたが望むものに似た何かを得ることができ、あなたの例に少なくとも変更は、新しいタスクを提出することです。

Socket client = serverSocket.accept(); 
HTTPRequestHandler handler = new HTTPRequestHandler(client); 
Future f = executor.submit(handler); 
executor.submit(()->{ 
    try{ 
     f.get(10, TimeUnit.SECONDS); 
    } catch(TimeoutException to){ 
     //timeout happened, this will cancel/interrupt the task. 
     f.cancel(true); 
    } catch(Exception e){ 
     throw new RuntimeException(e); 
     //something else went wrong... 
    } 
}); 

これは機能しますが、getコールを待つ追加のスレッドをブロックします。また、HTTPRequestHandlerコードで割り込みを処理する必要があります。

もう1つの方法は、ScheduledExecutorServiceを使用することです。

0

あなたのアプローチにはいくつかの問題があります。

私はHTTPリクエストを受信したJavaアプリケーションを作ってるんだが。入ってくるリクエストごとに、私は新しいスレッドを開始し、そのスレッドではリクエストを読んで必要なアクションを実行しています。

これは、メモリやその他のリソースを使い果たした確実な方法です。代わりに、サーブレットコンテナ(tomcat、jetty)内でアプリケーションを実行し、マルチスレッド処理を処理させます。要求を処理するコードが複数スレッドによって同時に呼び出されるため、スレッドセーフであることを確認してください。

ServerSocketを使用する必要がある場合は、固定数のスレッドでExecutorServiceを使用します。しかし、私はslowloris攻撃を防ぐために「スローロリス・アタック」

を実行できないようにしたい、あなたが後ろにアプリケーションを実行する必要があり

(スレッドの数に制限を使用することはありません) httpサーバー(Apacheなど)を開き、適切なセキュリティモジュールをインストールしてください。たとえば、次を参照してください。http://www.techrepublic.com/blog/smb-technologist/secure-your-apache-server-from-ddos-slowloris-and-dns-injection-attacks/

私はスレッドにmaxTime値を与えることを考えていました。スレッドがmaxTimeよりも時間がかかる場合、スレッドは何があっても終了します。

これはお勧めできません。一般に、HTTPリクエストを受信すると、コントローラ(リクエストを処理するコード)はできるだけ早く返信する必要がありますが、これを行う方法はリクエストの処理を最適化することです(たとえば、操作をしないHTTP要求を処理するには時間がかかりすぎます)。 処理時間が速いがクライアントの観点からはサーバーが応答しない場合は、アプリケーションの配布を考慮する必要があります(サーバーの多くのインスタンスをロードバランサの背後に置く)。

関連する問題