最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringCloud OpenFeign Post請(qǐng)求400錯(cuò)誤解決方案

 更新時(shí)間:2020年09月30日 09:36:58   投稿:yaominghui  
這篇文章主要介紹了SpringCloud OpenFeign Post請(qǐng)求400錯(cuò)誤解決方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

在微服務(wù)開發(fā)中SpringCloud全家桶集成了OpenFeign用于服務(wù)調(diào)用,SpringCloud的OpenFeign使用SpringMVCContract來解析OpenFeign的接口定義。 但是SpringMVCContract的Post接口解析實(shí)現(xiàn)有個(gè)巨坑,就是如果使用的是@RequestParam傳參的Post請(qǐng)求,參數(shù)是直接掛在URL上的。

問題發(fā)現(xiàn)與分析

最近線上服務(wù)器突然經(jīng)常性出現(xiàn)CPU高負(fù)載的預(yù)警,經(jīng)過排查發(fā)現(xiàn)日志出來了大量的OpenFeign跨服務(wù)調(diào)用出現(xiàn)400的錯(cuò)誤(HTTP Status 400)。

一般有兩種情況:

  • nginx 返回400
  • java應(yīng)用返回400

通過分析發(fā)現(xiàn)400是java應(yīng)用返回的,那么可以確定是OpenFeign客戶端發(fā)起跨服務(wù)請(qǐng)求時(shí)出現(xiàn)異常了。 但是查看源碼發(fā)現(xiàn)出現(xiàn)這個(gè)問題的服務(wù)接口非常簡單,就是一個(gè)只有三個(gè)參數(shù)的POST請(qǐng)求接口,這個(gè)錯(cuò)誤并不是必現(xiàn)的錯(cuò)誤,而是當(dāng)參數(shù)值比較長(String)的時(shí)候才會(huì)出現(xiàn)。 所以可以初步確認(rèn)可能是參數(shù)太長導(dǎo)致請(qǐng)求400,對(duì)于POST請(qǐng)求因參數(shù)太長導(dǎo)致400錯(cuò)誤非常疑惑,POST請(qǐng)求除非把參數(shù)掛在URL上,否則不應(yīng)該出現(xiàn)400才對(duì)。

問題排查

為了驗(yàn)證上面的猜測,手寫了一個(gè)簡單的示例,在驗(yàn)證過程中特意開啟了OpenFeign的debug日志。

首先編寫服務(wù)接口

這是一個(gè)簡單的Post接口,僅有一個(gè)參數(shù)(這里的代碼僅用于驗(yàn)證,非正式代碼)

@FeignClient(name = "user-service-provider")
public interface HelloService {
  @PostMapping("/hello")
  public String hello(@RequestParam("name") String name);
}

編寫服務(wù)

服務(wù)這里隨便寫一個(gè)Http接口即可(同上,代碼僅用于驗(yàn)證)

@SpringBootApplication
@RestController
public class Starter {
  @RequestMapping("/hello")
  public String hello(String name) {
    return "User服務(wù)返回值:Hello " + String.valueOf(name);
  }
	
  public static void main(String[] args) {
    SpringApplication.run(Starter.class, args);
  }
}

服務(wù)注冊(cè)并調(diào)用

將服務(wù)注冊(cè)到注冊(cè)中心上,通過調(diào)用hello服務(wù)

@Autowired
public HelloService helloService;	
@RequestMapping("/hello")
public String hello(String name) {
  return helloService.hello(name);
}

通過日志可以發(fā)現(xiàn),SpringCloud集成OpenFeign的POST請(qǐng)求確實(shí)是直接將參數(shù)掛在URL上,如下圖:

正是因?yàn)檫@個(gè)巨坑,導(dǎo)致了線上服務(wù)器經(jīng)常性高CPU負(fù)載預(yù)警。

問題解決

問題知道了,那么就好解決了,用SpringCloud官方的說法是可以使用@RequestBody來解決這個(gè)問題,但是@RequestBody的使用是有限制的,也就是參數(shù)只能有一個(gè),而且需要整個(gè)調(diào)用鏈路都做相應(yīng)的調(diào)整,這個(gè)代價(jià)有點(diǎn)高,這里不采用這種方式,而是采用RequestInterceptor來處理。

編寫RequestInterceptor

這里將request的queryLine取下來放在body中,需要注意的是,只有body沒有值的時(shí)候才能這么做。

public class PostRequestInterceptor implements RequestInterceptor {
  @Override
  public void apply(RequestTemplate template) {
    if ("post".equalsIgnoreCase(template.method()) && template.body() == null) {
      String query = template.queryLine();
      template.queries(new HashMap<>());
      if (StringUtils.hasText(query) && query.startsWith("?")) {
        template.body(query.substring(1));
      }
      template.header("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
    }
  }
}

配置RequestInterceptor

feign:
client:
config:
default:
requestInterceptors: cn.com.ava.yaolin.springcloud.demo.PostRequestInterceptor

在下圖可以看出請(qǐng)求參數(shù)不再掛在URL上了

@RequestBody的解決方案

問題雖然解決了,但采用的不是官方推薦的方案,這里將官方推薦的這種@RequestBody的解決方法也貼出來。 使用@RequestBody解決,需要4個(gè)步驟:

編寫請(qǐng)求參數(shù)Bean

public class HelloReqForm {
  private String name;
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
}

調(diào)整接口聲明

@PostMapping("/hello")
public String hello(@RequestBody HelloReqForm form);

調(diào)整服務(wù)調(diào)用

HelloReqForm form = new HelloReqForm();
form.setName(name);
return helloService.hello(form);

調(diào)整服務(wù)實(shí)現(xiàn)

@RequestMapping("/hello")
public String hello(@RequestBody HelloReqForm form) {
}

最終調(diào)用日志

涉及的Java類

最后列出一些涉及的java類:

