此文已由做者趙慧莉受權網易雲社區發佈。
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