欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

生產(chǎn)環(huán)境NoHttpResponseException異常排查解決記錄分析

 更新時(shí)間:2023年10月12日 08:58:53   作者:敲得碼黛  
這篇文章主要為大家介紹了生產(chǎn)環(huán)境NoHttpResponseException異常排查解決記錄分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

業(yè)務(wù)背景

公司最近正在準(zhǔn)備為郵儲(chǔ)銀行開(kāi)展一個(gè)營(yíng)銷活動(dòng),活動(dòng)規(guī)則是:用戶使用郵儲(chǔ)銀行卡在線上支付一分錢,就可以領(lǐng)取50元現(xiàn)金券,卡券領(lǐng)取完畢后,系統(tǒng)會(huì)自動(dòng)退還消費(fèi)者的1分錢。(相當(dāng)于免費(fèi)給郵儲(chǔ)用戶發(fā)放50元現(xiàn)金券),因?yàn)榘l(fā)券的入口要做在小程序里面,于是這個(gè)需求就落到了C端這邊(公司的另一個(gè)業(yè)務(wù)小組),而我主要負(fù)責(zé)B端支付模塊。經(jīng)過(guò)我們商討后,初步制定的業(yè)務(wù)邏輯為:用戶打開(kāi)C端小程序進(jìn)行支付、然后C端將支付請(qǐng)求轉(zhuǎn)給B端支付模塊、B端支付模塊向微信下單、等待消費(fèi)者完成支付后B端支付模塊通知C端交易完成并返回其支付方式、C端判斷支付方式是否為郵儲(chǔ)銀行卡(是郵儲(chǔ)銀行卡則發(fā)券)、然后C端調(diào)用B端支付模塊進(jìn)行退款。為了方便大家理解,我嘔心瀝血的畫(huà)出了系統(tǒng)調(diào)用的時(shí)序圖。

生產(chǎn)環(huán)境發(fā)現(xiàn)的問(wèn)題

1、NoHttpResponseException導(dǎo)致退款失敗

功能上線后,我便開(kāi)始監(jiān)控B端支付模塊的交易數(shù)據(jù),前兩天的數(shù)據(jù)并沒(méi)有什么異常,支付完成的訂單都已經(jīng)退款完成。然后在第三天快下班時(shí),我又統(tǒng)計(jì)了一遍數(shù)據(jù),發(fā)現(xiàn)竟然存在一筆沒(méi)退款的訂單,我整個(gè)人一下子就支棱了起來(lái)(不會(huì)又寫(xiě)了個(gè)Bug吧~),我先在數(shù)據(jù)庫(kù)中查到訂單號(hào),然后找運(yùn)維同事拿了一下日志,發(fā)現(xiàn)支付回調(diào)是正常的,并且下游系統(tǒng)也響應(yīng)了success,但是卻沒(méi)有調(diào)用退款接口進(jìn)行退款。排查到這里基本已經(jīng)可以確定不是支付模塊這邊的問(wèn)題了,但問(wèn)題畢竟還是要解決的,于是我聯(lián)系了C端的同事,暫時(shí)先通過(guò)接口的方式把消費(fèi)者的錢進(jìn)行退款。然后開(kāi)始排查C端系統(tǒng)的問(wèn)題,通過(guò)C端的日志發(fā)現(xiàn),在請(qǐng)求支付模塊進(jìn)行退款時(shí)存在一個(gè)異常信息,報(bào)錯(cuò)信息如下

看到這個(gè)報(bào)錯(cuò),我不禁陷入了思考:C端這個(gè)日志表明確實(shí)是發(fā)起了退款請(qǐng)求,但是B端支付模塊根本沒(méi)收到這個(gè)退款請(qǐng)求,這樣一來(lái)就比較尷尬了,雙方系統(tǒng)竟然都沒(méi)問(wèn)題,那只能是網(wǎng)絡(luò)問(wèn)題了(找不到人背鍋,只能推給網(wǎng)絡(luò)了~~哈哈),剛開(kāi)始只有一筆,我沒(méi)怎么在意,過(guò)了幾天后,陸陸續(xù)續(xù)發(fā)現(xiàn)了好幾筆類似的情況,平均幾千筆訂單就會(huì)出現(xiàn)一筆退款失敗的,并且這些訂單之間毫無(wú)規(guī)律,搞得我這幾天是干啥啥不香,于是痛下決心要深入研究一下這個(gè)問(wèn)題。

2、 異常情況分析

