国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

記一次線上bug排查-----SpringCloud Gateway組件 請(qǐng)求頭accept-encoding導(dǎo)致響應(yīng)結(jié)果亂碼

這篇具有很好參考價(jià)值的文章主要介紹了記一次線上bug排查-----SpringCloud Gateway組件 請(qǐng)求頭accept-encoding導(dǎo)致響應(yīng)結(jié)果亂碼。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

? ? ? ?基于公司的業(yè)務(wù)需求,在SpringCloud Gateway組件的基礎(chǔ)上,寫了一個(gè)轉(zhuǎn)發(fā)服務(wù),測(cè)試開發(fā)階段運(yùn)行正常,并實(shí)現(xiàn)初步使用。但三個(gè)月后,PostMan請(qǐng)求接口,返回異常,經(jīng)排查,從日志中獲取到轉(zhuǎn)發(fā)響應(yīng)的結(jié)果為亂碼:

? ? ??記一次線上bug排查-----SpringCloud Gateway組件 請(qǐng)求頭accept-encoding導(dǎo)致響應(yīng)結(jié)果亂碼,Java,編程語言,spring cloud,gateway,響應(yīng)結(jié)果亂碼,路由轉(zhuǎn)發(fā),微服務(wù)

跟蹤日志:

記一次線上bug排查-----SpringCloud Gateway組件 請(qǐng)求頭accept-encoding導(dǎo)致響應(yīng)結(jié)果亂碼,Java,編程語言,spring cloud,gateway,響應(yīng)結(jié)果亂碼,路由轉(zhuǎn)發(fā),微服務(wù)

轉(zhuǎn)發(fā)到目標(biāo)接口,響應(yīng)結(jié)果已亂碼。一般排查的思路是,查看請(qǐng)求方和響應(yīng)方的編碼格式是否一致,打印請(qǐng)求方的編碼格式為UTF-8,響應(yīng)服務(wù)的編碼格式也是UTF-8。

記一次線上bug排查-----SpringCloud Gateway組件 請(qǐng)求頭accept-encoding導(dǎo)致響應(yīng)結(jié)果亂碼,Java,編程語言,spring cloud,gateway,響應(yīng)結(jié)果亂碼,路由轉(zhuǎn)發(fā),微服務(wù)

以上說明編碼格式?jīng)]有問題。上網(wǎng)去找“gateway響應(yīng)結(jié)果亂碼”的相關(guān)文章,大多數(shù)會(huì)提供解決方案:

DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
DataBuffer join = dataBufferFactory.join(dataBuffers);
byte[] content = new byte[join.readableByteCount()];
join.read(content);
// 釋放掉內(nèi)存
DataBufferUtils.release(join);
String str = new String(content, Charset.forName("UTF-8"));
originalResponse.getHeaders().setContentLength(str.getBytes().length);
System.out.println(str);
return bufferFactory.wrap(str.getBytes());

