Question

Lors du développement d'une application qui consomme un webservice externe j'ai généré les sources de la wsdl-url puis créé un client:

GeoIPServiceClient service = new GeoIPServiceClient();
GeoIPServiceSoap geoIPClient = service.getGeoIPServiceSoap();

Depuis la création de cette procuration prend un certain temps, je mis le client comme un attribut dans ma classe de service.

Mais je suis inquiet que le client est pas thread-safe et ce Webservice est largement utilisé dans l'application par threads simultanés (WebApp). Je ne peux pas trouver toute la documentation à ce sujet.

Par précaution j'ai commencé à utiliser un pool d'objets de clients de savon au lieu d'une responsabilité partagée.

Est-ce une précaution inutile? Quelle est la meilleure pratique lors de l'écriture des clients Xfire?

Je soupçonne une sorte de problème avec la concurrence xfire depuis que je régulièrement, sous forte charge, obtenir les threads bloqués et à la suite de cette l'application se bloque. Voici une décharge de filetage partiel:

"http-xx.xx.xx.xx-80-17" daemon prio=10 tid=0x00007f560d437000 nid=0x66cb waiting for monitor entry [0x00000000412b8000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at com.sun.xml.bind.v2.runtime.reflect.opt.Injector.inject(Injector.java:174)
    - waiting to lock <0x00007f561d44e1c0> (a com.sun.xml.bind.v2.runtime.reflect.opt.Injector)
    at com.sun.xml.bind.v2.runtime.reflect.opt.Injector.inject(Injector.java:85)
    at com.sun.xml.bind.v2.runtime.reflect.opt.AccessorInjector.prepare(AccessorInjector.java:87)
    at com.sun.xml.bind.v2.runtime.reflect.opt.OptimizedAccessorFactory.get(OptimizedAccessorFactory.java:165)
    at com.sun.xml.bind.v2.runtime.reflect.Accessor$FieldReflection.optimize(Accessor.java:253)
    at com.sun.xml.bind.v2.runtime.reflect.TransducedAccessor$CompositeTransducedAccessorImpl.<init>(TransducedAccessor.java:231)
    at com.sun.xml.bind.v2.runtime.reflect.TransducedAccessor.get(TransducedAccessor.java:173)
    at com.sun.xml.bind.v2.runtime.property.SingleElementLeafProperty.<init>(SingleElementLeafProperty.java:83)
    at sun.reflect.GeneratedConstructorAccessor165.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at com.sun.xml.bind.v2.runtime.property.PropertyFactory.create(PropertyFactory.java:124)
    at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.<init>(ClassBeanInfoImpl.java:171)
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:481)
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:315)
    at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:139)
    at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:117)
    at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:188)
    at sun.reflect.GeneratedMethodAccessor176.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:128)
    at javax.xml.bind.ContextFinder.find(ContextFinder.java:277)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:372)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:337)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:244)
    at org.codehaus.xfire.jaxb2.JaxbType.getJAXBContext(JaxbType.java:306)
    - locked <0x00007f565b3aee60> (a org.codehaus.xfire.jaxb2.JaxbType)
    at org.codehaus.xfire.jaxb2.JaxbType.writeObject(JaxbType.java:230)
    at org.codehaus.xfire.aegis.AegisBindingProvider.writeParameter(AegisBindingProvider.java:229)
    at org.codehaus.xfire.service.binding.AbstractBinding.writeParameter(AbstractBinding.java:273)
    at org.codehaus.xfire.service.binding.WrappedBinding.writeMessage(WrappedBinding.java:90)
    at org.codehaus.xfire.soap.SoapSerializer.writeMessage(SoapSerializer.java:80)
    at org.codehaus.xfire.transport.http.HttpChannel.writeWithoutAttachments(HttpChannel.java:56)
    at org.codehaus.xfire.transport.http.OutMessageRequestEntity.writeRequest(OutMessageRequestEntity.java:51)
    at org.apache.commons.httpclient.methods.EntityEnclosingMethod.writeRequestBody(EntityEnclosingMethod.java:499)
    at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:2114)
    at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1096)
    at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:398)
    at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)
    at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
    at org.codehaus.xfire.transport.http.CommonsHttpMessageSender.send(CommonsHttpMessageSender.java:369)
    at org.codehaus.xfire.transport.http.HttpChannel.sendViaClient(HttpChannel.java:123)
    at org.codehaus.xfire.transport.http.HttpChannel.send(HttpChannel.java:48)
    at org.codehaus.xfire.handler.OutMessageSender.invoke(OutMessageSender.java:26)
    at org.codehaus.xfire.handler.HandlerPipeline.invoke(HandlerPipeline.java:131)
    at org.codehaus.xfire.client.Invocation.invoke(Invocation.java:79)
    at org.codehaus.xfire.client.Invocation.invoke(Invocation.java:114)
    at org.codehaus.xfire.client.Client.invoke(Client.java:336)
    at org.codehaus.xfire.client.XFireProxy.handleRequest(XFireProxy.java:77)
    at org.codehaus.xfire.client.XFireProxy.invoke(XFireProxy.java:57)
    at $Proxy143.getMyMethod(Unknown Source)

Le vidage de fil contient un grand nombre de threads bloqués qui ressemblent à ceci.

Était-ce utile?

La solution

Je suppose que vous obtenez beaucoup de threads bloqués, le client est en fait thread-safe en tant que données d'objet ne sont pas corrompues :). Mais je suis d'accord, il est pas le traitement des concurrency d'une bonne façon.

1) Une observation est que le verrou final semble être mise en œuvre de JAXB et non XFire. Que faire si vous essayez d'utiliser différentes implémentation JAXB comme JaxMe ?

2) De plus, le procédé getJAXBContext en JaxbType est synchronisé. Et très probablement parce que vos fils ont accès à la même instance de JaxbType ils peuvent être bloqués.

En regardant cette méthode, je fait déplacé la synchronisation dans la méthode après presense contexte est vérifié:

if (context == null) {
    synchronized (this)  {
         ...

Cela permettra aux clients qui ont déjà JAXBContext initialisés sauter la synchronisation coûteuse.

Ma suggestion est soit essayer fixer le code vous-même et de faire un test ou soumettre un bug à XFire ou les deux.)

Autres conseils

dépend de la version de Xfire que vous utilisez, comme ils l'ont fixé quelques problèmes de sécurité des threads dans la version 1.2.5. Vous pouvez vérifier le bug soulevé http://jira.codehaus.org/browse/XFIRE-886 , et voir plus de détails sur la release notes hxxp: //xfire.codehaus.org/XFire+1.2.5+Release+Notes

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top