  • SpringMVCContract 服務(wù)接口
  • RequestParamParameterProcessor 參數(shù)
  • feign.RequestTemplate Rest請(qǐng)求構(gòu)造器
  • feign.Request 處理http請(qǐng)求

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • java中jar包的生成與使用方式

    java中jar包的生成與使用方式

    這篇文章主要介紹了java中jar包的生成與使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • Java實(shí)戰(zhàn)項(xiàng)目 圖書管理系統(tǒng)

    Java實(shí)戰(zhàn)項(xiàng)目 圖書管理系統(tǒng)

    這篇文章主要介紹了使用java SSM jsp mysql maven設(shè)計(jì)實(shí)現(xiàn)的精品圖書管理系統(tǒng),是一個(gè)很好的實(shí)例,對(duì)大家的學(xué)習(xí)和工作具有借鑒意義,建議收藏一下
    2021-09-09
  • Java中的幾種關(guān)鍵字的使用小結(jié)

    Java中的幾種關(guān)鍵字的使用小結(jié)

    本文主要介紹了Java中的幾種關(guān)鍵字的使用小結(jié),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • 使用maven war包打包去除jar包瘦身

    使用maven war包打包去除jar包瘦身

    這篇文章主要介紹了使用maven war包打包去除jar包瘦身操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • SpringBoot Entity中枚舉類型詳細(xì)使用介紹

    SpringBoot Entity中枚舉類型詳細(xì)使用介紹

    本文介紹SpringBoot如何在Entity(DAO)中使用枚舉類型。(本文使用MyBatis-Plus)。在實(shí)際開發(fā)中,經(jīng)常會(huì)遇到表示類型或者狀態(tài)的情況,比如:有三種支付方式:微信、支付寶、銀聯(lián)。本文介紹如何這種場景的方案對(duì)比,并用實(shí)例來介紹如何用枚舉這種最優(yōu)雅的來表示
    2022-10-10
  • 利用maven deploy上傳本地jar至私服的方法

    利用maven deploy上傳本地jar至私服的方法

    這篇文章主要介紹了利用maven deploy上傳本地jar至私服的方法,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-02-02
  • Jackson自定義序列化與反序列化注解詳解

    Jackson自定義序列化與反序列化注解詳解

    這篇文章主要介紹了Jackson自定義序列化與反序列化注解詳解,某些場景下,我們使用Jackson對(duì)數(shù)據(jù)進(jìn)行序列化或反序列化的時(shí)候,需要對(duì)某些數(shù)據(jù)進(jìn)行特殊處理,需要的朋友可以參考下
    2023-11-11
  • 如何使用Spring boot的@Transactional進(jìn)行事務(wù)管理

    如何使用Spring boot的@Transactional進(jìn)行事務(wù)管理

    這篇文章介紹了SpringBoot中使用@Transactional注解進(jìn)行聲明式事務(wù)管理的詳細(xì)信息,包括基本用法、核心配置參數(shù)、關(guān)鍵注意事項(xiàng)、調(diào)試技巧、最佳實(shí)踐以及完整示例,感興趣的朋友一起看看吧
    2025-02-02
  • RabbitMq報(bào)錯(cuò)reply-code=406 reply-text=PRECONDITION_FAILED解決

    RabbitMq報(bào)錯(cuò)reply-code=406 reply-text=PRECONDITION_FAILED

    這篇文章主要為大家介紹了RabbitMq報(bào)錯(cuò)reply-code=406 reply-text=PRECONDITION_FAILED分析解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • Spring ApplicationContext上下文核心容器深入探究

    Spring ApplicationContext上下文核心容器深入探究

    ApplicationContext是Spring應(yīng)用程序中的中央接口,由于繼承了多個(gè)組件,使得ApplicationContext擁有了許多Spring的核心功能,如獲取bean組件,注冊(cè)監(jiān)聽事件,加載資源文件等
    2023-01-01

最新評(píng)論

荥阳市| 招远市| 嫩江县| 桐柏县| 靖西县| 杭锦旗| 永年县| 莆田市| 始兴县| 盘锦市| 定边县| 葫芦岛市| 中卫市| 常宁市| 彝良县| 常熟市| 岑巩县| 宜兴市| 贵德县| 桂林市| 巴林左旗| 琼结县| 马鞍山市| 微博| 迁西县| 正定县| 大厂| 临朐县| 开鲁县| 工布江达县| 沅江市| 开鲁县| 九寨沟县| 墨脱县| 福鼎市| 平泉县| 梁河县| 明溪县| 平塘县| 改则县| 洞头县|