自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

使用HTTP Client踩到的一個(gè)坑,你一定要避免

網(wǎng)絡(luò) 網(wǎng)絡(luò)管理
在實(shí)踐的過(guò)程中,我們經(jīng)常會(huì)遇到一些莫名其妙的問(wèn)題,而這些問(wèn)題導(dǎo)致的原因可能是實(shí)踐經(jīng)驗(yàn)不足,也可能是對(duì)API的使用不夠熟練。

前言

作為軟件開(kāi)發(fā)者,我們知道一切看似正常的系統(tǒng),不知埋藏著多少坑。今天跟大家分享一個(gè)實(shí)戰(zhàn)過(guò)程中遇到的HTTP Client使用不當(dāng)導(dǎo)致的坑。

筆者通過(guò)問(wèn)題的表象一路追蹤下去,最終找到導(dǎo)致問(wèn)題的根源:HTTP Client。結(jié)論很簡(jiǎn)單,先賣(mài)個(gè)關(guān)子,但分析的過(guò)程值得你借鑒。

問(wèn)題現(xiàn)象

場(chǎng)景:幾乎每個(gè)系統(tǒng)都有異步調(diào)用三方服務(wù)的功能,所負(fù)責(zé)的系統(tǒng)基于阻塞隊(duì)列實(shí)現(xiàn)了一個(gè)消息隊(duì)列,來(lái)調(diào)用三方服務(wù)。為了確保冪等性,隊(duì)列是順序消費(fèi)。這就導(dǎo)致一個(gè)問(wèn)題,一旦其中一個(gè)消息被阻塞,后面的消息就無(wú)法消費(fèi)。當(dāng)隊(duì)列滿時(shí),也無(wú)法向隊(duì)列中添加消息。

看似:極其偶發(fā)的場(chǎng)景下,消息隊(duì)列被阻塞十多分鐘。這是什么鬼?

下面就開(kāi)始了問(wèn)題的逐步排查。

問(wèn)題排查

首先想到的是,是不是消息隊(duì)列實(shí)現(xiàn)的底層機(jī)制有問(wèn)題。比如消息隊(duì)列是通過(guò)while(true)輪訓(xùn)+sleep睡眠來(lái)實(shí)現(xiàn)生產(chǎn)者和消費(fèi)者的持續(xù)存取數(shù)據(jù)。

既然消息被阻塞,是否是因?yàn)閟leep(睡)過(guò)頭了?后來(lái)一想,即使CPU進(jìn)行了分片處理,也不至于睡眠那么就不會(huì)被喚醒。同時(shí)也不太可能是線程被interrupted掉。因?yàn)?,如被interrupted掉了,整個(gè)隊(duì)列就掛了,不會(huì)延遲后恢復(fù)正常。

在此處困惑了很久,看了消息隊(duì)列實(shí)現(xiàn)的源碼很久,沒(méi)有突破。于是,與朋友探討了一下,一句話提醒了我:可能不是睡眠的問(wèn)題,而是生產(chǎn)者或消費(fèi)者的問(wèn)題。

于是仔細(xì)扒日志,發(fā)現(xiàn)還真是的:生產(chǎn)者向隊(duì)列中丟了一次數(shù)據(jù),持續(xù)很長(zhǎng)時(shí)間沒(méi)有再丟數(shù)據(jù);消費(fèi)者在生產(chǎn)者向隊(duì)列丟數(shù)據(jù)之后幾分鐘還有消費(fèi)的日志。很明顯,生產(chǎn)者是被消費(fèi)者阻塞了。

初步結(jié)論:消費(fèi)者消費(fèi)時(shí)間過(guò)長(zhǎng),導(dǎo)致隊(duì)列滿了,生產(chǎn)者向隊(duì)列添加數(shù)據(jù)時(shí)被阻塞。

經(jīng)驗(yàn)性猜測(cè):消費(fèi)者中有HTTP請(qǐng)求,HTTP請(qǐng)求可能長(zhǎng)時(shí)間持有連接未釋放。

問(wèn)題根源

當(dāng)分析定位到是HTTP請(qǐng)求的原因,就很好解決了。首先分析了日志,發(fā)現(xiàn)的確有一個(gè)HTTP請(qǐng)求,請(qǐng)求前打印了請(qǐng)求參數(shù),但始終沒(méi)看到返回結(jié)果的打印。扒日志終于看到,返回結(jié)果的日志是在15分鐘之后打印出來(lái)的,日志內(nèi)容為對(duì)方服務(wù)異常。

