2010-03-16 24 views
1

Notre configuration système se compose de deux serveurs Weblogic 10.3: l'un héberge la couche de présentation et l'autre héberge les EJB. Le système fonctionne très bien sous une charge modérée pendant un certain temps (un à plusieurs jours) après la méthode EJB appelle à partir du serveur de présentation au démarrage du serveur EJB pour échouer avec l'erreur suivante:Les appels EJB Weblogic commencent à échouer sous une charge modérée avec OptionalDataException

java.rmi.RemoteException: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: java.io.OptionalDataException 

Trace de la pile:

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) 

Une fois la première exception OptionalDataException rencontrée, tous les appels suivants échouent avec le même résultat. Certaines sources suggèrent que cela peut être dû au fait que le port de multidiffusion de cluster est mal configuré. Cependant, ces serveurs n'appartiennent pas à un cluster. Le démarrage du serveur EJB résout toujours temporairement le problème, mais le problème semble se produire à nouveau après un certain temps.

Mise à jour: il semble que le problème est pas liée à un débordement du nombre de connexions socket après tout (voir ma réponse ci-dessous). Après avoir refusé la classification par réseau, nous avons fonctionné très régulièrement pendant une semaine, après quoi nous avons commencé à recevoir à nouveau OptionalDataExceptions sur le serveur de présentation (trace de pile ci-dessous). Il est très étrange que le système fonctionne bien pendant une semaine, puis commence à échouer.

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 

Nous obtenons le contexte initial tout à fait la manière standard:

Properties p = new Properties(); 
p.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory"); 
p.put(Context.PROVIDER_URL, serverPath); 
Context context = new InitialContext(p); 

Demande également à toutes les références obtenues échouent avec un OptionalDataException similaire. Le démarrage du serveur de présentation résout le problème temporairement.

+0

Le serveur EJB lance-t-il également une exception correspondante comme EOFException en même temps? Juste pour essayer de percer si le EJB Remote est invoqué du tout sur le serveur ou s'il échoue avant cela. – JoseK

+0

Un très bon point. Je ne suis pas sûr à 100% mais je pense que la requête échoue avant d'arriver au serveur EJB - au moins il n'y a rien dans les logs du serveur EJB. Le niveau de journalisation a été augmenté depuis, donc si cela devait se produire à nouveau, nous le saurons avec certitude. Le serveur était en cours d'exécution et continuait à traiter ses tâches planifiées internes pendant que le problème se produisait, de sorte qu'au moins nous sachions que le serveur pouvait se connecter à la base de données, etc – MarkoU

+0

Et concernant le Clustering où cette erreur se produit habituellement - veux-tu dire les deux serveurs ne font partie d'AUCUN cluster ou ne font pas partie du même cluster? Comme vous le savez beaucoup d'URL suggèrent l'interférence de multidiffusion de cluster pour cette erreur. – JoseK

Répondre

1

Enfin les OptionalDataExceptions sont l'historique. En bref, dans notre code d'application, un objet de valeur complexe (utilisé comme valeur de retour pour les invocations de méthodes distantes) avait une structure de données HashMap comme champ interne. Après avoir modifié le type de ce champ à SynchronizedMap, les exceptions facultatives ont cessé de se produire. Il semble que quelque part dans le code existant, cette carte est traitée de manière non thread-safe. Ce qui est étrange, c'est que cela n'a causé aucun problème avec WLS 8.1, mais que WLS 10 est entré dans un état où toutes les invocations de méthodes distantes suivantes (y compris les recherches JNDI) ont échoué.

1

Enfin, nous avons trouvé la solution à cela (Edit: plus tard, nous avons découvert que ce n'était pas la cause du problème, mais un problème sérieux distinct.Pour la solution finale, s'il vous plaît voir la réponse ci-dessous). Une fois que nous avons commencé à recevoir l'exception suivante nous avons eu sur les pistes de la cause:

<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) 

Sur le serveur de présentation, qui est en cours d'exécution sur un autre hôte que le serveur EJB, nous avons eu la possibilité

-Dweblogic.NetworkClassLoadingEnabled=true 

pour activer évidemment le chargement de classe à partir du serveur EJB. Ce que nous ne savions pas, c'est que l'utilisation de cette option peut entraîner l'ouverture d'un grand nombre de sockets réseau. En utilisant netstat, nous avons pu constater que plusieurs milliers de sockets étaient dans l'état CLOSE_WAIT ou FIN_WAIT_2. Il semble que tous les éléments de l'interface Web ont été chargés à partir du serveur EJB en plus des classes malgré le fait que le fichier war sur le serveur de présentation contenait tout cela. L'énorme quantité de sockets n'a pas entraîné de messages d'erreur "trop ​​de fichiers" puisque Weblogic supprime l'ulimit pour les fichiers dans son script de démarrage. En utilisant un serveur de test, nous avons découvert qu'un simple clic sur l'interface web de l'utilisateur a ouvert environ 30 sockets entre les deux serveurs.

Nous avons éliminé cette option et reconditionné la guerre sur le serveur de présentation pour contenir toutes les classes nécessaires, supprimant ainsi la nécessité d'classloading réseau. Cela a entraîné une diminution du nombre de connexions socket entre les deux serveurs de milliers à 1.

Dans un résumé, d'éviter le chargement des classes de réseau dans Weblogic si possible.