salmayan: Bir sunucudaPoolingHttpClientConnectionManager aşağıdaki ulaşmak için Bahar kullanıyorum bağlantıları
, ben bir XML-Format REST arayüzü üzerinden veri almak. Verileri JSON'a dönüştürmek ve başka bir Sunucuya göndermek istiyorum. Kodum (benim işveren gazabından kaçınmak için bazı hassas classnames/URL'ler kaldırıldı) şöyle görünür:
Ana/Konfigürasyon sınıfı:
package stateservice;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class App {
Logger log = LoggerFactory.getLogger(App.class);
public static void main(String[] args) {
System.out.println("Start!");
SpringApplication.run(StateServiceApplication.class, args);
System.out.println("End!");
}
@Bean
public RestTemplate restTemplate() {
log.trace("restTemplate()");
HttpHost proxy = new HttpHost("proxy_url", 8080);
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
// Increase max total connection to 200
cm.setMaxTotal(200);
cm.setDefaultMaxPerRoute(50);
RequestConfig requestConfig = RequestConfig.custom().setProxy(proxy).build();
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
httpClientBuilder.setDefaultRequestConfig(requestConfig);
httpClientBuilder.setConnectionManager(cm);
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(
httpClientBuilder.build());
return new RestTemplate(requestFactory);
}
}
RESTful arayüzü temsil sınıfı:
package stateservice;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import foo.bar.XmlData
@RestController
public class StateController {
private static Logger log = LoggerFactory.getLogger(DataController.class);
@Autowired
ForwarderService forwarder;
@RequestMapping(value = "/data", method = RequestMethod.POST)
public String postState(@RequestBody XmlData data) {
forwarder.forward(data);
return "Done!";
}
}
Son olarak, yönlendirici:
package stateservice;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import foo.bar.Converter;
import foo.bar.XmlData;
@Service
public class ForwarderService {
private static Logger log = LoggerFactory.getLogger(ForwarderService.class);
String uri = "forward_uri";
@Autowired
RestTemplate restTemplate;
@Async
public String forward(XmlData data) {
log.trace("forward(...) - start");
String json = Converter.convert(data);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
ResponseEntity<String> response = restTemplate.postForEntity(uri,
new HttpEntity<String>(json, headers), String.class);
// responseEntity.getBody();
// log.trace(responseEntity.toString());
log.trace("forward(...) - end");
return response.getBody();
}
}
Ancak Bağlantı Yöneticisi nadiren yeniden kullanım için bağlantıları serbest bırakıyor gibi görünüyor ve ek olarak, sistem CLOSE_WAIT durumunda (netstat kullanılarak görülebilir) bağlantıları ile su basıyor. Havuzdaki tüm bağlantılar kiralanır, ancak serbest bırakılmaz ve CLOSE_WAIT durumundaki bağlantı sayısı ulimit'e ulaşır ulaşmaz 'Çok fazla açık dosya var' istisnası var
Kodun çok iş parçacıklı yapısı nedeniyle Ben, bu soketlerin kapatılamayacağından şüpheleniyorum/bağlantılar serbest bırakılır, çünkü başka bir iş parçacığı bir şekilde onları engeller.
Sorunu çözmek için bana verebileceğiniz herhangi bir yardım veya ipucunu gerçekten takdir ediyorum.
Sizin kodunuz hoş görünüyor. Sunucunun yanıt verdiğini biliyor musunuz? 'requestFactory' içinde 'setConnectTimeout' ve' setReadTimeout' özelliklerini ayarlamayı denediniz mi? "ForwardedService" işlevini eşzamanlı olarak çağırdığınızda ('@ Async' olmadan) çalışır mı? – Ruben
Evet, sunucu yanıt veriyor (Durum '200 OK'). Zaman aşımlarını ayarladım ve iletme yöntemini eşzamanlı olarak çağırdım - hiçbir şey yardımcı olmadı. – pczora
Sahip olduğum tek öneri KeepAlive stratejisini yapılandırmak. [Http client docs] 'da bölüm 2.6'ya bakın (http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html) – Ruben