目前能夠提供幫助的信息并不多,只有這一個(gè)報(bào)錯(cuò)日志,通過(guò)在網(wǎng)上收集到的一些相關(guān)資料,發(fā)現(xiàn)了幾篇比較有借鑒價(jià)值的文章,他們的觀點(diǎn)也都幾乎一致:服務(wù)端主動(dòng)斷開(kāi)TCP鏈接,然后客戶端使用半斷開(kāi)的鏈接發(fā)起請(qǐng)求時(shí),服務(wù)端響應(yīng)RST包導(dǎo)致此異常情況的發(fā)生。 大多數(shù)文章的建議是:捕獲NoHttpResponseException異常進(jìn)行重試。

3、驗(yàn)證思路

既然有了上述猜想,那么下一步肯定是要做驗(yàn)證的,驗(yàn)證一下在這個(gè)場(chǎng)景下確實(shí)會(huì)出現(xiàn)此現(xiàn)象。剛開(kāi)始的驗(yàn)證思路比較簡(jiǎn)單,就是在服務(wù)端通過(guò)工具模擬FIN包,然后再用HttpClient繼續(xù)請(qǐng)求,觀察其結(jié)果,然而抓包結(jié)果顯示Httpclient會(huì)創(chuàng)建一個(gè)新的tcp鏈接進(jìn)行請(qǐng)求,木得辦法,解鈴還須系鈴人,恐怕要看一下HttpClient源碼才能解釋這個(gè)現(xiàn)象了。

通過(guò)閱讀HttpClient源碼,大致找到了兩個(gè)比較關(guān)鍵的邏輯點(diǎn)

  • HttpClient建立tcp鏈接的時(shí)機(jī)(三次握手的時(shí)機(jī))
  • 發(fā)送http請(qǐng)求的時(shí)機(jī)
tip:在三次握手之前會(huì)檢查當(dāng)前tcp鏈接是否處于Open狀態(tài),若處于Open狀態(tài)則復(fù)用此鏈接,若不處于Open狀態(tài)則打開(kāi)一個(gè)新的tcp鏈接,這樣一來(lái)就解釋的通為什么之前HttpClient又重新創(chuàng)建了一個(gè)TCP鏈接的現(xiàn)象了。

4、NoHttpResponseException復(fù)現(xiàn)

然后接下來(lái)是要做的就是根據(jù)之前的猜想來(lái)復(fù)現(xiàn)NoHttpResponseException場(chǎng)景,具體的思路如下

  • 在Httpclient源碼中,等待tcp鏈接建立完成后,打上斷點(diǎn)
  • 等服務(wù)器主動(dòng)發(fā)送FIN包斷開(kāi)鏈接后,再發(fā)起請(qǐng)求,然后觀察結(jié)果

成功復(fù)現(xiàn)了NoHttpResponseException現(xiàn)象,抓包結(jié)果如下所示

通過(guò)抓包結(jié)果分析,可以得出"服務(wù)端主動(dòng)斷開(kāi)TCP鏈接,然后客戶端使用半斷開(kāi)的鏈接發(fā)起請(qǐng)求"確實(shí)會(huì)導(dǎo)致NoHttpResponseException現(xiàn)象,至于服務(wù)端什么情況下會(huì)主動(dòng)斷開(kāi)tcp鏈接?間隔多久主動(dòng)斷開(kāi)tcp鏈接?這里就不再討論了,讀者可以自行了解一下keep-alive機(jī)制。分析到這里,問(wèn)題基本上算是解決了,生產(chǎn)環(huán)境出現(xiàn)此問(wèn)題的執(zhí)行時(shí)序應(yīng)該如下所示

  • 客戶端HttpClient復(fù)用之前已經(jīng)Open的鏈接
  • 然后進(jìn)行檢查(因?yàn)榇藭r(shí)服務(wù)端還未關(guān)閉tcp鏈接,所以鏈接可用)
  • 緊接著服務(wù)端主動(dòng)關(guān)閉鏈接導(dǎo)致鏈接不可用
  • 服務(wù)端針對(duì)客戶端的請(qǐng)求響應(yīng)了RST包

5、解決方案

從業(yè)務(wù)層面考慮,即使修復(fù)了這個(gè)問(wèn)題,也還是會(huì)有很大的風(fēng)險(xiǎn),畢竟網(wǎng)絡(luò)是未知的,因此我建議C端同事做一個(gè)補(bǔ)償機(jī)制,用來(lái)處理退款失敗情況。

當(dāng)然網(wǎng)絡(luò)層面該優(yōu)化的也得優(yōu)化,具體步驟是在HttpClient初始化時(shí)添加重試策略。

