关于httpclient:HttpClient-在vivo内销浏览器的高并发实践优化

作者:vivo 互联网服务器团队- Zhi GuangquanHttpClient作为Java程序员最罕用的Http工具,其对Http连贯的治理能简化开发,并且晋升连贯重用效率;在失常状况下,HttpClient能帮忙咱们高效治理连贯,但在一些并发高,报文体较大的状况下,如果再遇到网络稳定,如何保障连贯被高效利用,有哪些优化空间。 一、问题景象北京工夫X月X日,浏览器信息流服务监控出现异常,次要体现在以下三个方面: 从某个工夫点开始,云监控显示局部Http接口的熔断器被关上,而且从明细列表能够发现问题机器: 2. 从PAAS平台Hystrix熔断治理界面中能够进一步确认问题机器的所有Http接口调用均呈现了熔断: 3. 日志核心有大量从Http连接池获取连贯的异样:org.apache.http.impl.execchain.RequestAbortedException: Request aborted。 二、问题定位综合以上三个景象,大略能够揣测出问题机器的TCP连贯治理出了问题,可能是虚拟机问题,也可能是物理机问题;与运维与零碎侧沟通后,发现虚拟机与物理机均无显著异样,第一工夫分割运维重启了问题机器,线上问题失去解决。 2.1 长期解决方案几天当前,线上局部其余机器也陆续呈现了上述景象,此时根本能够确认是服务自身有问题;既然问题与TCP连贯相干,于是分割运维在问题机器上建设了一个作业查看TCP连贯的状态散布: netstat -ant|awk '/^tcp/ {++S[$NF]} END {for(a in S) print (a,S[a])}'后果如下: 如上图,问题机器的CLOSE\_WAIT状态的连接数曾经靠近200左右(该服务Http连接池最大连接数设置的250),那问题间接起因根本能够确认是CLOSE\_WAIT状态的连贯过多导致的;本着第一工夫先解决线上问题的准则,先把连接池调整到500,而后让运维重启了机器,线上问题临时失去解决。 2.2 起因剖析调整连接池大小只是临时解决了线上问题,然而具体起因还不确定,依照以往教训,呈现连贯无奈失常开释根本都是开发者使用不当,在应用实现后没有及时敞开连贯;但很快这个想法就被否定了,起因不言而喻:以后的服务曾经在线上运行了一周左右,两头没有经验过发版,以浏览器的业务量,如果是连贯应用完没有及时关。 闭,250的连接数连一分钟都撑不到就会被打爆。那么问题就只能是一些异样场景导致的连贯没有开释;于是,重点排查了下近期上线的业务接口,尤其是那种数据包体较大,响应工夫较长的接口,最终把指标锁定在了某个详情页优化接口上;先查看处于CLOSE_WAIT状态的IP与端口连贯对,确认对方服务器IP地址。 netstat-tulnap|grep CLOSE_WAIT 通过与合作方确认,指标IP均来自该合作方,与咱们的揣测是相符的。 2.3 TCP抓包在定位问题的同时,也让运维共事帮忙抓取了TCP的数据包,结果表明的确是客户端(浏览器服务端)没返回ACK完结握手,导致挥手失败,客户端处于了CLOSE_WAIT状态,数据包的大小也与狐疑的问题接口相符。 为了不便大家了解,我从网上找了一张图,大家能够作为参考: CLOSE\_WAIT是一种被动敞开状态,如果是SERVER被动断开的连贯,那么就会在CLIENT呈现CLOSE\_WAIT的状态,反之同理; 通常状况下,如果客户端在一次http申请实现后没有及时敞开流(tcp中的流套接字),那么超时后服务端就会被动发送敞开连贯的FIN,客户端没有被动敞开,所以就停留在了CLOSE_WAIT状态,如果是这种状况,很快连接池中的连贯就会被耗尽。 所以,咱们明天遇到的状况(处于CLOSE_WAIT状态的连接数每天都在迟缓增长),更像是某一种异样场景导致的连贯没有敞开。 2.4 独立连接池为了不影响其余业务场景,防止出现系统性危险,咱们先把问题接口连接池进行了独立治理。 2.5 深入分析带着2.3的疑难咱们认真查看一下业务调用代码: try { httpResponse = HttpsClientUtil.getHttpClient().execute(request); HttpEntity httpEntity = httpResponse.getEntity(); is = httpEntity.getContent(); }catch (Exception e){ log.error(""); }finally { IOUtils.closeQuietly(is); IOUtils.closeQuietly(httpResponse); }这段代码存在一个显著的问题:既敞开了数据传输流( IOUtils.closeQuietly(is)),也敞开了整个连贯(IOUtils.closeQuietly(httpResponse)),这样咱们就没方法进行连贯的复用了;然而却更让人纳闷了:既然每次都手动敞开了连贯,为什么还会有大量CLOSE_WAIT状态的连贯存在呢? 如果问题不在业务调用代码上,那么只能是这个业务接口具备的某种特殊性导致了问题的产生;通过抓包剖析发现该接口有一个显著特色:接口返回报文较大,均匀在500KB左右。那么问题就极有可能是报文过大导致了某种异样,造成了连贯不能被复用也不能被开释。 2.6 源码剖析开始剖析之前,咱们须要理解一个基础知识:Http的长连贯和短连贯。所谓长连贯就是建设起连贯之后,能够复用连贯屡次进行数据传输;而短连贯则是每次都须要从新建设连贯再进行数据传输。 ...

