当WSDL太大时,JAX-WS客户端挂起30秒

时间:2013-09-20 15:08:46

标签: java wsdl jax-ws blocking

我对JAX-WS Webservices和Apache CXF有点新鲜。我们正在开发一个简单的客户端 - 服务器系统,它们之间的通信是通过JAX-WS Web服务协议实现的。在服务器端,我们使用Apache CXF实现(因为使用拦截器),在客户端它是正常的参考实现( jax-ws-rt )。

我的问题如下:当客户端首先创建服务时:

service = Service.create(uri.toURL(), new QName(targetNamespace, serviceName));

然后它通常将GET请求发送到服务器,以获取和处理WSDL。首先是这样的:

GET .../services/ws/mainservice?wsdl

然后立即

GET .../services/ws/mainservice?wsdl=mainservice.wsdl

到目前为止,这么好。第三个请求是正常的HTTP POST请求,使用SOAP调用客户端调用的函数。

一切正常,直到WSDL太大。我可以从网络浏览器查看大小,例如,使用上面的两个GET链接。当第二个GET请求的响应达到100K大小(浏览器中的XML响应)时,因为在Web服务接口中声明的函数太多,所以会发生以下情况:客户端在第二个GET期间挂起大约30秒请求,然后一切都很好,功能运行。

我调试了,在这种情况下阻塞了哪一点,它在 RuntimeWSDLParser.java ,createReader()函数中,当它调用时:

private static XMLStreamReader createReader(URL wsdlLoc, Class<Service> serviceClass) throws IOException, XMLStreamException {
InputStream stream;
try {
    stream = wsdlLoc.openStream();
} catch (IOException io) {

}

,此文件位于客户端的jax-ws-rt.jar中。

奇怪的是(至少对我来说,但我并不熟悉它),如果我用调试器到达这一行,并立即跳过,那么大约30秒的阻塞。如果我等了25秒,然后我就踩了一下,那么它只有5秒钟。所以似乎在某个地方有一个反击。

另一件事:只有在我使用localhost连接时才会出现此问题。如果我尝试使用另一台计算机的differenc客户端,并使用内部IP地址,则没有阻塞。当我尝试使用TCPMon并且我重定向端口时也是如此。

我希望我足够具体。任何帮助将不胜感激,我几天坚持这个问题。提前谢谢!

1 个答案:

答案 0 :(得分:3)

今天你很幸运!有两种选择:

  1. 在本地使用WSDL文档文件

    将WSDL文档文件和schemma文件的副本保存到项目中。

    ClassLoader classloader = Thread.currentThread().getContextClassLoader();
    URL wsdlLocation = classloader.getResource("MyHelloService.wsdl");
    QName serviceName= new QName("http://test.com/", "MyHelloService");
    
    MyHelloService service = new MyHelloService(wsdlLocation, serviceName);
    service.sayHello("Test");
    
  2. 没有WSDL文档文件

    QName qname = new QName("http://thenamespace", "FooService");
    FooService service = new FooService(null, qname); // null for ignore WSDL
    Foo port = service.getFooPort();
    BindingProvider bindingProvider = (BindingProvider) port;
    bindingProvider.getRequestContext()
        .put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
        "http://foo.com/soap/fooBean");
    
    // Use the service
    Object obj = port.doSomething(param);
    

  3. 另见: