Вызовы Weblogic EJB начинают завершаться сбоем при умеренной нагрузке с помощью OptionalDataException
-
20-09-2019 - |
Вопрос
Наша система состоит из двух серверов Weblogic 10.3:в одном из них размещен уровень представления, а в другом - EJBS.Система работает нормально при умеренной нагрузке в течение некоторого времени (от одного до нескольких дней), после чего вызовы метода EJB с сервера презентаций на сервер EJB начинают завершаться сбоем со следующей ошибкой:
java.rmi.RemoteException: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: java.io.OptionalDataException
Трассировка стека:
java.io.OptionalDataException
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1349)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
at weblogic.utils.io.ChunkedObjectInputStream.readObject(ChunkedObjectInputStream.java:197)
at weblogic.rjvm.MsgAbbrevInputStream.readObject(MsgAbbrevInputStream.java:564)
at weblogic.utils.io.ChunkedObjectInputStream.readObject(ChunkedObjectInputStream.java:193)
at weblogic.jndi.internal.RootNamingNode_WLSkel.invoke(Unknown Source)
at weblogic.rmi.internal.BasicServerRef.invoke(BasicServerRef.java:589)
at weblogic.rmi.cluster.ClusterableServerRef.invoke(ClusterableServerRef.java:230)
at weblogic.rmi.internal.BasicServerRef$1.run(BasicServerRef.java:477)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:363)
at weblogic.security.service.SecurityManager.runAs(Unknown Source)
at weblogic.rmi.internal.BasicServerRef.handleRequest(BasicServerRef.java:473)
at weblogic.rmi.internal.wls.WLSExecuteRequest.run(WLSExecuteRequest.java:118)
Как только возникает первое исключение OptionalDataException, все последующие вызовы завершаются неудачей с тем же результатом.Некоторые источники предполагают, что это может быть связано с неправильной настройкой порта групповой рассылки кластера.Однако эти серверы не принадлежат кластеру.
Загрузка сервера EJB всегда временно устраняет проблему, но, похоже, проблема возникает снова через некоторое время.
Обновить:похоже, что проблема заключается в не в конце концов, это связано с переполнением количества подключений к сокетам (см. Мой собственный ответ ниже).После запрета загрузки сетевых классов мы работали очень стабильно в течение недели, после чего мы снова начали получать OptionalDataExceptions на сервере презентаций (трассировка стека ниже).Очень странно, что система отлично работает в течение недели, а затем начинает давать сбои.
javax.naming.CommunicationException [Root exception is java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.io.OptionalDataException]
at weblogic.jndi.internal.ExceptionTranslator.toNamingException(ExceptionTranslator.java:74)
at weblogic.jndi.internal.WLContextImpl.translateException(WLContextImpl.java:439)
at weblogic.jndi.internal.WLContextImpl.lookup(WLContextImpl.java:395)
at weblogic.jndi.internal.WLContextImpl.lookup(WLContextImpl.java:380)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
...
Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.io.OptionalDataException
at weblogic.rjvm.ResponseImpl.unmarshalReturn(ResponseImpl.java:234)
at weblogic.rmi.cluster.ClusterableRemoteRef.invoke(ClusterableRemoteRef.java:348)
at weblogic.rmi.cluster.ClusterableRemoteRef.invoke(ClusterableRemoteRef.java:259)
at weblogic.jndi.internal.ServerNamingNode_1030_WLStub.lookup(Unknown Source)
at weblogic.jndi.internal.WLContextImpl.lookup(WLContextImpl.java:392)
... 38 more
Caused by: java.io.OptionalDataException
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1349)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
at
weblogic.utils.io.ChunkedObjectInputStream.readObject(ChunkedObjectInputStream.java:197)
at weblogic.rjvm.MsgAbbrevInputStream.readObject(MsgAbbrevInputStream.java:564)
at
weblogic.utils.io.ChunkedObjectInputStream.readObject(ChunkedObjectInputStream.java:193)
at weblogic.jndi.internal.RootNamingNode_WLSkel.invoke(Unknown Source)
at weblogic.rmi.internal.BasicServerRef.invoke(BasicServerRef.java:589)
at weblogic.rmi.cluster.ClusterableServerRef.invoke(ClusterableServerRef.java:230)
at weblogic.rmi.internal.BasicServerRef$1.run(BasicServerRef.java:477)
at
weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:363)
at weblogic.security.service.SecurityManager.runAs(Unknown Source)
at weblogic.rmi.internal.BasicServerRef.handleRequest(BasicServerRef.java:473)
at weblogic.rmi.internal.wls.WLSExecuteRequest.run(WLSExecuteRequest.java:118)
... 2 more
Мы получаем начальный контекст вполне стандартным способом:
Properties p = new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
p.put(Context.PROVIDER_URL, serverPath);
Context context = new InitialContext(p);
Также вызовы любых полученных ссылок завершаются ошибкой с аналогичным OptionalDataException .Загрузка сервера презентаций сама по себе временно устраняет проблему.
Решение
Наконец, исключения OptionalDataExceptions - это история.Короче говоря, в коде нашего приложения объект complex value (используемый в качестве возвращаемого значения для вызовов удаленных методов) имел структуру данных HashMap в качестве внутреннего поля.После изменения типа этого поля на synchronizedMap исключения OptionalDataExceptions перестали возникать.Похоже, что где-то в устаревшем коде эта карта обрабатывается не потокобезопасным способом.
Что странно, так это то, что это не вызвало проблем с WLS 8.1, но каким-то образом привело к тому, что WLS 10 перешел в состояние, в котором все последующие вызовы удаленных методов (включая поиск JNDI) начали завершаться сбоем.
Другие советы
Наконец- то мы нашли решение этой проблемы (Править:позже мы выяснили, что это была не первопричина проблемы, а отдельная серьезная проблема.Для получения окончательного решения, пожалуйста, смотрите ответ ниже).Как только мы начали получать следующее исключение, мы вышли на след причины:
<BEA-000403> <IOException occurred on socket: Socket[addr=/x.x.x.x,port=3266,localport=7001]
java.net.SocketException: Connection refused.
java.net.SocketException: Connection refused
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at weblogic.socket.SocketMuxer.readReadySocketOnce(SocketMuxer.java:887)
at weblogic.socket.SocketMuxer.readReadySocket(SocketMuxer.java:859)
at weblogic.socket.DevPollSocketMuxer.processSockets(DevPollSocketMuxer.java:120)
at weblogic.socket.SocketReaderRequest.run(SocketReaderRequest.java:29)
at weblogic.socket.SocketReaderRequest.execute(SocketReaderRequest.java:42)
at weblogic.kernel.ExecuteThread.execute(ExecuteThread.java:145)
at weblogic.kernel.ExecuteThread.run(ExecuteThread.java:117)
На сервере презентаций, который работает на другом хосте, чем сервер EJB, у нас была опция
-Dweblogic.NetworkClassLoadingEnabled=true
чтобы, очевидно, включить загрузку класса с сервера EJB.Чего мы не знали, так это того, что использование этой опции может привести к открытию огромного количества сетевых сокетов.Используя netstat, мы смогли выяснить, что несколько тысяч сокетов находились либо в состоянии CLOSE_WAIT, либо в состоянии FIN_WAIT_2.Похоже, что все элементы веб-интерфейса были загружены с сервера EJB в дополнение к классам, несмотря на то, что файл war на сервере презентаций содержал все это.Огромное количество сокетов не привело к появлению сообщений об ошибках "слишком много файлов", поскольку Weblogic удаляет ограничение для файлов в своем сценарии запуска.Используя тестовый сервер, мы выяснили, что один щелчок пользователя по веб-интерфейсу открывает около 30 сокетов между двумя серверами.
Мы удалили эту опцию и переупаковали war на сервере презентаций, чтобы он содержал все необходимые классы, таким образом устранив необходимость в сетевой загрузке классов.Это привело к уменьшению количества сокет-соединений между двумя серверами с тысячи до 1.
Подводя итог, избегайте загрузки сетевого класса в Weblogic, если это вообще возможно.