<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          開工第一天,這個超時問題把我干趴下了

          共 4139字,需瀏覽 9分鐘

           ·

          2022-02-26 12:57

          前言:近日我司進(jìn)行云服務(wù)商更換,恰逢由我負(fù)責(zé)新上線的三方調(diào)用 api 維護(hù)管理,在將服務(wù)由阿里云部署到騰訊云過程中,我們壓測發(fā)現(xiàn)在騰訊云調(diào)用京東接口時 TP999 抖動十分劇烈,盡管業(yè)務(wù)層有重試操作但是超時依然較多,并不滿足業(yè)務(wù)要求…… 接下來針對過程中發(fā)現(xiàn)的種種問題我們便踏上了優(yōu)化之路。

          開端

          那還是普通的一夜,突然群里蹦出一些報警消息,多條業(yè)務(wù)線調(diào)用外部 api 超時,dubbo 線程池數(shù)量不足,還好很快服務(wù)恢復(fù)了正常,不過這也為我提了個大醒,我維護(hù)的服務(wù)作為業(yè)務(wù)調(diào)用的聚合出口,一旦服務(wù)發(fā)生異常將會導(dǎo)致很多業(yè)務(wù)方失敗。盡管在壓測過程中我們便知道了遷移云后的 api 調(diào)用可用性會有明顯下降,但在 C 端業(yè)務(wù)還未遷移時便出了這么大影響確實(shí)是前期準(zhǔn)備不足。

          基于表面問題分析

          出現(xiàn)問題先從最容易下手的地方開始解決,先分析問題,線程池飆高報警,結(jié)合日志、APM(skywalking) 工具進(jìn)行排查,發(fā)現(xiàn)報警時刻線程數(shù)量和 cpu 均出現(xiàn)飆升情況,由于服務(wù)主要提供的功能就是三方調(diào)用,很多線程卡在調(diào)用三方 api 等待響應(yīng)結(jié)果步驟上,并且有響應(yīng)結(jié)果的調(diào)用消耗在 http 的時間也特別長,這就很容易理解了,是由于三方 api 抖動加之服務(wù)創(chuàng)建 http 連接過多先是導(dǎo)致應(yīng)用響應(yīng)緩慢,再之服務(wù)超時觸發(fā)重試瞬間導(dǎo)致應(yīng)用負(fù)載翻倍,進(jìn)而加劇了服務(wù)緩慢問題。在不具備限流降級能力時服務(wù)一旦出現(xiàn)這種情況很容易導(dǎo)致雪崩,萬幸沒有太多業(yè)務(wù)損失,作為一個成熟的程序員總不能給自己留坑啊,趕緊來填坑!

          多方位填坑

          問題找到了,方案自然不缺了
          1. 修改 http 調(diào)用方式,引入 http 連接池

          這個方案其實(shí)在之前壓測過程中便考慮采用了,由于使用的三方 sdk 在 http 調(diào)用中均使用 java 原生的 HttpURLConnection ,這在接口高并發(fā)情況下不停創(chuàng)建連接,性能實(shí)在太差了??紤]團(tuán)隊內(nèi)大家熟悉程度直接用 HttpClinet 覆蓋三方 SDK 中的 HttpUtil 實(shí)現(xiàn),稍加修改即可。修改好重新進(jìn)行壓測,TP999 指標(biāo)、cpu 使用率均有明顯下降,這波漂亮,投入產(chǎn)出 ++!
          1. 第一個方案就萬事大吉了嗎?支持請求超時分級,線程隔離

          在第一個方案開發(fā)上線后我們又發(fā)現(xiàn)了新問題,業(yè)務(wù)側(cè)超時情況依然明顯!這個原因很容易想到,針對不同業(yè)務(wù)方我們只配置了一份超時配置,盡管部分業(yè)務(wù)方(主要是 C 端業(yè)務(wù),對接口超時十分敏感)會提前超時然后觸發(fā)重試,但是我的應(yīng)用線程依然在阻塞請求,這是資源的浪費(fèi)啊,仔細(xì)想想,之前的問題還是沒有解決,在客戶端不停重試下服務(wù)的 dubbo 線程豈不是還得爆了啊。再優(yōu)化,這次我想到了請求分級,由于不同業(yè)務(wù)方對接口的響應(yīng)時效要求不同,我們進(jìn)行了連接池隔離,針對不同的業(yè)務(wù)方調(diào)用可以在調(diào)用時設(shè)置請求分級,我們大致分類下創(chuàng)建了三種分級 ‘FAST’,'STANDARD','SLOW',不同分級由服務(wù)提供者去配置使用不同超時方案。服務(wù)穩(wěn)定性又進(jìn)一步,問題再一次得到了解決。
          這里還要提醒下大家 HttpClinet 使用過程中一般會配置連接池使用,切記搭配連接池使用時超時參數(shù)要配置三個,分別為
          ConnectionRequestTimeout?獲取連接池連接的超時時間(這個大家最容易忽略了)
          ConnectTimeout?連接超時時間
          SocketTimeout?socket?讀取超時時間
          1. 合理應(yīng)用重試(消費(fèi)者重試)

            盡管在提供者服務(wù)上已進(jìn)行代碼優(yōu)化,但是為了提升業(yè)務(wù)成功率,合理的使用重試也是很有必要的。此處要注意如果服務(wù)響應(yīng)較慢千萬避免消費(fèi)者的多級重試,如果我們的整個業(yè)務(wù)調(diào)用鏈每一層都做了重試那么就會導(dǎo)致鏈路中響應(yīng)慢的服務(wù)壓力愈發(fā)增長,嚴(yán)重的引發(fā)重試風(fēng)暴,直接壓垮服務(wù),所以合理設(shè)置重試也是很關(guān)鍵的一環(huán),這里我們后續(xù)也要考慮引入熔斷降級方案,避免意外發(fā)生。

          在上述三招連環(huán)出擊后,問題基本告一段落,2C4G 200 dubbo 線程,30 http 線程,吞吐量固定 1k,服務(wù)的 TP999 在壓測過程中基本可以穩(wěn)定在 500 毫秒以下,滿足各方要求。

          問題再起

          伴隨著應(yīng)用接入量越來越大,我們的 C 端業(yè)務(wù)方又給提出了一個新問題,服務(wù)的超時情況怎么和阿里的服務(wù)差那么大啊(此處僅是指京東接口),由于是新業(yè)務(wù)直接上線到騰訊云,懷疑可能是我們服務(wù)的性能問題,這個在之前只有一些 B 端業(yè)務(wù)我確實(shí)沒有過多注意,必須把這個問題好好查一查,還是從 APM 工具側(cè)查看,果然,接口的 TP999 抖動十分劇烈,很多達(dá)到超時閾值,而 C 端業(yè)務(wù)十分重視這些指標(biāo),這也值得我們?nèi)W(xué)習(xí),往往這些指標(biāo)上線很容易暴露出根本問題,在高并發(fā)下看 TP90、TP99 時指標(biāo)看起來還是挺正常的,那是因為超高請求量將響應(yīng)時間給平均下去了。

          糾結(jié)求解

          這次的問題不再簡單,面對這些 TP999 的超時響應(yīng),我們在觀測了應(yīng)用的整體流量、JVM 情況等等,愣是沒有找到瓶頸,有之前阿里云的應(yīng)用對比我們堅信問題是存在的,可能是在網(wǎng)絡(luò)請求層面。接下來我們一步步出擊。
          1、查看 APM 工具發(fā)現(xiàn)部分 HTTP 請求確實(shí)超時,還有一部分是 HTTP 請求耗時不算長,但是從 APM 統(tǒng)計的調(diào)用鏈路來看耗費(fèi)在提供者服務(wù)的時間比較長導(dǎo)致超時了。上述為兩個問題,分別來看,請求可以確定是超時的我懷疑是不是由于使用了 http 連接池,池中的鏈接是不是超時了,從 httpclient 的日志中我分析了一下并沒有這個問題,因為三方響應(yīng)的 header 只返回了 keepalived,并沒有返回其有超時時間。第二個問題我反復(fù)查找當(dāng)時并沒有找到原因,服務(wù)壓力不大,也沒有發(fā)生長耗時的 GC,實(shí)在不好解釋這個問題,但是后來問題找到了,繼續(xù)看結(jié)果在下文。
          2、為了觀察應(yīng)用的請求響應(yīng)信息,我們對 http 出口進(jìn)行了抓包,通過對大量請求的抓包分析,我們找到了在響應(yīng)比較高的時候抓包的 ip 中竟然有香港的 ip,為了驗證這個問題,我們?nèi)グ俣攘?dns 解析,發(fā)現(xiàn)該 ip 確實(shí)為該域名所有。
          圖上部分為此域名解析出的香港 ip,下半部分為該域名解析出的北京 ip,同一臺機(jī)器上響應(yīng)時長差距明顯
          3、我們的服務(wù)器和出口 ip 都是北京的為什么 dns 解析出來的 ip 會返回香港的呢?帶著問題我們求助了騰訊云官方,在官方問題排查過程中,我們又做了其他測試,在服務(wù)器上寫了一個 python 小腳本定時進(jìn)行指定域名的 dns 域名解析,果然在跑了一段時間后出現(xiàn)了幾次解析結(jié)果為香港的 ip,狂喜。此時騰訊云官方也有了回應(yīng),由于京東自己搭建的 DNS 解析服務(wù)器,但是無法準(zhǔn)確識別騰訊云的 ip 地域,導(dǎo)致偶爾會解析到香港,解決方案是他們推動京東去識別騰訊云的 ip。
          該圖為騰訊云默認(rèn) dns 統(tǒng)計腳本的日志信息,第三個 ip 地址為香港,雖然較少出現(xiàn),但是訪問耗時長,且不定時會丟包
          4、等官方解決進(jìn)度遲緩啊,我們能有什么臨時的解決辦法嗎?糾結(jié)之時我們也接入了架構(gòu)組為我們搭建的 kong 出口網(wǎng)關(guān),有專門的 net 出口,更高的帶寬,完善的 granfa 監(jiān)控,結(jié)合監(jiān)控請求抖時展現(xiàn)更明顯了,于是我們想到了固定 host,更改 dns 方案,由于固定 host 風(fēng)險太大了,我們采用了更改 dns 的方案嘗試。原來機(jī)器上默認(rèn)是騰訊云的 dns,我們分別更換為阿里的 dns 和 114 的 dns 進(jìn)行了測試,測試結(jié)果是差距不大最終我們采用了阿里的 dns,在更換阿里的 dns 后效果明顯,原來 TP999 的尖刺明顯減少,觀察 kong 日志也不存在香港的 ip 了,這里就有點(diǎn)詫異騰訊不是說和 dns 沒關(guān)系嗎,為什么換了別人家的 dns 情況就好了很多(這個問題的結(jié)果是明確的,但是原因目前還是停留在猜測階段,猜測是 114 和阿里 dns 對此有優(yōu)化,所以在該場景下優(yōu)于騰訊 dns,若大家有方案可以驗證此問題歡迎提出來哦)。
          dns 切換后依據(jù) kong 統(tǒng)計計算的 SLA 信息,會比較明顯看出效果
          小插曲,kong 網(wǎng)關(guān)的 dns 解析器是寫在 kong.conf 配置文件中的,如果未配置該項則會讀取系統(tǒng)的 /etc/resolv.conf 文件,每次 kong 啟動后會讀取配置并緩存到內(nèi)存中,如果啟動 kong 后再修改系統(tǒng)的 nameserver 對 kong 是不管用的!還好我們之前有在專門的機(jī)器中測試 dns 更換效果,所以才敢肯定是 kong 配置問題,但是來回也折騰了不少時間才找到問題。
          在這里我也想告訴大家,和別人協(xié)作,如果可以請一定準(zhǔn)備好對比數(shù)據(jù),避免他人因質(zhì)疑而不配合,或者合作結(jié)果并不如預(yù)期時可以有個對照。
          5、記得最開始有一個問題當(dāng)時沒找到原因嗎,「一部分 HTTP 請求耗時不算長,但是從 APM 統(tǒng)計的調(diào)用鏈路來看耗費(fèi)在提供者服務(wù)的時間比較長導(dǎo)致超時了這個的問題最后還是 http 請求超時的原因,我對照了 kong 的日志和服務(wù)的 httpClient 日志,發(fā)現(xiàn)出現(xiàn)這種問題的請求有個共同點(diǎn)就是請求頭很快接收到了,但是 body 遲遲未讀取到然后觸發(fā)超時了。skyWaling 中展示的 HTTP 耗時很短的原因是因為只要開始有響應(yīng)就算請求結(jié)束了,然后為什么會有只返回 header 的情況呢?我 ping 了一下出現(xiàn)問題的 ip 是香港的,響應(yīng)時間明顯要比北京的慢,而且偶爾會丟包。這個問題解釋通了。

          終是踏平

          經(jīng)過又一輪的問題解決,測試加驗證效果耗費(fèi)了近兩周時間,服務(wù)的可用性也提升了一個層次,算是一個小坑,不過這也讓我們對 http 的整個請求流程做了很多梳理和二次認(rèn)知,以上便是我在解決這個超時問題的整個解決路徑和心路歷程,感謝看我的叨叨叨,希望我們可以一起共同進(jìn)步。

          有道無術(shù),術(shù)可成;有術(shù)無道,止于術(shù)

          歡迎大家關(guān)注Java之道公眾號


          好文章,我在看??

          瀏覽 50
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产一区二区在线播放 | 人人摸人人摸人人操 | 久久撸在线观看 | 成人黄片免费 | 亚洲无码五区 |