Başlamadan beri, her zaman InterruptedException ile nasıl başa çıkılacağı ve eğer çok fazla zaman alıyorlarsa http isteğinin nasıl iptal edileceği konusunda kafam karışmıştı. Müşterilerimize iki yöntem, senkronizasyon ve uyumsuzluk sağladığım bir kütüphanem var. Amaçları için uygun olduklarını düşündükleri yöntemi arayabilirler.AsyncRestTemplate HTTP isteği, çok fazla zaman alıyorlarsa nasıl iptal edilir?
- executeSync() - Bir sonuç olana kadar bekler, sonuç verir.
- executeAsync() - diğer şeyler yapıldıktan sonra gerekirse işlenebilir hangi derhal Geleceği döndürür.
Onlar kullanıcı kimliği ve zaman aşımı değeri vardır DataKey
nesneyi geçecek. Hangi makinenin kullanıcı kimliğine göre çağrı yapılacağını anlayacağız ve daha sonra bu makineyle bir URL oluşturacağız ve AsyncRestTemplate kullanarak URL'ye http çağrısı yapacağız ve daha sonra yanıtın başarılı olup olmadığına bağlı olarak onlara geri göndereceğiz.
geri bir ListenableFuture
döndürür AsyncRestTemplate
ait exchange yöntemini kullanıyorum ve o isteği o ben AsyncRestTemplate
gitti neden yüzden IO engelleme olmayan kullanır böylece MİT tabanlı istemci bağlantıları ile zaman uyumsuz olmayan engelleme mimarisini olmasını istedik. Bu yaklaşım problem tanımım için doğru geliyor mu? Bu kütüphane çok ağır yük altında üretimde kullanılacaktır. Aşağıda
public interface Client {
// for synchronous
public DataResponse executeSync(DataKey key);
// for asynchronous
public ListenableFuture<DataResponse> executeAsync(DataKey key);
}
Ve aşağıda arabiriminin benim uygulamasıdır:
public class DataClient implements Client {
// using spring 4 AsyncRestTemplate
private final AsyncRestTemplate restTemplate = new AsyncRestTemplate();
// for synchronous
@Override
public DataResponse executeSync(DataKey keys) {
Future<DataResponse> responseFuture = executeAsync(keys);
DataResponse response = null;
try {
response = responseFuture.get(keys.getTimeout(), TimeUnit.MILLISECONDS);
} catch (InterruptedException ex) {
// do we need to catch InterruptedException here and interrupt the thread?
Thread.currentThread().interrupt();
// also do I need throw this RuntimeException at all?
throw new RuntimeException("Interrupted", ex);
} catch (TimeoutException ex) {
DataLogging.logEvents(ex, DataErrorEnum.CLIENT_TIMEOUT, keys);
response = new DataResponse(null, DataErrorEnum.CLIENT_TIMEOUT, DataStatusEnum.ERROR);
responseFuture.cancel(true); // terminating the tasks that got timed out so that they don't take up the resources?
} catch (Exception ex) {
DataLogging.logEvents(ex, DataErrorEnum.ERROR_CLIENT, keys);
response = new DataResponse(null, DataErrorEnum.ERROR_CLIENT, DataStatusEnum.ERROR);
}
return response;
}
// for asynchronous
@Override
public ListenableFuture<DataResponse> executeAsync(final DataKey keys) {
final SettableFuture<DataResponse> responseFuture = SettableFuture.create();
final org.springframework.util.concurrent.ListenableFuture orig =
restTemplate.exchange(createURL(keys), HttpMethod.GET, keys.getEntity(), String.class);
orig.addCallback(
new ListenableFutureCallback<ResponseEntity<String>>() {
@Override
public void onSuccess(ResponseEntity<String> result) {
responseFuture.set(new DataResponse(result.getBody(), DataErrorEnum.OK,
DataStatusEnum.SUCCESS));
}
@Override
public void onFailure(Throwable ex) {
DataLogging.logErrors(ex, DataErrorEnum.ERROR_SERVER, keys);
responseFuture.set(new DataResponse(null, DataErrorEnum.ERROR_SERVER,
DataStatusEnum.ERROR));
}
});
// propagate cancellation back to the original request
responseFuture.addListener(new Runnable() {
@Override public void run() {
if (responseFuture.isCancelled()) {
orig.cancel(false); // I am keeping this false for now
}
}
}, MoreExecutors.directExecutor());
return responseFuture;
}
}
Ve müşteri kendi kodundan böyle arayacaktır -
// if they are calling executeSync() method
DataResponse response = DataClientFactory.getInstance().executeSync(dataKey);
// and if they want to call executeAsync() method
Future<DataResponse> response = DataClientFactory.getInstance().executeAsync(dataKey);
Şimdi soru şu -
http istek çok uzun sürersebiz
akım kurulumlaAsyncRestTemplate
çağrı kesme miyim? AslındaexecuteSync
yönteminde benim yukarıdaki kodda benimfuture
üzerindecancel
arıyorum ama bunu yapmak doğrulamak nasıl emin değilim emin ne olması gerektiği yapıyor? Geri yüklemeyi orijinal geleceğe yaymak istiyorum, böylece ilgili http isteğini (muhtemelen kaynakları kaydetmek için yapmak istiyorum) iptal edebilirim, bu yüzden executeAsync yöntemimde bir dinleyici ekledim.RestTemplate
çağrılarını kesemeyiz, ancak bunu yapıp yapamayacağımızıAsyncRestTemplate
'dan emin olamayız.AsyncRestTemplate
çağrılarını kesebileceğimizi söylersek, http çağrılarını kesmek için her şeyi doğru yapıyorum? Yoksa bunu yapmanın daha iyi/daha temiz bir yolu var mı? Veya şu anki tasarımımda Http isteğiniAsyncRestTemplate
ile iptal etme konusunda endişelenmeme gerek var mı? bu benim HTTP isteği anlamına mı ardından iptal edildi -// propagate cancellation back to the original request responseFuture.addListener(new Runnable() { @Override public void run() { if (responseFuture.isCancelled()) { orig.cancel(false); // I am keeping this false for now } } }, MoreExecutors.directExecutor());
, ben bazen (değil her) bazı CancellationException atıyor görebilir?
- Ayrıca
InterruptedException
catch bloğundaexecuteSync
yönteminde doğru şeyi yapıyorum? Eğer değilse, o zaman bununla başa çıkmanın doğru yolu nedir? Ve benim durumumdaInterruptedException
ile uğraşmak zorunda mıyım? - Varsayılan olarak
AsyncRestTamplete
, çağrıları engellemek ve iş parçacığı başına istek kullanmakta doğru mu? Varsa, mevcut kurulumumda NIO tabanlı istemci bağlantılarına sahip olmanın bir yolu var mı?
Herhangi açıklamalar/kod önerileri büyük yardımı olacaktır.
Tüm sorularınızı yanıtlayamıyorum, ancak "InterruptedException" catch bloğu içindeki geçerli dizgiyi kesmeniz gerekmediğini size söyleyebilirim. 'DataErrorEnum'unuza bir' CLIENT_INTERRUPTED 'değeri eklemek ve diğer catch bloklarınıza benzer bir hata yanıtı vermek isteyebilirsiniz. –
Tüm sorularınızı yanıtlayamıyorum, ancak neden bu amaçla soket zaman aşımlarını kullanmadığınızı merak ettim, hat üzerinden veri gönderiliyor ve yine de bağlantıyı iptal etmek istiyor musunuz? –