這段關(guān)鍵代碼,在我的響應(yīng)結(jié)果包裝過濾器是有的,如下:

    /**
     * 獲取到解碼方的response,驗(yàn)簽--->重新封裝--->加簽
     * 通過 DataBufferFactory 解決響應(yīng)體分段傳輸問題。
     */
    private ServerHttpResponseDecorator verifyRePackageSignatureResponse(ServerWebExchange exchange, String jmf_decode_url, String route_privateKey, String jmf_publicKey) {
        ServerHttpResponse response = exchange.getResponse();
        log.debug("R:給響應(yīng)結(jié)果response設(shè)置編碼格式----START----");
        response.getHeaders().add("Content-Type","application/json;charset=UTF-8");
        log.debug("R:給響應(yīng)結(jié)果response設(shè)置編碼格式-----END-----");
        DataBufferFactory bufferFactory = response.bufferFactory();

        return new ServerHttpResponseDecorator(response) {
            @Override
            public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                if (body instanceof Flux) {

                    // 獲取響應(yīng)類型,如果是 json 就打印
                    String originalResponseContentType = exchange.getAttribute(ServerWebExchangeUtils.ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR);
                    log.debug("響應(yīng)類型為originalResponseContentType:{}",originalResponseContentType);
                    if (RequestResponseUtil.isJson(originalResponseContentType)) {
                        Flux<? extends DataBuffer> fluxBody = Flux.from(body);
                        return super.writeWith(fluxBody.buffer().map(dataBuffers -> {

                            // 合并多個(gè)流集合,解決返回體分段傳輸
                            DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
                            DataBuffer join = dataBufferFactory.join(dataBuffers);
                            byte[] content = new byte[join.readableByteCount()];
                            join.read(content);

                            // 釋放掉內(nèi)存
                            DataBufferUtils.release(join);

                            // 正常返回的數(shù)據(jù)
                            String rootData = new String(content, StandardCharsets.UTF_8);
                            log.debug("R:正常返回的數(shù)據(jù)rootData為:{}", rootData);


                            //使用枚舉 + 工廠 + 策略模式(第二版)
                            String newQqtBodyJson = null;
                            try {
                                newQqtBodyJson = DecoderSignStrategyContext.zwmVerifySignResponse(rootData, jmf_decode_url, route_privateKey, jmf_publicKey);
                                log.debug("R:【碼路由服務(wù)】經(jīng)具體策略處理,得到結(jié)果newQqtBodyJson為:{}", newQqtBodyJson);
                            } catch (Exception e) {
                                log.error("R:【碼路由服務(wù)】解碼方返回結(jié)果驗(yàn)簽異常:{}", e);
                                throw new VerifySignException(StaticVar.FAIL_10020015, "R:【碼路由服務(wù)】解碼方返回結(jié)果驗(yàn)簽異常");
                            }
                            byte[] respData = newQqtBodyJson.getBytes();
                            //byte[] respData = newQqtBodyJson.getBytes(StandardCharsets.UTF_8);
                            byte[] uppedContent = new String(respData, Charset.forName("UTF-8")).getBytes();
                            return bufferFactory.wrap(uppedContent);

                        }));

                    } else {
                        log.error("響應(yīng)結(jié)果異常");
                        throw new ProcessHandleException(StaticVar.FAIL_10020015, "R:【碼路由服務(wù)】解碼方返回結(jié)果異常,非法JSON");
                    }
                }

                // if body is not a flux. never got there.
                return super.writeWith(body);
            }
        };
    }

因此不是代碼的問題。又找到了一篇文章,解決了PostMan請(qǐng)求的問題。

https://bbs.csdn.net/topics/399102026/close

記一次線上bug排查-----SpringCloud Gateway組件 請(qǐng)求頭accept-encoding導(dǎo)致響應(yīng)結(jié)果亂碼,Java,編程語言,spring cloud,gateway,響應(yīng)結(jié)果亂碼,路由轉(zhuǎn)發(fā),微服務(wù)

如上所述,在PostMan請(qǐng)求的headers中去掉Accept-Encoding,請(qǐng)求成功:

記一次線上bug排查-----SpringCloud Gateway組件 請(qǐng)求頭accept-encoding導(dǎo)致響應(yīng)結(jié)果亂碼,Java,編程語言,spring cloud,gateway,響應(yīng)結(jié)果亂碼,路由轉(zhuǎn)發(fā),微服務(wù)

? ? ? ?至此,PostMan請(qǐng)求亂碼的問題已解決。但事情似乎沒有那么簡(jiǎn)單,接下來,使用手機(jī)模擬掃碼,請(qǐng)求碼路由服務(wù),又出現(xiàn)了亂碼,掃碼結(jié)果頁面,返回結(jié)果:

記一次線上bug排查-----SpringCloud Gateway組件 請(qǐng)求頭accept-encoding導(dǎo)致響應(yīng)結(jié)果亂碼,Java,編程語言,spring cloud,gateway,響應(yīng)結(jié)果亂碼,路由轉(zhuǎn)發(fā),微服務(wù)

?查看日志,亂碼如下:

記一次線上bug排查-----SpringCloud Gateway組件 請(qǐng)求頭accept-encoding導(dǎo)致響應(yīng)結(jié)果亂碼,Java,編程語言,spring cloud,gateway,響應(yīng)結(jié)果亂碼,路由轉(zhuǎn)發(fā),微服務(wù)

? ? ? 排查問題進(jìn)入瓶頸期,有些煩躁了,必須冷靜下來,重新捋一下代碼,同時(shí)也在想,既然和PostMan請(qǐng)求存在同樣的問題,是不是在請(qǐng)求頭中默認(rèn)會(huì)有一個(gè)Accept-Encoding屬性,從而導(dǎo)致了亂碼,根據(jù)這個(gè)思路,在自定義的請(qǐng)求轉(zhuǎn)發(fā)過濾器中,發(fā)現(xiàn)了以下代碼:

