Eclipse生成的Web服务客户端非常慢 [英] Eclipse Generated Web Service Client Extremely Slow

查看:641
本文介绍了Eclipse生成的Web服务客户端非常慢的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个SOAP服务(使用JAX-WS(端点类)托管),但我不认为这很重要)





我可以通过Visual Studio生成客户端(C#)连接到Web服务并使用Web服务。



我使用Eclipse Web Tools(新 - >其他 - > Web服务 - > Web服务客户端)生成了一个Java客户机。



然后我写了一个JUnit测试来测试客户端。测试通过,但需要很长时间才能运行。每个服务电话需要300秒(给或几秒钟)。此外,计算机的速度并不重要。如果我运行在我非常缓慢的笔记本电脑上,它需要相同的时间,就像我在快速家用机上运行一样。



我已经调用了轴代码到org.apache.axis.encoding.DeserializationContext中的以下函数:

  public void parse()throws SAXException 
{
if(inputSource!= null){
SAXParser parser = XMLUtils.getSAXParser();
尝试{
parser.setProperty(http://xml.org/sax/properties/lexical-handler,this);
parser.parse(inputSource,this);

尝试{
//清理 - 以便解析器可以重复使用。
parser.setProperty(http://xml.org/sax/properties/lexical-handler,nullLexicalHandler);
} catch(Exception e){
//忽略。
}

没有惊喜,但是调用parser.parse()正在占用300秒从web服务是非常短的,所以它不应该花费很多时间来解析。



如果有人在想,解析器的实际类型是 com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl



我无法调试,因为我没有源头(我累了调用50个调用深入常用的库)。



我目前正在运行分析器以包含Sun的软件包。我会发布我的发现,一旦完成(添加所有这些软件包显着减慢测试)



我正在运行 Eclipse 3.5。 1 我正在使用 axis 1.4



编辑:



这是JUnit测试:

  @Test 
public void testExecuter )throws IOException,InterruptedException,RemoteException,ServiceException
{
// Listener l = new Listener(3456);
//l.start();
执行者exec = new ExecuterServiceLocator()。getExecuterPort();
// Executer exec = new ExecuterProxy(http:// localhost:3456 / Executer);
System.out.println(executer created);
_return remote = exec.execute(perl -e \print 5\,新的EvAction [0]);
System.out.println(after call 1);
assertEquals(5,remote.getStdout());
assertEquals(,remote.getStderr());
assertEquals(0,remote.getReturnCode());
}

注意:创建执行程序的两种方式都有相同的事情发生



Edit2:



以下是我用于启动服务的代码:

  public static void main(String [] args){
Endpoint.create(new Executer())。publish(http:// localhost: 3456 /执行器);
}

我不能发布网址,因为我刚刚开发一个机器现在但是,如果我去 http:// localhost:3456 / Executer?WSDL

 <! -  
JAX-WS RI发布于http://jax-ws.dev .java.net。 RI的版本是JDK 6中的JAX-WS RI 2.1.6。
- >
-
<! -
由JAX-WS RI生成的http://jax-ws.dev.java.net。 RI的版本是JDK 6中的JAX-WS RI 2.1.6。
- >
-
< definitions targetNamespace =http:// executer /name =ExecuterService>
-
< types>
-
< xsd:schema>
< xsd:import namespace =http:// executer /schemaLocation =http:// localhost:3456 / Executer?xsd = 1/>
< / xsd:schema>
< / types>
-
< message name =Execute>
< part name =parameterselement =tns:Execute/>
< / message>
-
< message name =ExecuteResponse>
< part name =parameterselement =tns:ExecuteResponse/>
< / message>
-
< message name =IOException>
< part name =faultelement =tns:IOException/>
< / message>
-
< message name =InterruptedException>
< part name =faultelement =tns:InterruptedException/>
< / message>
-
< portType name =执行者>
-
< operation name =Execute>
< input message =tns:Execute/>
< output message =tns:ExecuteResponse/>
< fault message =tns:IOExceptionname =IOException/>
< fault message =tns:InterruptedExceptionname =InterruptedException/>
< / operation>
< / portType>
-
< binding name =ExecuterPortBindingtype =tns:Executer>
< soap:binding transport =http://schemas.xmlsoap.org/soap/httpstyle =document/>
-
< operation name =Execute>
< soap:operation soapAction =/>
-
< input>
< soap:body use =literal/>
< / input>
-
< output>
< soap:body use =literal/>
< / output>
-
< fault name =IOException>
< soap:fault name =IOExceptionuse =literal/>
< / fault>
-
< fault name =InterruptedException>
< soap:fault name =InterruptedExceptionuse =literal/>
< / fault>
< / operation>
< / binding>
-
< service name =ExecuterService>
-
< port name =ExecuterPortbinding =tns:ExecuterPortBinding>
< soap:address location =http:// localhost:3456 / Executer/>
< / port>
< / service>
< / definitions>

编辑:



我认为这可能引起一个问题:



我使用TCPMonitor查看SOAP请求,我注意到客户端在说HTTP / 1.0,服务器在说HTTP / 1.1,但是我不知道这是否导致了这个问题。我正在试图找出如何让客户端说HTTP / 1.1。



以下是SOAP消息,以防任何人想知道:

  POST / Executer HTTP / 1.0 
Content-Type:text / xml; charset = utf-8
接受:application / soap + xml,application / dime,multipart / related,text / *
用户代理:Axis / 1.4
主机:USENBOONETL1C:2222
缓存控制:no-cache
Pragma:no-cache
SOAPAction:
Content-Length:354

<?xml version = 1.0encoding =UTF-8?>< soapenv:Envelope xmlns:soapenv =http://schemas.xmlsoap.org/soap/envelope/xmlns:xsd =http://www.w3。 org / 2001 / XMLSchemaxmlns:xsi =http://www.w3.org/2001/XMLSchema-instance>< soapenv:Body>< Execute xmlns =http:// executer /> < arg0 xmlns => perl -e& quot; print 5& quot;< / arg0>< / Execute>< / soapenv:Body>< / soapenv:Envelope>

和响应:

  HTTP / 1.1 200 OK 
内容类型:text / xml;
charset =utf-8
内容长度:266

<?xml version =1.0?< S:Envelope xmlns:S = http://schemas.xmlsoap.org/soap/envelope/\"><S:Body><ns2:ExecuteResponse xmlns:ns2 =http:// executer />< return>< stdout> 5℃; /标准输出>< stderr的>< / stderr的>< RETURNCODE大于0< / RETURNCODE>< /回报>< / NS2:ExecuteResponse>< / S:身体与GT;< / S:信封>

编辑:



最后!证明将HTTP客户端更改为CommonsHTTPClient并使用HTTP / 1.1修复了问题:



这是我添加到客户端的代码,它修复了它:

  BasicClientConfig basicClientConfig = new BasicClientConfig(); 
SimpleChain simpleChain = new SimpleChain();

simpleChain.addHandler(new CommonsHTTPSender());
basicClientConfig.deployTransport(http,simpleChain);

ExecuterServiceLocator l = new ExecuterServiceLocator(basicClientConfig);
...

注意:您必须添加 httpclient.jar common.codec.jar 到类路径。

解决方案

1)验证C#和Java客户端是否正在向服务器发送完全相同的请求。如果您使用的是Jetty,那么打开请求日志记录可能会给您您需要的数据。



2)一旦SAX解析器开始在客户端上运行,它将使得回调将直接或间接调用调用方法在您生成的客户端。您应该能够在生成的客户端方法的开头和结尾(和/或 return s)中设置断点,并使用它们来确定延迟发生的位置



(BTW,在SAX API中,URL如 http://xml.org/sax/properties/lexical-处理程序在本地用于标识属性名称;没有任何内容可以在该地址找到任何内容。请参见 http://xerces.apache.org/xerces2-j/properties.html 了解更多信息。)


A little up front info:

I have a SOAP service (hosted using JAX-WS (Endpoint class), but I don't think that is important).

I can connect to and use the web service just fine with Visual Studio generating the client (C#).

I generated a java client using Eclipse Web Tools (new --> other --> web services --> web services client).

Then I wrote a JUnit test to test the client. The test passes, but it takes an extremely long time to run. Each service call takes 300 seconds (give or take a couple seconds). Furthermore, it doesn't matter how fast the computer is. If I run this on my very slow work laptop it takes the same amount of time as if I run it on my fast home machine.

I have debugged into the axis code to the following function within org.apache.axis.encoding.DeserializationContext:

public void parse() throws SAXException
    {
        if (inputSource != null) {
            SAXParser parser = XMLUtils.getSAXParser();
            try {
                parser.setProperty("http://xml.org/sax/properties/lexical-handler", this);
                parser.parse(inputSource, this);

                try {
                    // cleanup - so that the parser can be reused.
                    parser.setProperty("http://xml.org/sax/properties/lexical-handler", nullLexicalHandler);
                } catch (Exception e){
                    // Ignore.
                }

no suprise, but the call to parser.parse() is taking up the 300 seconds. The from the web service is very short, so it shouldn't take much time to parse.

In case anyone is wondering, the actual type of parser is com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl

I can't debug into it because I don't have the source (and I'm tired up debugging 50 calls deep into commonly used libraries).

I'm currently running the profiler to include packages from Sun. I'll post my findings for that once it completes (adding all those packages significantly slows down the test)

I'm running Eclipse 3.5.1 and I'm using axis 1.4

Edit:

Here is the JUnit test:

@Test
public void testExecuter() throws IOException, InterruptedException, RemoteException, ServiceException
{
    //Listener l = new Listener(3456);
    //l.start();
    Executer exec = new ExecuterServiceLocator().getExecuterPort();
    //Executer exec = new ExecuterProxy("http://localhost:3456/Executer");
    System.out.println("executer created");
    _return remote = exec.execute("perl -e \"print 5\"", new EvAction[0]);
    System.out.println("after call 1");
    assertEquals("5", remote.getStdout());
    assertEquals("", remote.getStderr());
    assertEquals(0, remote.getReturnCode());
}

NOTE: Both ways of creating the Executer have the same thing happen

Edit2:

Here is the code I'm using to start the service:

public static void main(String[] args) {
    Endpoint.create(new Executer()).publish("http://localhost:3456/Executer");
}

I can't post the URL since I am just developping it on a single machine right now. However, here is the WSDL that is generated if I go to http://localhost:3456/Executer?WSDL

<!--
 Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.6 in JDK 6. 
-->
−
<!--
 Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.6 in JDK 6. 
-->
−
<definitions targetNamespace="http://executer/" name="ExecuterService">
−
<types>
−
<xsd:schema>
<xsd:import namespace="http://executer/" schemaLocation="http://localhost:3456/Executer?xsd=1"/>
</xsd:schema>
</types>
−
<message name="Execute">
<part name="parameters" element="tns:Execute"/>
</message>
−
<message name="ExecuteResponse">
<part name="parameters" element="tns:ExecuteResponse"/>
</message>
−
<message name="IOException">
<part name="fault" element="tns:IOException"/>
</message>
−
<message name="InterruptedException">
<part name="fault" element="tns:InterruptedException"/>
</message>
−
<portType name="Executer">
−
<operation name="Execute">
<input message="tns:Execute"/>
<output message="tns:ExecuteResponse"/>
<fault message="tns:IOException" name="IOException"/>
<fault message="tns:InterruptedException" name="InterruptedException"/>
</operation>
</portType>
−
<binding name="ExecuterPortBinding" type="tns:Executer">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
−
<operation name="Execute">
<soap:operation soapAction=""/>
−
<input>
<soap:body use="literal"/>
</input>
−
<output>
<soap:body use="literal"/>
</output>
−
<fault name="IOException">
<soap:fault name="IOException" use="literal"/>
</fault>
−
<fault name="InterruptedException">
<soap:fault name="InterruptedException" use="literal"/>
</fault>
</operation>
</binding>
−
<service name="ExecuterService">
−
<port name="ExecuterPort" binding="tns:ExecuterPortBinding">
<soap:address location="http://localhost:3456/Executer"/>
</port>
</service>
</definitions>

Edit:

I think this might be causing a problem:

I used TCPMonitor to look at the SOAP requests and I noticed that the client was speaking HTTP/1.0 and the server is speaking HTTP/1.1, but I don't know if this is causing the problem. I'm currently trying to figure out how to make the client speak HTTP/1.1.

Here are the SOAP messages in case anyone was wondering:

POST /Executer HTTP/1.0
Content-Type: text/xml; charset=utf-8
Accept: application/soap+xml, application/dime, multipart/related, text/*
User-Agent: Axis/1.4
Host: USENBOONETL1C:2222
Cache-Control: no-cache
Pragma: no-cache
SOAPAction: ""
Content-Length: 354

<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Body><Execute xmlns="http://executer/"><arg0 xmlns="">perl -e &quot;print 5&quot;</arg0></Execute></soapenv:Body></soapenv:Envelope>

and the response:

HTTP/1.1 200 OK
Content-type: text/xml;
charset="utf-8"
Content-length: 266

<?xml version="1.0" ?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns2:ExecuteResponse xmlns:ns2="http://executer/"><return><stdout>5</stdout><stderr></stderr><returnCode>0</returnCode></return></ns2:ExecuteResponse></S:Body></S:Envelope>

Edit:

Finally! turns out changing the HTTP client to CommonsHTTPClient and using HTTP/1.1 fixed the issue:

Here is the code I added to the client which fixed it:

BasicClientConfig basicClientConfig = new BasicClientConfig();
SimpleChain simpleChain = new SimpleChain();

simpleChain.addHandler(new CommonsHTTPSender());
basicClientConfig.deployTransport("http", simpleChain);

ExecuterServiceLocator l = new ExecuterServiceLocator(basicClientConfig);
...

note: You have to add common-httpclient.jar and common.codec.jar to the classpath.

解决方案

1) Verify that the C# and Java clients are sending exactly the same requests to the server. If you're using Jetty, turning on request logging would probably give you the data that you need.

2) Once the SAX parser starts running on the client, it's going to make callbacks that will wind up -- directly or indirectly -- invoking methods in your generated client. You should be able to set breakpoints at the beginning and end (and/or returns) of the generated client methods, and use these to determine where the delay[s] happen[s].

(BTW, in the SAX API, URLs such as http://xml.org/sax/properties/lexical-handler are used locally to identify property names; nothing is going to look for anything at that address. See http://xerces.apache.org/xerces2-j/properties.html for more info.)

这篇关于Eclipse生成的Web服务客户端非常慢的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