Моему Websocket требуется вечность для подключения

ОБНОВЛЕНИЕ Кажется, что в конструкторе org.glassfish.tyrus.core.BaseContainer эти две строки выполняются очень медленно:

this.managedExecutorService = lookupManagedExecutorService();
this.managedScheduledExecutorService = lookupManagedScheduledExecutorService();

Что делать с упоминанием Android в комментариях к обоим методам, я использую неправильный код для Java, предназначенный для настольных компьютеров?


Я использую код точно так же, как и из:

Документация Tyrus Websocket: 1.1.2 Клиентская конечная точка

Каким-то образом подключение занимает около 10 секунд, особенно в этой строке, когда я запускаю отладчик Eclipse:

ClientManager client = ClientManager.createClient();

Может ли это быть связано с этим? Потенциально похожий вопрос о переполнении стека

Я действительно потерян, я чувствую, что я редкий выброс, пытающийся использовать веб-сокеты с клиентом Java, а не с браузером с Javascript.


person smuggledPancakes    schedule 22.05.2015    source источник
comment
Помните, что работа в режиме отладки может замедлить работу; оптимизация может работать не лучшим образом, сборка мусора и т. д.   -  person D. Ben Knoble    schedule 23.05.2015
comment
Попробуйте Тайрус 1.10. #createClient не должен занимать много времени, #connectToServer может (проблемы с сервером/сетью)   -  person Pavel Bucek    schedule 23.05.2015
comment
@Pavel, я использую tyrus-standalone-client-1.10.jar   -  person smuggledPancakes    schedule 27.05.2015
comment
Ах хорошо. Я видел 1.1.2, но на самом деле это ссылка, указывающая на документацию 1.9 ;) в любом случае, можете ли вы провести более подробные измерения? вы можете просто попытаться вызвать ClientManager.createClient несколько тысяч раз и посмотреть, сколько времени это займет (без подключенного отладчика). Обработка пути к классам может занять некоторое время, если он очень длинный.   -  person Pavel Bucek    schedule 27.05.2015
comment
Я только что заметил ваше ОБНОВЛЕНИЕ; это будет означать, что время тратится на окончательный класс ‹?› aClass = Class.forName(javax.naming.InitialContext);, который, как ожидается, завершится ошибкой на Android - это причина?   -  person Pavel Bucek    schedule 27.05.2015
comment
Строки 180 и 200 в BaseContainer.java занимают около шести секунд для выполнения вызова Method.invoke(). Я не могу понять, почему, и я не вижу ничего в Google о том, что эти звонки занимают слишком много времени...   -  person smuggledPancakes    schedule 27.05.2015
comment
Мне нужно, чтобы JVM не требовала 5-6 секунд, чтобы попытаться найти каждую службу, я бы предпочел, чтобы они сразу потерпели неудачу или не пытались вообще. Код для поиска этих сервисов находится в BaseContainer, и я не могу его переопределить :(   -  person smuggledPancakes    schedule 27.05.2015
comment
Еще одно обновление: кажется, что когда я запускаю свой код без контекста JNDI, он работает быстро. Нет исключения типа начального контекста и он не зависает на пять секунд. Когда у меня есть ошибочный контекст JNDI, он зависает... проблема в том, что я не могу легко обойти ошибочный контекст JNDI вне производства. Я должен буду что-то придумать.   -  person smuggledPancakes    schedule 28.05.2015
comment
Попробуйте System.setProperty(javax.naming.InitialContext.INITIAL_CONTEXT_FACTORY, "javax.naming.spi.InitialContextFactory");, прежде чем звонить createClient. Это должно быстро привести к сбою поиска JNDI. В моих тестах клиент создается менее чем за 100 мс. (как вариант Grizzly, так и Jdk).   -  person vanOekel    schedule 28.05.2015
comment
@vanOekel, если вы превратите свой комментарий в ответ, я приму его. Работает ☜(⌒▽⌒)☞   -  person smuggledPancakes    schedule 28.05.2015


Ответы (1)


Таким образом, причиной проблем является инициализация InitialContext компанией Tyrus для повторного использования (запланированного) сервиса-исполнителя, если он доступен. Обычно это быстро дает сбой, если ничего не доступно (и это регистрируется как сообщение отладки, см. далее), но в этом случае это не удалось только после попытки инициализировать INITIAL_CONTEXT_FACTORY не работает. Чтобы переопределить это поведение, вызовите
System.setProperty(javax.naming.InitialContext.INITIAL_CONTEXT_FACTORY, "javax.naming.spi.InitialContextFactory")
перед созданием клиента. Затем первоначальный InitialContext попытается создать экземпляр интерфейса, и это быстро завершится ошибкой.

Проблемы, вероятно, можно было обнаружить раньше с подробным ведением журнала. Tyrus не ведет большого количества журналов (отладки), но в этом случае установка с jul поверх logback могла бы показать раннее указание на основные проблемы. Общее правило: всегда убедитесь, что вы можете просмотреть журнал трассировки/отладки, когда сталкиваетесь со странными проблемами.

Что касается комментариев Android в исходном коде: это просто платформа, на которой была замечена несовместимость с «профилем JDK8 compact2», и она была решена путем отказа от прямого импорта класса javax.naming.InitialContext (поскольку, по-видимому, он не существует в профиле compact2) но вместо этого используется отражение (см. также TYRUS-242).

Если вы создаете исключительно Java-клиент Websocket, рассмотрите возможность использования клиента JDK 7. . Пакет клиента JDK 7 (org.glassfish.tyrus:tyrus-container-jdk-client:1.10) значительно меньше стандартного (org.glassfish.tyrus.bundles:tyrus-standalone-client:1.10).

Я также чувствовал себя аутсайдером, когда начал использовать веб-сокеты с клиентом Java (я выбираю Jetty websocket client API реализация). Я также начал больше использовать встроенные Tomcat (например, basic-jsp-embed). При объединении этих методов вы получаете мощное («полнодуплексное») сетевое решение (больше похожее на одноранговую сеть, а не на клиент-сервер). Надеюсь, это приживется.
Необходимо помнить одно предостережение: некоторые брандмауэры разрывают соединения (выглядящие как http-соединения) через 30 минут (даже если соединение используется). Поэтому для стабильного соединения убедитесь, что клиент отправляет регулярные пинг-сообщения, чтобы обеспечить работоспособное соединение, и создает новое соединение в течение или каждые 30 минут.

person vanOekel    schedule 28.05.2015