記一次線上bug排查-----SpringCloud Gateway組件 請(qǐng)求頭accept-encoding導(dǎo)致響應(yīng)結(jié)果亂碼,Java,編程語言,spring cloud,gateway,響應(yīng)結(jié)果亂碼,路由轉(zhuǎn)發(fā),微服務(wù)

由于在請(qǐng)求轉(zhuǎn)發(fā)的邏輯中,重新構(gòu)建了一個(gè)request請(qǐng)求的同時(shí),重新創(chuàng)建了一個(gè)請(qǐng)求頭headers,它在重新構(gòu)建的時(shí)候默認(rèn)會(huì)有一個(gè)accept-encoding屬性,看到這一行代碼時(shí),正印證了以上我的猜想,問題已經(jīng)找到了,將其置為空字符串即可(注意:不能使其為null,也不能remove這個(gè)屬性,會(huì)報(bào)錯(cuò))。

? 將headers的accept-encoding屬性置為空字符串,并添加注釋如下:

// 定義新的消息頭
        HttpHeaders headers = new HttpHeaders();
        //System.out.println("headers = " + headers); //查看重新定義消息頭的內(nèi)容
        headers.putAll(exchange.getRequest().getHeaders());

        // 由于修改了傳遞參數(shù),需要重新設(shè)置CONTENT_LENGTH,長(zhǎng)度是字節(jié)長(zhǎng)度,不是字符串長(zhǎng)度
        int length = bodyStr.getBytes().length;
        log.debug("bodyStr長(zhǎng)度為:{}",length);
        headers.remove(HttpHeaders.CONTENT_LENGTH);

        // 設(shè)置CONTENT_TYPE
        if (StringUtils.isNotBlank(contentType)) {
            headers.set(HttpHeaders.CONTENT_TYPE, contentType);
        }

        String jmf_decode_url = request.getURI().toString();
        String qqtBodyJsonStr = JSONUtils.toString(bizPackage);

        //request.mutate().header(HttpHeaders.CONTENT_LENGTH, Integer.toString(bodyStr.length())); //報(bào)錯(cuò)JSON parse error JsonEOFException,長(zhǎng)度必須為字節(jié)的長(zhǎng)度
        request.mutate().header(HttpHeaders.CONTENT_LENGTH, Integer.toString(length));//成功,解決JSON parse error JsonEOFException

        /**
         * 亂碼現(xiàn)象:請(qǐng)求響應(yīng)結(jié)果亂碼
         * 解決過程分為PostMan請(qǐng)求和手機(jī)端App掃碼請(qǐng)求:
         *   (1)、PostMan請(qǐng)求響應(yīng)亂碼解決:
         *             PostMan請(qǐng)求的headers中默認(rèn)會(huì)有"Accept-Encoding"屬性,值為"gzip, deflate, br",導(dǎo)致響應(yīng)結(jié)果亂碼
         *         去掉Accept-Encoding后請(qǐng)求正常。
         *
         *   (2)、手機(jī)端App掃碼請(qǐng)求亂碼解決:
         *             在HttpRequestSignForwardGatewayFilter中定義新的消息頭,headers中默認(rèn)會(huì)有"accept-encoding"屬性,
         *         值為"gzip, deflate, br", 添加代碼"request.mutate().header("accept-encoding",""); "解決亂碼
         *
         *       注意: 創(chuàng)建headers對(duì)象默認(rèn)會(huì)生成“accept-encoding=‘gzip, deflate, br‘ ”屬性,此處必須將accept-encoding
         *       置為空字符串(置為null會(huì)報(bào)錯(cuò)),否則使用默認(rèn)值會(huì)導(dǎo)致響應(yīng)結(jié)果亂碼。
         *       說明: 測(cè)試開發(fā)階段未發(fā)生此問題,第三方檢測(cè)時(shí)演示出現(xiàn)此問題,這個(gè)可能是gateway內(nèi)部的問題,尚未可知。
         *
         *          經(jīng)測(cè)試,這種方式已解決了:手機(jī)端APP掃碼和PostMan響應(yīng)結(jié)果亂碼的問題(PostMan請(qǐng)求時(shí)可以不用刻意去掉Accept-Encoding,
         *       也可請(qǐng)求成功)
         *
         */
        request.mutate().header("accept-encoding","");