private static CloseableHttpClient init() {
        // 配置請(qǐng)求的超時(shí)設(shè)置
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT)
                .setConnectTimeout(CONNECT_TIMEOUT)
                .setSocketTimeout(SOCKET_TIMEOUT)
                .build();
        // 重試策略 RETRY_COUNT=3 代表NoHttpResponseException異常重試3次
        HttpRequestRetryHandler retryHandler = (exception, executionCount, context) -> {
            return executionCount <= RETRY_COUNT && exception instanceof NoHttpResponseException;
        }; 
        return HttpClients.custom()
                .setConnectionManager(new PoolingHttpClientConnectionManager())
                .setRetryHandler(retryHandler)
                .setDefaultRequestConfig(requestConfig)
                .build();
    }

6、引發(fā)的思考

  • HttpClientPool的鏈接管理策略(復(fù)用、回收等等)。
  • Keep-alive機(jī)制
  • 計(jì)算機(jī)網(wǎng)絡(luò)

以上就是生產(chǎn)環(huán)境NoHttpResponseException異常排查解決記錄分析的詳細(xì)內(nèi)容,更多關(guān)于生產(chǎn)環(huán)境NoHttpResponseException的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Spring整合Quartz定時(shí)任務(wù)并在集群、分布式系統(tǒng)中的應(yīng)用

    Spring整合Quartz定時(shí)任務(wù)并在集群、分布式系統(tǒng)中的應(yīng)用

    這篇文章主要介紹了Spring整合Quartz定時(shí)任務(wù)并在集群、分布式系統(tǒng)中的應(yīng)用,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-04-04
  • Java設(shè)計(jì)模式之橋接模式詳解(Bridge Pattern)

    Java設(shè)計(jì)模式之橋接模式詳解(Bridge Pattern)

    橋接模式是一種結(jié)構(gòu)型設(shè)計(jì)模式,旨在將抽象部分與其實(shí)現(xiàn)部分分離,從而使兩者可以獨(dú)立地變化,橋接模式通過(guò)組合關(guān)系代替繼承關(guān)系,將抽象和實(shí)現(xiàn)解耦,使代碼更具擴(kuò)展性和維護(hù)性
    2025-02-02
  • Spring?JPA之find拓展方法示例詳解

    Spring?JPA之find拓展方法示例詳解

    這篇文章主要為大家介紹了Spring?JPA之find拓展方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • 解析Java虛擬機(jī)中類的初始化及加載器的父委托機(jī)制

    解析Java虛擬機(jī)中類的初始化及加載器的父委托機(jī)制

    這篇文章主要介紹了Java虛擬機(jī)中類的初始化及加載器的父委托機(jī)制,包括命名空間等深層次的知識(shí)點(diǎn)講解,需要的朋友可以參考下
    2015-11-11
  • Java實(shí)現(xiàn)克魯斯卡爾算法的示例代碼

    Java實(shí)現(xiàn)克魯斯卡爾算法的示例代碼

    克魯斯卡爾算法是一種用于求解最小生成樹(shù)問(wèn)題的貪心算法。這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)克魯斯卡爾算法的方法,需要的可以參考一下
    2023-04-04
  • SpringBoot應(yīng)用jar包啟動(dòng)原理詳解

    SpringBoot應(yīng)用jar包啟動(dòng)原理詳解

    本文主要介紹了SpringBoot應(yīng)用jar包啟動(dòng)原理詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-03-03
  • java必學(xué)必會(huì)之方法的重載(overload)

    java必學(xué)必會(huì)之方法的重載(overload)

    java必學(xué)必會(huì)之方法的重載,介紹了方法的重載、構(gòu)造方法的重載,想要學(xué)好java方法的重載的朋友一定要好好閱讀這篇文章
    2015-12-12
  • Java單例模式分析

    Java單例模式分析

    這篇文章主要給大家介紹了關(guān)于Java單例模式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-09-09
  • java使用poi在excel單元格添加超鏈接設(shè)置字體顏色的方法

    java使用poi在excel單元格添加超鏈接設(shè)置字體顏色的方法

    這篇文章主要介紹了java使用poi在excel單元格添加超鏈接,設(shè)置字體顏色,poi功能還是很強(qiáng)大的,基本能想到的功能都能通過(guò)poi實(shí)現(xiàn),本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-09-09
  • 詳解Spring如何解析占位符

    詳解Spring如何解析占位符

    Spring一直支持將屬性定義到外部的屬性的文件中,并使用占占位符的形式為使用"${}"包裝的屬性名稱,為了使用屬性占位符,我們必須配置一個(gè)PropertyPlaceholderConfigurer或PropertySourcesPlaceholderConfigurer實(shí)例,本文將介紹如何解析占位符
    2021-06-06

最新評(píng)論