2009-08-06 45 views
1

当显影这消耗我已经产生从WSDL-URL的源,然后创建的客户端的外部web服务的应用程序:xfire客户端代理线程安全吗?

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

自创建这个代理的花费一些时间我设置客户端作为属性在我的服务班。

但我担心客户端不是线程安全的,这个web服务在应用程序中被并发线程(webapp)大量使用。我找不到关于此的任何文档。

为了防患于未然,我开始使用肥皂客户端的对象池而不是共享的客户端。

这是不必要的预防措施吗?编写xfire客户端时的最佳做法是什么?

我怀疑xfire的某种并发问题,因为我经常在高负载下遇到阻塞的线程,并因此导致应用程序崩溃。这里的一个局部线程转储:

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

线程转储含有大量阻塞的线程是这个样子的。

回答

1

我猜你会得到很多阻塞线程,客户端实际上是线程安全的,因为对象数据没有被破坏:)。但我同意它没有以一种好的方式处理并发。

1)一个观察结果是最终锁定似乎在JAXB实现中,而不是在XFire中。如果您尝试使用不同的JAXB实现(如JaxMe)会怎么样?

2)此外,同步JaxbType中的方法getJAXBContext。很可能是因为你的线程正在访问相同的JaxbType实例,它们可能会被阻塞。

望着那方法我真的感动同步进入方法方面presense检查后:

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

这将允许那些已经初始化的JAXBContext跳过昂贵的同步客户端。

我的建议是尝试自己修复代码并进行测试或向XFire提交错误,或者同时执行两项操作:)。

1

取决于您使用的Xfire版本,因为它们修复了版本1.2.5中的几个线程安全问题。您可以检查在http://jira.codehaus.org/browse/XFIRE-886处提出的错误,并在hxxp上查看发布说明的更多详细信息://xfire.codehaus.org/XFire+1.2.5+Release+Notes