重啟后,部署后問題得到解決。這個(gè)問題在測(cè)試開發(fā)階段沒有暴露出來,按理說應(yīng)該早暴露了,但現(xiàn)實(shí)情況就是這么詭異,這可能是Gateway內(nèi)部的bug,尚未可知。

記一次線上bug排查-----SpringCloud Gateway組件 請(qǐng)求頭accept-encoding導(dǎo)致響應(yīng)結(jié)果亂碼,Java,編程語言,spring cloud,gateway,響應(yīng)結(jié)果亂碼,路由轉(zhuǎn)發(fā),微服務(wù)

? ? ?希望此文對(duì)遇到同樣問題的小伙伴有所幫助和啟發(fā),望了解gateway內(nèi)部原理機(jī)制的大神,參與討論。

? ? 亂碼問題已排查并處理結(jié)束,完結(jié),撒花!

參考文章:

RestTemplate請(qǐng)求頭accept-encoding導(dǎo)致亂碼_resttemplate 亂碼_AE86Jag的博客-CSDN博客

https://bbs.csdn.net/topics/399102026/close

在此感謝文章作者!文章來源地址http://www.zghlxwxcb.cn/news/detail-758743.html

到了這里,關(guān)于記一次線上bug排查-----SpringCloud Gateway組件 請(qǐng)求頭accept-encoding導(dǎo)致響應(yīng)結(jié)果亂碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 記一次線上問題 → Deadlock 的分析與優(yōu)化

    記一次線上問題 → Deadlock 的分析與優(yōu)化

    今天女朋友很生氣 女朋友:我發(fā)現(xiàn)你們男的,都挺單純的 我:這話怎么說 女朋友:腦袋里就只想三件事,搞錢,跟誰喝點(diǎn),還有這娘們真好看 我:你錯(cuò)了,其實(shí)我們男人吧,每天只合計(jì)一件事 女朋友:啥事呀? 我:這娘們真好看,得搞錢跟她喝點(diǎn) ? MySQL8. 0.30 ?,隔離級(jí)別

    2024年02月15日
    瀏覽(16)
  • 記一次線上問題 → 偶爾的熱情真的難頂呀!

    記一次線上問題 → 偶爾的熱情真的難頂呀!

    昨晚和媳婦坐在沙發(fā)上刷視頻 我用手肘輕輕推了推媳婦:你看這渣男,玩完女的都不娶人家 媳婦:哎喲我天,哎呀媽,我這也沒好哪去呀 我疑惑的看向媳婦:啥意思啊 媳婦看向自己的手機(jī):啥意思啊,特么有些人,娶完了也不玩呀 我負(fù)責(zé)的系統(tǒng)需要同步上游系統(tǒng)的數(shù)據(jù) 同

    2024年02月03日
    瀏覽(19)
  • 記一次線上kafka重復(fù)消費(fèi)的問題解決及思考

    線上ELK日志發(fā)現(xiàn)kafka消費(fèi)者消費(fèi)到重復(fù)消息 由于生產(chǎn)方本身就發(fā)送了重復(fù)的消息,導(dǎo)致消費(fèi)到重復(fù)消息 消費(fèi)方采用的是循環(huán)poll的模式,具體是在多線程分租戶去批量處理的消息

    2024年02月10日
    瀏覽(19)
  • 記一次線上問題引發(fā)的對(duì) Mysql 鎖機(jī)制分析

    最近雙十一開門紅期間組內(nèi)出現(xiàn)了一次因 Mysql 死鎖導(dǎo)致的線上問題,當(dāng)時(shí)從監(jiān)控可以看到數(shù)據(jù)庫活躍連接數(shù)飆升,導(dǎo)致應(yīng)用層數(shù)據(jù)庫連接池被打滿,后續(xù)所有請(qǐng)求都因獲取不到連接而失敗 整體業(yè)務(wù)代碼精簡(jiǎn)邏輯如下: 數(shù)據(jù)庫實(shí)例監(jiān)控: 當(dāng)時(shí)通過分析上游問題流量限流解決后

    2024年02月05日
    瀏覽(28)
  • 記一次線上mysql出錯(cuò):由于docker自動(dòng)拉取最新mysql鏡像導(dǎo)致mysql容器無法啟動(dòng)

    記一次線上mysql出錯(cuò):由于docker自動(dòng)拉取最新mysql鏡像導(dǎo)致mysql容器無法啟動(dòng)

    我隨便寫寫,你們隨便看看 環(huán)境背景:在docker中部署mysql鏡像,通過portainer管理docker容器 簡(jiǎn)單說下過程:docker里mysql的時(shí)區(qū)沒有設(shè)置,導(dǎo)致相差8小時(shí),通過增加TZ=Asiz/Shanghai環(huán)境變量,然后重啟容器來生效。結(jié)果重啟的時(shí)候始終無法啟動(dòng)起來,后來發(fā)現(xiàn)是自動(dòng)升級(jí)了mysql鏡像版

    2024年02月07日
    瀏覽(24)
  • 記一次 Redisson 線上問題 → ERR unknown command 'WAIT' 的排查與分析

    記一次 Redisson 線上問題 → ERR unknown command 'WAIT' 的排查與分析

    昨晚和一個(gè)朋友聊天 我:處對(duì)象嗎,咱倆試試? 朋友:我有對(duì)象 我:我不信,有對(duì)象不公開? 朋友:不好公開,我當(dāng)?shù)男∪?程序在生產(chǎn)環(huán)境穩(wěn)定的跑著 直到有一天,公司執(zhí)行組件漏洞掃描,有漏洞的? jar ?要進(jìn)行升級(jí)修復(fù) 然后我就按著掃描報(bào)告將有漏洞的? jar ?修復(fù)到指

    2024年02月09日
    瀏覽(21)
  • JAVA開發(fā)(記一次504 gateway timeout錯(cuò)誤排查過程)

    JAVA開發(fā)(記一次504 gateway timeout錯(cuò)誤排查過程)

    一、問題與背景: 最近在發(fā)布一個(gè)web項(xiàng)目,在測(cè)試環(huán)境都是可以的,發(fā)布到生產(chǎn)環(huán)境通過IP訪問也是可以的,但是通過域名訪問就出現(xiàn)504 gateway timeout。通過postman去測(cè)試接口也是一樣。ip和端口都可以通,域名卻不行,百思不得其解。通過一頓百度搜索,解析說通過nginx配置文

    2024年02月11日
    瀏覽(30)
  • 通過一次線上問題,講下Ribbon重試機(jī)制

    通過一次線上問題,講下Ribbon重試機(jī)制

    前段時(shí)間,產(chǎn)品經(jīng)理在線上驗(yàn)證產(chǎn)品功能的時(shí)候,發(fā)現(xiàn)某個(gè)功能不符合需求預(yù)期,后來測(cè)試驗(yàn)證發(fā)現(xiàn)是服務(wù)端的一個(gè)接口大概率偶現(xiàn)超時(shí),前端做了兜底處理,所以對(duì)線上用戶么有太大影響。 由于服務(wù)端的接口偶現(xiàn)超時(shí),并且網(wǎng)關(guān)設(shè)置了30s超時(shí)熔斷,所以前端請(qǐng)求就直接報(bào)錯(cuò)

    2024年02月15日
    瀏覽(23)
  • 一次線上mysql 調(diào)優(yōu) ,join 的調(diào)優(yōu),索引優(yōu)化(Block Nested Loop)

    一次線上mysql 調(diào)優(yōu) ,join 的調(diào)優(yōu),索引優(yōu)化(Block Nested Loop)

    原因: 某接口調(diào)用十分緩慢,通過 Explain 發(fā)現(xiàn)是SQL問題 可以看到,在Join連接時(shí),出現(xiàn)了BNL查詢,BNL出現(xiàn)是因?yàn)?,JOIN連接時(shí) dr表也就是 domian_redemption 被驅(qū)動(dòng)的表上沒出現(xiàn)可用的索引。 個(gè)人解決方法: 在對(duì)應(yīng)的連接字段上,既dr的orderCode字段,內(nèi)表加上索引,再次執(zhí)行Explai

    2024年02月05日
    瀏覽(21)
  • 記一次內(nèi)存泄漏排查

    記一次內(nèi)存泄漏排查

    最近某項(xiàng)目的服務(wù)突然告警,cpu超85%,隨后就是服務(wù)宕機(jī)。交付重啟服務(wù)后恢復(fù)正常但是隨后不久又開始告警,特別是白天,嚴(yán)重影響客戶業(yè)務(wù)進(jìn)行。 1、分析日志 查看日志的過程中發(fā)現(xiàn)存在內(nèi)存溢出(OOM),思考要么存在內(nèi)存泄漏要么業(yè)務(wù)上觸發(fā)了某個(gè)接口存在大對(duì)象,結(jié)

    2023年04月16日
    瀏覽(33)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包