2016-04-07 44 views
5

Mam problem z wysyłaniem jednocześnie żądań usługi odpoczynkowej; Wiadomości w kliencie (Apache JMeter) to "Resetowanie połączenia" dla niektórych żądań, w zależności od numeru żądania, na przykład, wysyłam 100 żądań, a odpowiedź serwera jest w 100% udana, ale jeśli wyślę 500 żądań, to 30 % odpowiedzi to błąd.Resetowanie połączenia zużywającego usługę REST (scala/spray)

java.net.SocketException: Connection reset 
    at java.net.SocketInputStream.read(SocketInputStream.java:196) 
    at java.net.SocketInputStream.read(SocketInputStream.java:122) 
    at org.apache.http.impl.io.AbstractSessionInputBuffer.fillBuffer(AbstractSessionInputBuffer.java:166) 
    at org.apache.http.impl.io.SocketInputBuffer.fillBuffer(SocketInputBuffer.java:90) 
    at org.apache.http.impl.io.AbstractSessionInputBuffer.readLine(AbstractSessionInputBuffer.java:281) 
    at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:92) 
    at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:61) 
    at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:254) 
    at org.apache.http.impl.AbstractHttpClientConnection.receiveResponseHeader(AbstractHttpClientConnection.java:289) 
    at org.apache.http.impl.conn.DefaultClientConnection.receiveResponseHeader(DefaultClientConnection.java:252) 
    at org.apache.http.impl.conn.ManagedClientConnectionImpl.receiveResponseHeader(ManagedClientConnectionImpl.java:191) 
    at org.apache.jmeter.protocol.http.sampler.MeasuringConnectionManager$MeasuredConnection.receiveResponseHeader(MeasuringConnectionManager.java:201) 
    at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:300) 
    at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:127) 
    at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:715) 
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:520) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805) 
    at org.apache.jmeter.protocol.http.sampler.HTTPHC4Impl.executeRequest(HTTPHC4Impl.java:517) 
    at org.apache.jmeter.protocol.http.sampler.HTTPHC4Impl.sample(HTTPHC4Impl.java:331) 
    at org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy.sample(HTTPSamplerProxy.java:74) 
    at org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase.sample(HTTPSamplerBase.java:1146) 
    at org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase.sample(HTTPSamplerBase.java:1135) 
    at org.apache.jmeter.threads.JMeterThread.process_sampler(JMeterThread.java:434) 
    at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:261) 
    at java.lang.Thread.run(Thread.java:745) 

zmodyfikowałem "application.conf", treść jest następny:

spray.can { 
    server { 
    server-header = spray-can/${spray.version} 
    ssl-encryption = off 
    pipelining-limit = 16 
    idle-timeout = 60 s 
    request-timeout = 30 s 
    timeout-timeout = 2 s 
    timeout-handler = "" 
    reaping-cycle = 250 ms 
    stats-support = on 
    remote-address-header = off 
    raw-request-uri-header = off 
    transparent-head-requests = on 
    chunkless-streaming = off 
    verbose-error-messages = on 
    request-chunk-aggregation-limit = 1m 
    response-header-size-hint = 512 
    bind-timeout = infinite 
    unbind-timeout = 1s 
    registration-timeout = 1s 
    default-host-header = "" 
    automatic-back-pressure-handling = on 
    back-pressure { 
     noack-rate = 10 
     reading-low-watermark = infinite 
    } 
    parsing = ${spray.can.parsing} 
    } 
    client { 
    user-agent-header = spray-can/${spray.version} 
    idle-timeout = 60 s 
    request-timeout = 40 s 
    reaping-cycle = 250 ms 
    response-chunk-aggregation-limit = 1m 
    chunkless-streaming = off 
    request-header-size-hint = 256 
    max-encryption-chunk-size = 1m 
    connecting-timeout = 30s 
    proxy { 
     http = default 
     https = default 
    } 
    ssl-tracing = off 
    parsing = ${spray.can.parsing} 
    } 
    host-connector { 
    max-connections = 80 
    max-retries = 8 
    max-redirects = 0 
    pipelining = enabled 
    idle-timeout = 30 s 
    client = ${spray.can.client} 
    } 
} 

Ustawienia JVM są:

-Xms1024M 
-Xmx2048M 
-Xss1M 
-XX:MaxPermSize=1024m 

WAŻNE: Ponieważ logiki bussines jest necesary że serwer obsługuje jednocześnie transakcje; 500 indywidualnych połączeń (transakcji) w mniej niż 5 sekund.

Odpowiedz

2

Twoje ustawienia wyglądają dobrze, a obsługa 500 żądań na sekundę zdecydowanie nie stanowi problemu.

Najprawdopodobniej przetwarzanie żądań trwa zbyt długo, tj. Ponad request-timeout + timeout-timeout = 32 sekundy. Musisz sprawdzić swoją architekturę i zobaczyć, gdzie i dlaczego spędza tyle czasu. Byłoby to dość niezwykłe w przypadku zwykłych usług internetowych, w których większość żądań jest wykonywana w milisekundach. Jeśli masz ciężkie przetwarzanie, które musisz zrobić, trwa dłużej niż limit czasu, możesz odpowiedzieć 202 Accepted i wykonać przetwarzanie w tle. Możesz zwrócić identyfikator URI, w którym klient może sprawdzić status żądania, lub użyć wywołania zwrotnego do klienta lub dowolnego innego mechanizmu, aby poinformować, że żądanie zostało wykonane.

Należy pamiętać, aby nie blokować samej trasy, w przeciwnym razie skutecznie zablokowałbyś wszystkie inne żądania, a Ty mógłbyś uzyskać błędy przekroczenia limitu czasu. Zobacz tę odpowiedź na przykład: Use a Dispatcher with Spray HttpService. Aby zaimplementować przetwarzanie żądań bez blokowania, zobacz: How does spray.routing.HttpService dispatch requests?.

Kilka pomysłów na rozwiązywanie problemów: 1) zmierzyć ile czasu zajmuje przetworzenie pojedynczego żądania i zobaczyć, jak się skaluje - czy masz rywalizację o zasoby? 2) sprawdź, czy twoja sieć i klient nie powodują przekroczenia limitu czasu - ich przekroczenie powinno być większe niż serwer.

1

Dziękuję za współpracę i za poświęcony czas Aleksey Izmailov.

Consulting Spray Documentation, muszę ustawić parametr spray.can.servertimeout-timeout = 500s, przy tej konfiguracji serwer 500S do zaakceptowania odpowiedź wniosek zrobić. Jeśli nie ma na nie czasu, wyślij komunikat o błędzie, aby wypełnić żądanie.

Celem tego jest uzyskanie limitu czasu na serwerze, aby otrzymać odpowiedź, więc zakończyłeś czas oczekiwania aplikacji (w moim przypadku request-timeout = 30 s). Jeśli ten czas (timeout-timeout) zostanie spełniony, a na pewno brak odpowiedzi, serwer w końcu zakończy żądanie.

spray.can { 
    server { 
    ... 
    timeout-timeout = 500 s 
    ... 
    } 
    }