CloseableHttpClient 連線超時導致XxlJob排程阻塞,影響排程任務的執行
問題原因
1.分析日誌發現,xxlJob後臺介面沒有執行時間和執行結果,在某一個時間點之後,某一個任務因為阻塞全部執行失敗,影響業務系統未正常進行。比如:定時投保,購買保險等。
2.臨時解決:先重啟服務,XxlJob恢復排程,可以正常執行任務。
3.最佳化解決:排查logger日誌,發現請求的日誌有,返回的日誌沒有,分析程式碼發現,CloseableHttpClient未設定超時時間,加上該程式碼,重新上線。
4.業務資料的拉取,提供給業務方來做線下處理等操作。
5.加上python監控,根據SQL查詢業務執行結果,每隔2個小時查詢一次,如果沒有執行結果,則報警提示。達到監控的目的。
DEMO程式碼示例:
package com.example.core.mydemo.http.httpclient; import com.alibaba.fastjson.JSON; import com.example.core.mydemo.http.CancelOrderReqVO; import com.example.core.mydemo.http.CancelRenyunOrderReqVO; import com.example.core.mydemo.json2.GsonUtils; import org.apache.http.HttpEntity; import org.apache.http.StatusLine; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import org.springframework.http.HttpStatus; import java.io.IOException; import java.nio.charset.StandardCharsets; public class CloseableHttpTest { public static void main(String[] args) throws Exception { CancelOrderReqVO data = new CancelOrderReqVO(); data.setOrderNum("111123333"); data.setServerType("1"); //僅僅測試 String url = "http://www.baidu.com"; String jsonParam = GsonUtils.toJson(data); System.out.println("呼叫外部介面入參jsonParam:{}" + jsonParam); String resJson = doPost(url,jsonParam); System.out.println("呼叫外部介面返回:{}" + resJson); } static String doPost(String url, String params) throws Exception { CloseableHttpClient httpclient = HttpClients.createDefault(); HttpPost httpPost = new HttpPost(url);// 建立httpPost System.out.println("請求url:"+url+",param:" + JSON.toJSONString(params)); httpPost.setHeader("Accept", "application/json;charset=utf-8"); httpPost.setHeader("Content-Type", "application/json;charset=utf-8"); String charSet = "UTF-8"; StringEntity entity = new StringEntity(params, charSet); httpPost.setEntity(entity); //設定超時時間【關鍵】 // 設定連線超時時間(毫秒) int connectTimeout = 10000; // 設定讀取超時時間(毫秒) int socketTimeout = 10000; // 設定從連線池中獲取連線的超時時間(毫秒) int connectionRequestTimeout = 10000; RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).setConnectionRequestTimeout(connectionRequestTimeout).build(); httpPost.setConfig(requestConfig); CloseableHttpResponse response = null; try { response = httpclient.execute(httpPost); StatusLine status = response.getStatusLine(); int state = status.getStatusCode(); if (state == HttpStatus.OK.value()) { HttpEntity responseEntity = response.getEntity(); String jsonString = EntityUtils.toString(responseEntity); // return new String(jsonString.getBytes(),"UTF-8"); return jsonString; } else{ //logger.error("請求返回:"+state+"("+url+")"); } } finally { if (response != null) { try { response.close(); } catch (IOException e) { e.printStackTrace(); } } try { httpclient.close(); } catch (IOException e) { e.printStackTrace(); } } return null; } }