Ho un servizio RESTful che funziona molto velocemente. Lo sto testando su localhost. Il client utilizza il modello Spring REST. Ho iniziato con un approccio ingenuo:Uso del modello Spring REST, creando troppe connessioni o lento
RestTemplate restTemplate = new RestTemplate(Collections.singletonList(new GsonHttpMessageConverter()));
Result result = restTemplate.postForObject(url, payload, Result.class);
Quando faccio un sacco di queste richieste, sto ottenendo la seguente eccezione:
Caused by: org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://localhost:8080/myservice":No buffer space available (maximum connections reached?): connect; nested exception is java.net.SocketException: No buffer space available (maximum connections reached?): connect
Questo è causato da connessioni non essere chiuso e appeso in TIME_WAIT stato. L'eccezione inizia quando le porte effimere sono esaurite. Quindi l'esecuzione attende che le porte siano di nuovo libere. Sto vedendo le massime prestazioni con pause lunghe. Il tasso che sto ottenendo è quasi quello di cui ho bisogno, ma ovviamente queste connessioni TIME_WAIT non sono buone. Testato sia su Linux (Ubuntu 14) che Windows (7), risultati simili in tempi diversi a causa di diversi intervalli delle porte.
Per risolvere il problema, ho provato a utilizzare HttpClient con HttpClientBuilder dalla libreria dei componenti Http di Apache.
RestTemplate restTemplate = new RestTemplate(Collections.singletonList(new GsonHttpMessageConverter()));
HttpClient httpClient = HttpClientBuilder.create()
.setMaxConnTotal(TOTAL)
.setMaxConnPerRoute(PER_ROUTE)
.build();
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));
Result result = restTemplate.postForObject(url, payload, Result.class);
Con questo client, non vedo eccezioni. Il client utilizza ora solo un numero molto limitato di porte effimere. Ma a prescindere dalle impostazioni che uso (TOTAL e PER_ROUTE), non riesco a ottenere le prestazioni di cui ho bisogno.
Utilizzando il comando netstat
, vedo che non ci sono molte connessioni fatte al server. Ho provato a impostare i numeri a diverse migliaia, ma sembra che il client non usi mai così tanto.
C'è qualcosa che posso fare per migliorare le prestazioni, senza aprire troppe connessioni?
UPDATE: Ho provato a installare numero di connessioni totali e per tratta a 5000 e il 2500 ma sembra ancora come il client non è la creazione di più di un centinaio (a giudicare dalle netstat -n | wc -l
). Il servizio REST è implementato usando JAX-RS ed è in esecuzione su Jetty.
UPDATE2: ora ho regolato il server con alcune impostazioni di memoria e sto ottenendo un throughput veramente buono. L'approccio ingenuo è ancora un po 'più veloce, ma penso che sia solo un piccolo overhead del pooling sul lato client.
L'errore "Nessun spazio disponibile sul buffer" è più correlato al sistema, meno con il codice. Un sacco di connessioni TIME_WAIT indicano che le connessioni non sono raggruppate. Non modificare le impostazioni TIME_WAIT, causerà più problemi di quanti ne risolva (http://vincent.bernat.im/en/blog/2014-tcp-time-wait-state-linux.html). Le solite cause per nessuno spazio disponibile sul buffer sono le schede di rete rotte o un piccolo wmem_max su Linux. Dovresti essere in grado di creare almeno da 50 a 60k connessioni a un host remoto sulla stessa porta prima di esaurire i socket (quadrupli IP). – mp911de