[英]Eclipse Generated Web Service Client Extremely Slow
一些前期信息:
我有一个SOAP服务(使用JAX-WS(端点类)托管,但是我认为这并不重要)。
通过Visual Studio生成客户端(C#),我可以连接并使用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();
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.
}
没有惊喜,但是对parser.parse()的调用占用了300秒。 来自网络的服务非常短,因此不需要花费很多时间来解析。
如果有人想知道,解析器的实际类型是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();
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());
}
注意:两种创建执行者的方式都会发生相同的事情
编辑2:
这是我用来启动服务的代码:
public static void main(String[] args) {
Endpoint.create(new Executer()).publish("http://localhost:3456/Executer");
}
我无法发布URL,因为我现在只是在一台机器上开发它。 但是,如果我转到http:// localhost:3456 / Executer?WSDL ,这是生成的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>
编辑:
我认为这可能会引起问题:
我使用TCPMonitor查看SOAP请求,并且注意到客户端正在使用HTTP / 1.0,而服务器正在使用HTTP / 1.1,但是我不知道这是否引起了问题。 我目前正在尝试弄清楚如何使客户端使用HTTP / 1.1。
如果有人在想,以下是SOAP消息:
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 "print 5"</arg0></Execute></soapenv:Body></soapenv:Envelope>
和响应:
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>
编辑:
最后! 原来将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);
...
注意:您必须将common-httpclient.jar
和common.codec.jar
添加到类路径。
我遇到了同样的问题,并解决了修改http版本的问题。
一种更简单的方法是在存根类内部,在Call实例上调用setProperty方法:
_call.setProperty(MessageContext.HTTP_TRANSPORT_VERSION,HTTPConstants.HEADER_PROTOCOL_V11);
1)验证C#和Java客户端正在向服务器发送完全相同的请求。 如果您使用的是Jetty,则打开请求日志记录可能会为您提供所需的数据。
2)一旦SAX解析器开始在客户端上运行,它将进行回调,这些回调将直接或间接地在生成的客户端中调用方法。 您应该能够在生成的客户端方法的开始和结束(和/或return
s)处设置断点,并使用这些断点来确定延迟发生的位置。
(顺便说一句,在SAX API中,本地使用http://xml.org/sax/properties/lexical-handler
类的URL来标识属性名称;在该地址什么也找不到。请参见http:// xerces.apache.org/xerces2-j/properties.html了解更多信息。)
您的问题正是我现在所面临的。 有趣的是,我经历了几乎相同的周期(端点服务,.net客户端工作正常,而eclipse生成的客户端花费了5分钟的处理时间)。 的确,感谢您发布更新和解决方案。 我不是精通Java的人,所以请问您是否将解决方案应用于相同的Eclipse生成的客户端代码? 还是您做了完全不同的事情? 如果您修改了eclipse生成的客户端代码,那么您到底在哪里添加了这些行?
谢谢,我也非常感谢您的帮助:)
干杯,阿拉什
最有可能是超时。 可能是该解析器试图从Internet(DTD,XSD等)下载内容,但您位于代理/防火墙的后面。
在运行测试时尝试获取服务器的堆栈跟踪信息,以查看发生了什么事情(例如jps / jstat)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.