再看看代碼,發(fā)現(xiàn)HTTP請(qǐng)求是基于HTTP Client實(shí)現(xiàn)的,而當(dāng)初寫(xiě)這段代碼的人并沒(méi)有設(shè)置超時(shí)時(shí)間。為了保持業(yè)務(wù)脫敏,找了一段類似的代碼:

public static String doPostWithJSON(String url, String json) throws Exception {
CloseableHttpClient client = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader("Content-Type","application/json;charset=UTF-8");
StringEntity se = new StringEntity(json, Charset.forName("UTF-8"));
se.setContentType("application/json");
httpPost.setEntity(se);
CloseableHttpResponse response = client.execute(httpPost);
HttpEntity entity = response.getEntity();
String result = EntityUtils.toString(entity, "UTF-8");
return result;
}

像上述代碼一樣,設(shè)置了請(qǐng)求參數(shù),但未指定HttpPost的超時(shí)時(shí)間。看似正常的代碼,隱藏著一個(gè)巨大的坑,導(dǎo)致的結(jié)果就是HTTP請(qǐng)求一直等待。

筆者所遇到的情況還好,對(duì)方設(shè)置的超時(shí)時(shí)間為15分鐘,還給返回了結(jié)果。如果對(duì)方未設(shè)置超時(shí)時(shí)間,可能就一直等待了,當(dāng)業(yè)務(wù)量比較大時(shí),會(huì)導(dǎo)致災(zāi)難的發(fā)生!

HTTP Client的超時(shí)設(shè)置

找問(wèn)題往往是最難,當(dāng)找到問(wèn)題時(shí),解決起來(lái)就容易多了。HTTP Client的不同版本有不同的設(shè)置超時(shí)時(shí)間的方式,這也算是HTTP Client的又一大弊端吧,API版本變動(dòng)太大。

4.3版本的配置:

httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,10000);
httpClient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT,10000);

4.3以后版本的配置:

RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(10000).setConnectTimeout(10000).build();
httpGet.setConfig(requestConfig);

其中,setConnectTimeout為連接超時(shí)時(shí)間,單位為毫秒。

setSocketTimeout為請(qǐng)求獲取數(shù)據(jù)的超時(shí)時(shí)間,單位毫秒。如果訪問(wèn)一個(gè)接口,指定時(shí)間內(nèi)無(wú)法返回?cái)?shù)據(jù),就直接放棄此次調(diào)用。

其他版本的使用,建議參考一下相關(guān)的API說(shuō)明了。

小結(jié)

在實(shí)踐的過(guò)程中,我們經(jīng)常會(huì)遇到一些莫名其妙的問(wèn)題,而這些問(wèn)題導(dǎo)致的原因可能是實(shí)踐經(jīng)驗(yàn)不足,也可能是對(duì)API的使用不夠熟練。而經(jīng)驗(yàn)來(lái)自哪里?來(lái)自像本文這樣一個(gè)個(gè)問(wèn)題的排查、總結(jié)、積累而獲得。

比如,讀完本篇文章,你已經(jīng)知道了:當(dāng)使用HTTP Client時(shí)一定要設(shè)置超時(shí)時(shí)間。同時(shí),你肯定也能舉一反三,凡是在HTTP調(diào)用時(shí)都需要考慮一下超時(shí)時(shí)間及對(duì)應(yīng)的異常處理。

責(zé)任編輯:武曉燕 來(lái)源: 程序新視界
相關(guān)推薦

2017-10-16 12:52:51

2024-03-21 15:01:44

2017-06-08 09:19:35

2020-10-28 15:07:01

Arthas

2018-10-25 15:04:22

編程程序員陷阱

2024-11-20 10:30:00

AI架構(gòu)

2018-08-23 16:25:29

HadoopHDFS存儲(chǔ)

2019-12-24 14:00:36

運(yùn)維Linux測(cè)試

2020-12-03 10:17:25

Kubernetes架構(gòu)微服務(wù)

2018-08-29 11:04:05

2018-09-07 23:27:53

AI開(kāi)源學(xué)習(xí)框架

2022-06-13 09:26:41

Promise前端代碼

2024-04-23 10:23:34

WPFMVVMPrism

2016-11-24 15:54:06

androidJSONObject

2022-03-22 18:12:26

網(wǎng)絡(luò)攻擊數(shù)據(jù)安全安全威脅

2024-09-09 00:00:00

2021-03-15 12:00:19

Kubernetes微服務(wù)架構(gòu)

2022-09-30 14:00:50

JavaScrip新特性代碼

2019-08-21 19:49:21

機(jī)器學(xué)習(xí)人工智能

2020-04-14 08:46:47

Java對(duì)象編譯器
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)