changeTheGame
V2EX  ›  程序员

Java 调用 webservice 接口,为什么这么慢

By changeTheGame at 2021 年 1 月 8 日 · 4749 次点击

Java 调用 webservice 接口,为什么这么慢,有没有好的优化方案,本人目前改成 http 方式发 soap 消息调用,速度依旧很慢,维持在平均 100ms 下不来。 之前用 cxf 的 JaxWsDynamicClientFactory 速度更加慢,400ms 、500ms 都出现过。

这是现在使用 httpClient 的调用代码

public static String callWebSV(String urlWsdl,String soap,String soapAction){
        String result=null;
        try {
            CloseableHttpClient httpClient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(urlWsdl);
            httpPost.setHeader("Content-Type", "text/xml;charset=UTF-8");
            httpPost.setHeader("SOAPAction", soapAction);
            InputStreamEntity entity = new InputStreamEntity(new ByteArrayInputStream(soap.getBytes()));
            httpPost.setEntity(entity);
            CloseableHttpResponse response = httpClient.execute( httpPost);
            if (response.getStatusLine().getStatusCode() == org.apache.http.HttpStatus.SC_OK) {
                HttpEntity responseEntity = response.getEntity();
                String back = EntityUtils.toString(responseEntity);
                //log.info("httpClient 返回 soap:" + back);
                result=parseResult(back);
                log.info("httpClient 返回结果:" + result);
            } else {
                log.error("HttpClinet 返回状态码:" + response.getStatusLine().getStatusCode());
            }
        } catch (Exception e) {
            log.error("调用错误:",e);
        }
        return result;
    }
第 1 条附言  ·  2021 年 1 月 8 日
刚才看了一下,对方重启服务器后,我这重启代码,刚开始一段时间,大概半小时,速度维持在 20ms 左右。然后半个小时之后,速度下降到 100ms 到 1000ms 之间,也不知道是什么原因
24 条回复  •  2021-01-09 13:00:11 +08:00
opengps
   1
opengps  
   2021 年 1 月 8 日
本地调用慢,还是公网调用慢?还是接口逻辑慢?
changeTheGame
   2
changeTheGame  
OP
   2021 年 1 月 8 日
@opengps 同一网段服务器之间调用,我也不知道为啥慢
Aidenboss
   3
Aidenboss  
   2021 年 1 月 8 日
用链接复用了吗?
changeTheGame
   4
changeTheGame  
OP
   2021 年 1 月 8 日
@Aidenboss 链接复用是什么
tmackan
   5
tmackan  
   2021 年 1 月 8 日
@changeTheGame tcp 长连接?不太懂
tmackan
   6
tmackan  
   2021 年 1 月 8 日
@Aidenboss 是指异步阻塞的调用?这个只有在比较大并发的情况下有用。单次 url 请求,没啥用,类似的可以参考 gevent,只有在很多 url 请求的时候比较有效果
tmackan
   7
tmackan  
   2021 年 1 月 8 日
@Aidenboss 异步非阻塞 说错了
yamasa
   8
yamasa  
   2021 年 1 月 8 日
wireshark 把整个会话抓出来,按时间戳定位问题出在哪里。问题不一定在你代码里,说不定就是 peer 端响应慢。

soap 这种玩意儿真的该淘汰掉了,废话比 json 和 yml 都多,也没有压缩。考虑搞成 grpc 之类的吧。
djj0809
   9
djj0809  
   2021 年 1 月 8 日 via iPhone
httpclient 复用了么?
yamasa
   10
yamasa  
   2021 年 1 月 8 日
@changeTheGame 你的这个方法 callWebSV 如果是从多个 thread 大量并发调用,写法就是有问题的,httpClient 应该复用,而不是每次都 create 出来。这是比较重的资源。
changeTheGame
   11
changeTheGame  
OP
   2021 年 1 月 8 日
@yamasa 我就是多个线程并发调用这个方法的,httpClient 可以复用吗
yamasa
   12
yamasa  
   2021 年 1 月 8 日
@changeTheGame 那肯定得复用。而且还应该考虑配置 connPooling,连接池,以及 dead conn scanner 。一步一步优化。
securityCoding
   13
