一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - SpringCloud OpenFeign Post請求400錯誤解決方案

SpringCloud OpenFeign Post請求400錯誤解決方案

2020-09-30 14:56yaominghui Java教程

這篇文章主要介紹了SpringCloud OpenFeign Post請求400錯誤解決方案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下

在微服務開發中SpringCloud全家桶集成了OpenFeign用于服務調用,SpringCloud的OpenFeign使用SpringMVCContract來解析OpenFeign的接口定義。 但是SpringMVCContract的Post接口解析實現有個巨坑,就是如果使用的是@RequestParam傳參的Post請求,參數是直接掛在URL上的。

問題發現與分析

最近線上服務器突然經常性出現CPU高負載的預警,經過排查發現日志出來了大量的OpenFeign跨服務調用出現400的錯誤(HTTP Status 400)。

一般有兩種情況:

  • nginx 返回400
  • java應用返回400

通過分析發現400是java應用返回的,那么可以確定是OpenFeign客戶端發起跨服務請求時出現異常了。 但是查看源碼發現出現這個問題的服務接口非常簡單,就是一個只有三個參數的POST請求接口,這個錯誤并不是必現的錯誤,而是當參數值比較長(String)的時候才會出現。 所以可以初步確認可能是參數太長導致請求400,對于POST請求因參數太長導致400錯誤非常疑惑,POST請求除非把參數掛在URL上,否則不應該出現400才對。

問題排查

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

首先編寫服務接口

這是一個簡單的Post接口,僅有一個參數(這里的代碼僅用于驗證,非正式代碼)

?
1
2
3
4
5
@FeignClient(name = "user-service-provider")
public interface HelloService {
  @PostMapping("/hello")
  public String hello(@RequestParam("name") String name);
}

編寫服務

服務這里隨便寫一個Http接口即可(同上,代碼僅用于驗證)

?
1
2
3
4
5
6
7
8
9
10
11
12
@SpringBootApplication
@RestController
public class Starter {
  @RequestMapping("/hello")
  public String hello(String name) {
    return "User服務返回值:Hello " + String.valueOf(name);
  }
    
  public static void main(String[] args) {
    SpringApplication.run(Starter.class, args);
  }
}

服務注冊并調用

將服務注冊到注冊中心上,通過調用hello服務

?
1
2
3
4
5
6
@Autowired
public HelloService helloService;  
@RequestMapping("/hello")
public String hello(String name) {
  return helloService.hello(name);
}

通過日志可以發現,SpringCloud集成OpenFeign的POST請求確實是直接將參數掛在URL上,如下圖:

SpringCloud OpenFeign Post請求400錯誤解決方案

正是因為這個巨坑,導致了線上服務器經常性高CPU負載預警。

問題解決

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

編寫RequestInterceptor

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
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

在下圖可以看出請求參數不再掛在URL上了

SpringCloud OpenFeign Post請求400錯誤解決方案

@RequestBody的解決方案

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

編寫請求參數Bean

?
1
2
3
4
5
6
7
8
9
public class HelloReqForm {
  private String name;
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
}

調整接口聲明

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

調整服務調用

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

調整服務實現

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

最終調用日志

SpringCloud OpenFeign Post請求400錯誤解決方案

涉及的Java類

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

  • SpringMVCContract 服務接口
  • RequestParamParameterProcessor 參數
  • feign.RequestTemplate Rest請求構造器
  • feign.Request 處理http請求

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:http://www.manongjc.com/detail/19-fxjynmrashzgysy.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 美女扒开尿口让男生添 漫画 | 亚洲成人77777| 香蕉久草| 三上悠亚精品专区久久 | 王淑兰李思雨李铁柱乡村小说免费 | 韩剧在线免费观看 | 91香蕉国产视频 | 91粉色视频在线导航 | bbbbbbaaaaaa毛片| 五月婷婷伊人网 | 国产裸舞福利资源在线视频 | 日本艳鉧动漫1~6在线观看 | 99精品国产成人a∨免费看 | 成人观看免费大片在线观看 | 香蕉精品 | 91久久国产青草亚洲 | 日韩精品一区二区三区视频 | 51国产午夜精品免费视频 | 四虎影视国产精品婷婷 | 末代皇帝无删减版在线观看 | 97福利社| 免费看1级伦理 | 久久久免费热线精品频 | 日本免费不卡在线一区二区三区 | 大香线一本 | 欧美日韩在线观看一区二区 | 亚洲精品在线播放 | 欧美精品综合一区二区三区 | 2019国内精品久久久久久 | 欧美日韩一区二区综合在线视频 | 日本午夜色 | 夫妇野外交换激情 | 色综合久久天天综合观看 | 狠狠涩| 娇喘高潮教室h | 99美国热| jm漫天堂破解版 | 亚洲精品九色在线网站 | 日本xxxx在线视频免费 | 99国产国人青青视频在线观看 | 星星动漫在线观看无删减 |