此文已由做者赵慧莉受权网易云社区发布。
java
欢迎访问网易云社区,了解更多网易技术产品运营经验。web
最近在作内容分发网络(Content Delivery Network,简称 CDN)CDN的后端线上回归集监控时,经常出现连续执行多个用例时会报“org.apache.http.NoHttpResponseException”错误,而单个执行一个用例就不会报这种错误。通过分析为何接口测试时不会出现这种问题,而线上回归的时候就会触发这种错误呢?缘由是因为线上的回归集是为了验证明际的状况要检查CDN是否部署成功,因此线上一个用例的执行时间是30分钟之上,而线下接口测试只须要毫秒级别。接下来我将介绍下为何会出现“org.apache.http.NoHttpResponseException”,以及如何解决这种问题。apache
HttpClient的实现类为CloseableHttpClient。建立CloseableHttpClient实例有两种方式: (1)使用CloseableHttpClient的工厂类HttpClients的方法来建立实例。HttpClients提供了根据各类默认配置来建立CloseableHttpClient实例的快捷方法。最简单的实例化方式是调用HttpClients.createDefault()。 (2)使用CloseableHttpClient的builder类HttpClientBuilder,先对一些属性进行配置,再调用build方法来建立实例。上面的HttpClients.createDefault()实际上调用的也就是HttpClientBuilder.create().build()。 可是在测试的时候连续执行多个方法的时候就会报错,直接执行其中的一个测试方法就不会有这种问题:后端
java.lang.AssertionError: org.apache.http.NoHttpResponseException: nos-yq-yanlian.netease.com:8080 failed to respond at org.testng.Assert.fail(Assert.java:89) at com.netease.pubncdn.test.testcase.OnlineDomainDeployTest.testCreateHttpDomain(OnlineDomainDeployTest.java:192) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
通过查询资料发现:Http规范没有规定一个持久链接应该保持存活多久。有些Http服务器使用非标准的Keep-Alive头消息和客户端进行交互,服务器端会保持数秒时间内保持链接。HttpClient也会利用这个头消息。若是服务器返回的响应中没有包含Keep-Alive头消息,HttpClient会认为这个链接能够永远保持。然而,不少服务器都会在不通知客户端的状况下,关闭必定时间内不活动的链接,来节省服务器资源。在某些状况下默认的策略显得太乐观,咱们可能须要自定义链接存活策略。安全
经过以下代码能够自定义链接存活策略:服务器
CloseableHttpClient client = HttpClients.custom() .setKeepAliveStrategy(keepAliveStrategy) .build();
ConnectionKeepAliveStrategy keepAliveStrategy = new ConnectionKeepAliveStrategy() { public long getKeepAliveDuration(HttpResponse response, HttpContext context) { // Honor 'keep-alive' header HeaderElementIterator it = new BasicHeaderElementIterator( response.headerIterator(HTTP.CONN_KEEP_ALIVE)); while (it.hasNext()) { HeaderElement he = it.nextElement(); String param = he.getName(); String value = he.getValue(); if (value != null && param.equalsIgnoreCase("timeout")) { try { return Long.parseLong(value) * 1000; } catch(NumberFormatException ignore) { } } } HttpHost target = (HttpHost) context.getAttribute( HttpClientContext.HTTP_TARGET_HOST); if ("www.baidu.com".equalsIgnoreCase(target.getHostName())) { // Keep alive for 5 seconds only return 5 * 1000; } else { // otherwise keep alive for 30 seconds return 30 * 1000; } } };
经过(三)中的方式能够解决“org.apache.http.NoHttpResponseException”报错的问题,可是考虑到实际的应用场景不适合此种方法。由于一次请求到下次请求之间的间隔为30分钟以上,不适合将链接时间改成30分钟以上(由于不少服务器都会在不通知客户端的状况下,关闭必定时间内不活动的链接,来节省服务器资源)。 修改测试代码为不在@BeforeClass时进行建立实例,而是在每一个测试用例里面进行建立实例来规避的解决这种问题。网络
为了定位上述的报错问题,须要了解使用HttpClient请求一个Http请求的步骤,以及如何自定义链接存活策略。在查到解决办法后要考虑是否真正适合咱们的应用场景,以及采用了这种方式是否会形成资源浪费,最终选择适合的方式来规避的解决这个问题。测试
更多网易技术、产品、运营经验分享请点击。spa
相关文章:
【推荐】 Gradle task