securityCoding  
   2021 年 1 月 8 日
持续的用 arthas trace 看一下 ,输出到文件,先把性能瓶颈范围确定下来
php8
   14
php8  
   2021 年 1 月 8 日 via Android
先在你这边压测一下对方
wucao219101
   15
wucao219101  
   2021 年 1 月 8 日
首先,你这边的 HttpClient 明显没有复用,每次都重新 create,HttpClient 是线程安全的可复用的,具体可以参考:
https://hc.apache.org/httpcomponents-client-ga/tutorial/html/fundamentals.html#d5e213

> HttpClient implementations are expected to be thread safe. It is recommended that the same instance of this class is reused for multiple request executions.

另外,可以在调用过程中加一下链路跟踪,最简单的方式就是加一个 Zipkin 观察一下,到底是客户端问题还是服务端问题。
wucao219101
   16
wucao219101  
   2021 年 1 月 8 日
另外,基本的 close 操作都没有做,CloseableHttpClient 、CloseableHttpResponse 这些都是用过后要关闭的资源,你都没 close,资源用过后都不关闭肯定有问题,当然 CloseableHttpClient 如果复用了就不需要 close,但是 CloseableHttpResponse 肯定是要 close 的。

参考官方案例: https://hc.apache.org/httpcomponents-client-ga/quickstart.html
wysnylc
   17
wysnylc  
   2021 年 1 月 8 日
org.apache.http.client.fluent
hantsy
   18
hantsy  
   2021 年 1 月 8 日
@changeTheGame

1,你的代码有点晕,看代码姑且说是 SOAP,SOAP 那一套可是国际标准的。 调用 SOAP WebService,太简单了。一般的 SOAP 服务只要从公开的 WSDL 生成客户端代码就可以像本地代码一样的用了。

这类工具很多,比如 NetBeans IDE 中集成了。https://netbeans.org/kb/docs/websvc/client.html

如果项目在本地,NetBeans 自动识别 Soap,拖放操作就可以生成。 另外还有 maven wsdl plugin 也可以生客户端代码。

2, 如果普通的 Http 操作,ApacheHttpClient 太笨重了,操作麻烦,当然功能比较全面。可以尝试 Okhttp 等。

另外 Java 11 自带的 HttpClient 直接用更简单: https://github.com/hantsy/quarkus-sandbox/blob/master/restclient-java11/src/main/java/com/example/PostResourceClient.java.
changeTheGame
   19
changeTheGame  
OP
   2021 年 1 月 9 日 via iPhone
@tmackan 我就是有很多数据网一个 webservice 接口推
changeTheGame
   20
changeTheGame  
OP
   2021 年 1 月 9 日 via iPhone
@wucao219101 谢谢大佬,有空我看看 zipkin 去
changeTheGame
   21
changeTheGame  
OP
   2021 年 1 月 9 日 via iPhone
@hantsy 谢谢大佬,我是用 soapui 测试工具生成的 soap 消息,目前放弃使用 http client 了,改回 cxf 调用了,领导急着要没时间改了,有空在看吧
Kirsk
   22
Kirsk  
   2021 年 1 月 9 日 via Android
这不是你的问题 是对方做了状态存储以至于越来越慢 真的吗这个问题需要链路分析?
hantsy
   23
hantsy  
   2021 年 1 月 9 日
@changeTheGame

SOAP WebService 调用还是用 SOAP Client 比较好,操作上一般可以将 SOAP WSDL 操作,直接映射到本地接口,然后直接调用。

NetBeans 集成应该最智能的,Metro 是 SUN 当年与 MS 和解后,在 Web Service 上合作的产物, 也是应用很广泛的。
生成 Client 代码的例子网上大把,花几分配置一下就完了。

其他也 SOAP Client 也不难,Apache CXF 个人我也不喜欢,但它的确应用很广。
changeTheGame
   24
changeTheGame  
OP
   2021 年 1 月 9 日
@hantsy 嗯嗯,知道了,谢谢
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
© 2026 V2EX · 47ms · 3.9.8.5