代码之家  ›  专栏  ›  技术社区  ›  Albert Péter

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

  •  4
  • Albert Péter  · 技术社区  · 11 年前

    我对JAX-WSWebservices和ApacheCXF有点陌生。我们正在开发一个简单的客户端-服务器系统,它们之间的通信是通过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
    

    到目前为止,一切都很好。第三个请求是普通的HTTPPOST请求,使用SOAP调用客户端调用的函数。

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

    我调试了,在这种情况下哪个点被阻止了,它在 运行时间WSDLParser.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连接时,才会出现这个问题。如果我尝试使用与另一台计算机不同的客户端,并使用内部IP地址,则不会出现阻塞。当我尝试使用TCPMon并重定向端口时也不会。

    我希望我说得足够具体。任何帮助都将不胜感激,我已经被这个问题困扰了好几天了。提前谢谢!

    1 回复  |  直到 8 年前
        1
  •  4
  •   Paul Vargas    11 年前

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

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

    另请参阅: