HttpMethod自定義失敗重連
我們做web開發時,需要經常使用httpclient來請求http服務,有時為了安全起見,服務提供方會提供多個http地址,這樣如果我們請求某個ip出現異常,可以重試其他的ip地址,來儘量保證系統的穩定,以下是自定義一個HttpMethod重試機制的簡要程式碼。
HostCluster類定義需要連線的協議、ips[]、重試次數、隨機獲取一個host等:
點選(此處)摺疊或開啟
- public class HostCluster {
-
protected static final String HTTP_PROTOCOL = \"http\";
-
protected static final String HTTPS_PROTOCOL = \"https\";
-
-
protected String protocol;
-
protected String[] ips; //contain ip and port
-
-
private int idx;
-
private int retry;
-
-
private Random random;
-
-
public HostCluster(String ipAndPort) {
-
this(HTTP_PROTOCOL, ipAndPort);
-
}
-
-
public HostCluster(String protocol, String ipAndPort) {
-
this(protocol, ipAndPort, 0);
-
}
-
-
public HostCluster(String protocol, String ipAndPort, int retry) {
- if (StringUtils.isEmpty(ipAndPort)) {
-
throw new IllegalArgumentException(\"invalid constructor params.\");
-
}
- if (retry < 0) {
-
throw new IllegalArgumentException(\"invalid retry.\");
-
}
- if (!HTTP_PROTOCOL.equals(protocol) && !HTTPS_PROTOCOL.equals(protocol)) {
-
throw new IllegalArgumentException(\"invalid protocol.\");
-
}
-
-
//split the string
- String[] splitStr = StringUtils.split(ipAndPort, \",\");
-
-
this.protocol = protocol;
-
this.ips = splitStr;
-
this.retry = retry;
-
-
this.idx = this.ips.length;
-
this.random = new Random();
-
}
-
-
public String randomHost() {
-
int index = this.random.nextInt(idx);
-
log.info(\"randomIp=\" + ips[index]);
-
return this.protocol + \"://\" + ips[index];
-
}
-
-
public boolean isHttps() {
-
return HTTPS_PROTOCOL.equals(protocol);
-
}
-
-
public String getProtocol() {
-
return protocol;
-
}
-
-
public int getRetry() {
-
return retry;
-
}
- }
ClusterRetryHttpMethod從HostCluster獲取的randomHost,然後new URI()設定相應的base(GetMethod or PostMethod)
點選(此處)摺疊或開啟
- public abstract class ClusterRetryHttpMethod<T extends HttpMethod> {
-
protected HostCluster cluster;
-
protected String urlSuffix;
-
protected T base;
-
private Integer retry;
-
-
public ClusterRetryHttpMethod(HostCluster cluster, String urlSuffix) {
-
this(cluster, urlSuffix, null);
-
}
-
-
public ClusterRetryHttpMethod(HostCluster cluster, String urlSuffix, Integer retry) {
- if (cluster == null || StringUtils.isBlank(urlSuffix)) {
-
throw new IllegalArgumentException(\"invalid params.\");
-
}
-
if (retry != null) {
- if (retry < 0) {
-
throw new IllegalArgumentException(\"invalid retry.\");
-
} else {
-
this.retry = retry;
-
}
-
}
-
this.cluster = cluster;
-
this.urlSuffix = urlSuffix;
-
-
this.base = initBase();
-
}
-
-
public boolean isHttps() {
-
return this.cluster.isHttps();
-
}
-
-
public void setQueryString(String queryString) {
-
this.base.setQueryString(queryString);
-
}
-
-
public void setQueryString(NameValuePair[] params) {
-
this.base.setQueryString(params);
-
}
-
-
public int getRetry() {
-
return retry == null ? this.cluster.getRetry() : retry;
-
}
-
-
protected abstract T initBase();//子類各自實現,GetMethod or PostMethod
-
-
public T randomMethod() throws Exception {
-
String url = this.randomUrl();
-
if (StringUtils.isBlank(url)) {
-
url = \"/\";
-
}
-
-
this.base.setURI(new URI(url, true));
-
return base;
-
}
-
-
protected String randomUrl() {
-
return cluster.randomHost() + urlSuffix;
-
}
- }
最後就是怎麼呼叫了,這裡使用的是HttpClientPool來呼叫http連線,關於HttpClientPool詳見我的另一篇文章:http://blog.itpub.net/28912557/viewspace-1223241/
點選(此處)摺疊或開啟
-
public class HttpClientPool extends GenericObjectPool<HttpClient> {
-
-
private int httpsPort;
-
-
public HttpClientPool(PoolableObjectFactory<HttpClient> factory) {
-
super(factory);
-
}
-
-
public <T> T doPost(ClusterRetryHttpMethod method, HttpClientDataCallback<T> callback) {
-
HttpClient toUse = null;
-
HttpMethod m = null;
-
int index = 0;
- if (method == null) {
-
return null;
-
}
-
if (method.isHttps()) {
-
Protocol myhttps = new Protocol(\"https\", new SSLProtocolSocketFactoryImpl(), httpsPort);
-
Protocol.registerProtocol(\"https\", myhttps);
-
}
-
try {
-
toUse = borrowObject();
-
while (index <= method.getRetry()) {
-
try {
-
m = method.randomMethod();
-
toUse.executeMethod(m);
-
T rel = callback.handleResponse(m.getResponseBodyAsString());
-
return rel;
-
} catch (Exception e) {
-
logger.error(\"failed to execute http request.\", e);
-
index++;
-
} finally {
-
try {
-
m.releaseConnection();
-
} catch (Exception e) {
-
// in case fail, ignore and return object
-
}
-
}
-
}
- } catch (Exception e) {
-
return null;
-
} finally {
-
if (toUse != null) {
-
try {
-
returnObject(toUse);
- } catch (Exception e) {
-
}
-
}
-
if (method.isHttps()) {
-
try {
-
Protocol.unregisterProtocol(\"https\");
- } catch (Exception e) {
-
}
-
}
-
}
-
// all retry failed
-
return null;
-
-
}
-
-
-
public int getHttpsPort() {
-
return httpsPort;
-
}
-
-
public void setHttpsPort(int httpsPort) {
-
this.httpsPort = httpsPort;
-
}
- }
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28912557/viewspace-1356116/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- .NET Core授權失敗如何自定義響應資訊?
- perl 資料庫連結失敗重試機制資料庫
- 自定義Spring Security的身份驗證失敗處理Spring
- 使用者自定義控制元件拖拽失敗問題控制元件
- MongoVUE 連線失敗GoVue
- gin 自定義驗證器 為什麼會註冊失敗呢
- 精講RestTemplate第7篇-自定義請求失敗異常處理REST
- 自定義連線池
- CF連線伺服器失敗怎麼回事 cf連線失敗解決辦法伺服器
- postgresql連線失敗如何處理SQL
- 在容器外部連線kafka失敗Kafka
- mysql遠端連結失敗筆記MySql筆記
- 遠端主機mysql連線失敗MySql
- 資料庫連線設定失敗!資料庫
- VSCode 遠端連線失敗VSCode
- 資料庫遠端連線失敗資料庫
- MQ消費失敗,自動重試思路MQ
- 網頁提示連線資料庫失敗是怎麼回事(網站資料庫連線失敗)網頁資料庫網站
- 集合框架-去重自定義物件案例框架物件
- android中自定義屬性重複定義Android
- win10更新失敗重啟迴圈怎麼辦_win10更新失敗無限重啟修復方法Win10
- 記一次微信自定義分享debug均為true但是分享失敗的經歷
- Oracle備庫TNS連線失敗的分析Oracle
- 虛擬機器連線xshell失敗虛擬機
- testng擴充套件 失敗的用例重跑套件
- TestNG測試框架之失敗測試重跑框架
- pbootcms後臺“登入失敗:表單提交校驗失敗,請重新整理後重試”boot
- laravel8統一介面返回的json格式—通過自定義函式及自定義exception返回成功及失敗結果LaravelJSON函式Exception
- 如何實現 SAP UI5 路由失敗時顯示自定義的 NOT Found 頁面試讀版UI路由面試
- Java的快速失敗和安全失敗Java
- Laravel重寫資源路由自定義URLLaravel路由
- 公眾號新增自定義連結
- Windows Terminal 自定義 SSH 連線Windows
- 記一次 Kafka 重啟失敗問題排查Kafka
- Pytest學習筆記9-失敗重跑筆記
- RAC刪除節點失敗重啟大法解決
- mongodb資料庫連結失敗如何解決MongoDB資料庫
- 遠端連線 Mysql 失敗的解決方法MySql