August 15, 2022 · 1 min · jiezi

关于httpclient:Appache-httpclient证书认证过程

tcp三次握手后,client开始和server进行SSL连贯,默认client用jdk的证书库对服务器证书进行认证,如果证书非法抛异样。如下示例代码 public static void main(String[] args) throws Exception { HttpClientBuilder builder = HttpClients.custom(); SSLContext sslContext = SSLContextBuilder.create().loadTrustMaterial(new TrustStrategy() { @Override public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { return false; } }).build();// builder.setSSLContext(sslContext); CloseableHttpClient client = builder.build(); HttpGet get = new HttpGet("https://expired.badssl.com/");// HttpGet get = new HttpGet("https://baidu.com"); try (CloseableHttpResponse resp = client.execute(get)) { System.out.println(resp.getStatusLine()); } }抛出证书异样,异样堆栈如下 Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: timestamp check failed at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296) at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509) at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216) at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979) at sun.security.ssl.Handshaker.process_record(Handshaker.java:914) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387) at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:436) at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:384) at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142) at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:376) at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:393) at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236) at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186) at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89) at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185) at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83) at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108) at com.learn.http.HttpClientTest.main(HttpClientTest.java:39)Caused by: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: timestamp check failed at sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:352) at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:249) at sun.security.validator.Validator.validate(Validator.java:260) at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324) at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229) at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124) at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1491) ... 20 moreCaused by: java.security.cert.CertPathValidatorException: timestamp check failed at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:135) at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:219) at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:140) at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:79) at java.security.cert.CertPathValidator.validate(CertPathValidator.java:292) at sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:347) ... 26 moreCaused by: java.security.cert.CertificateExpiredException: NotAfter: Mon Apr 13 07:59:59 CST 2015 at sun.security.x509.CertificateValidity.valid(CertificateValidity.java:274) at sun.security.x509.X509CertImpl.checkValidity(X509CertImpl.java:629) at sun.security.provider.certpath.BasicChecker.verifyTimestamp(BasicChecker.java:190) at sun.security.provider.certpath.BasicChecker.check(BasicChecker.java:144) at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:125) ... 31 more证书验证相干类类有两个局部组成,一个是appache的httpclient,还有一个是jsse.jar包,httpclient次要利用jsse.jar来实现SSL通信,浅蓝色背景是类是jsse的类,其余是httpclient 包的类 ...

July 3, 2022 · 2 min · jiezi

关于httpclient:Go-httpclient-常用操作

模块介绍httpclient 是基于 net/http  封装的 Go HTTP 客户端申请包,反对罕用的申请形式、罕用设置,比方: 反对设置 Mock 信息反对设置失败时告警反对设置失败时重试反对设置我的项目外部的 Trace反对设置超时工夫、Header 等申请阐明办法名形容httpclient.Get()GET 申请httpclient.PostForm()POST 申请,form 模式httpclient.PostJSON()POST 申请,json 模式httpclient.PutForm()PUT 申请,form 模式httpclient.PutJSON()PUT 申请,json 模式httpclient.PatchForm()PATCH 申请,form 模式httpclient.PatchJSON()PATCH 申请,json 模式httpclient.Delete()DELETE 申请配置阐明配置项配置办法设置 TTL 本次申请最大超时工夫httpclient.WithTTL(ttl time.Duration)设置 Header 信息httpclient.WithHeader(key, value string)设置 Logger 信息httpclient.WithLogger(logger *zap.Logger)设置 Trace 信息httpclient.WithTrace(t trace.T)设置 Mock 信息httpclient.WithMock(m Mock)设置失败时告警httpclient.WithOnFailedAlarm(alarmTitle string, alarmObject AlarmObject, alarmVerify AlarmVerify)设置失败时重试httpclient.WithOnFailedRetry(retryTimes int, retryDelay time.Duration, retryVerify RetryVerify)设置 TTL// 设置本次申请最大超时工夫为 5shttpclient.WithTTL(time.Second*5),设置 Header 信息能够调用屡次进行设置多对 key-value 信息。 // 设置多对 key-value 信息,比方这样:httpclient.WithHeader("Authorization", "xxxx"),httpclient.WithHeader("Date", "xxxx"),设置 Logger 信息传递的 logger 便于 httpclient 打印日志。 ...

January 25, 2021 · 2 min · jiezi

关于httpclient:Java之HttpClient调用WebService接口发送短信源码实战

摘要Java之HttpClient调用WebService接口发送短信源码实战 一:接口文档 二:WSDL 三:HttpClient办法HttpClient办法一 HttpClient办法二 HttpClient办法三 HttpClient办法四 四:封装soapXml办法(外围办法) 五:调用WebService接口 六:调用后果 七:短信后果 完结以上就是Java之通过HttpClient形式调用WebService接口的实现流程 作者:迷彩出处:Java源码网原文地址:https://javaymw.com/post/108

October 29, 2020 · 1 min · jiezi