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 очень полезен, но используйте его с осторожностью.

Другие вопросы по тегам