JTOpen KeyedDataQueue тайм-аут чтения ()
Я обнаружил странное поведение при использовании метода read(), предоставленного JTOpen KeyedDataQueue
учебный класс.
Я установил тайм-аут 90-х и для 99% выполнений чтения, когда тайм-аут достигнут, мое выполнение вызывающего метода возобновляется.
Что касается остальных 1%, тайм-аут не считается / не достигнут, и мой вызывающий метод остается зависшим...
После небольшого поиска я нашел этот пост:
http://archive.midrange.com/java400-l/201112/msg00056.html
В основном это подтверждает то, что я подозревал:
"Я также обнаружил, что функция тайм-аута DataQueue.read() находится на стороне сервера, поэтому, если соединение TCP/IP будет молча разорвано (что, по моему мнению, является основной причиной этого), оно все равно будет зависать".
Я использую версию 7.2 JTOpen, и я понимаю, что версия 7.9 уже существует. Я не обновил до 7.9, потому что у меня есть много критически важных приложений, использующих 7.2, которые стабильны, и на самом деле это первый реальный сценарий, который заставляет меня задуматься об обновлении до 7.9.
Чтобы помочь мне с этим решением, мне бы очень хотелось получить ваши отзывы, особенно от тех из вас, кто сталкивался с этой ситуацией и в конечном итоге решил ее путем обновления JTOpen.
В частности, есть ли обходные пути для этой проблемы, и помогает ли в этом обновление JTOpen? Повлияет ли обновление JTOpen до 7.9 на что-нибудь, что работало в 7.2?
1 ответ
Как упомянуто выше, тайм-аут чтения очереди данных находится на стороне сервера. Если TCP-соединение между iSeries и клиентом останавливается или умирает, клиент будет ждать до истечения времени ожидания сокета. Мое решение состоит в том, чтобы установить отказоустойчивый прерыватель, чтобы остановить остановленное чтение. Вот краткий пример того, как это можно сделать.
public class DataQueueListenerExample {
//This executes our Interrupter after the specified delay.
public final ScheduledThreadPoolExecutor interruptExecuter = new ScheduledThreadPoolExecutor(1);
//the dataqueue object.
protected DataQueue dataqueue;
public DataQueueEntry read(int wait)
{
ScheduledFuture<?> future = null;
try {
//create our fail safe interrupter. We only want it to
//interrupt when we are sure the read has stalled. My wait time is 15 seconds
future = createInterrupter(wait * 2, TimeUnit.SECONDS);
//read the dataqueue
return this.dataqueue.read(wait);
} catch (AS400SecurityException e) {
} catch (ErrorCompletingRequestException e) {
} catch (IOException e) {
} catch (IllegalObjectTypeException e) {
} catch (InterruptedException e) {
//The read was interrupted by our Interrupter
return null;
} catch (ObjectDoesNotExistException e) {
} finally{
//Cancel our interrupter
if(future != null && !future.isDone())
future.cancel(true);
Thread.interrupted();//clear the interrupted flag
interruptExecuter.shutdown();
}
return null;
}
public ScheduledFuture<?> createInterrupter(long timeout,TimeUnit timeunit)
{
return interruptExecuter.schedule(new Interrupter(),timeout,timeunit);
}
class Interrupter implements Runnable
{
final Thread parent;
Interrupter()
{
this.parent = Thread.currentThread();
}
@Override
public void run() {
parent.interrupt();
}
}
}
Я настоятельно рекомендую воссоздать объект DataQueue на новом соединении AS400 после исключения InterruptedException. Скорее всего, ваше AS400 соединение остановлено. Thread.interrupt очень полезен, но используйте его с осторожностью.