- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章SpringCloud OpenFeign Post请求400错误解决方案由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
在微服务开发中SpringCloud全家桶集成了OpenFeign用于服务调用,SpringCloud的OpenFeign使用SpringMVCContract来解析OpenFeign的接口定义。 但是SpringMVCContract的Post接口解析实现有个巨坑,就是如果使用的是@RequestParam传参的Post请求,参数是直接挂在URL上的.
问题发现与分析 。
最近线上服务器突然经常性出现CPU高负载的预警,经过排查发现日志出来了大量的OpenFeign跨服务调用出现400的错误(HTTP Status 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上,如下图:
正是因为这个巨坑,导致了线上服务器经常性高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上了 。
@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) { } 。
最终调用日志 。
涉及的Java类 。
最后列出一些涉及的java类:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我.
原文链接:http://www.manongjc.com/detail/19-fxjynmrashzgysy.html 。
最后此篇关于SpringCloud OpenFeign Post请求400错误解决方案的文章就讲到这里了,如果你想了解更多关于SpringCloud OpenFeign Post请求400错误解决方案的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我只是想知道要安装哪个版本的 Visual Studio 2010(专业版或高级版)提示升级项目.. 项目包括:asp.net mvc、数据库和silverlight。 最佳答案 通常,由不同版本的相
目录 前言 四、技术选型 五、后端接口设计 5.1业务系统接口 5.2App 端接口 六、关键逻辑实现 6.1Red
目录 前言 一、需求分析 1.1发送通知 1.2撤回通知 1.3通知消息数 1.4通知消息列表 二、数据模型设计
目录 前言 一、多租户的概念 二、隔离模式 2.1独立数据库模式 2.2共享数据库独立数据架构 2.3共享数据库共享数据架构
导读: 虽然锁在一定程度上能够解决并发问题,但稍有不慎,就可能造成死锁。本文介绍死锁的产生及处理。 死锁的产生和预防 发生死锁的必要条件有4个,分别为互斥条件、不可剥夺条件、请求与保持条件和循环等待条
在浏览网页后,我找不到任何功能来执行此操作,我有可行的个人解决方案。也许它对某人有用。 **使用 Moment 插件转换日期。***moment(currentPersianDate).clone()
是否有一种解决方案可以很好地处理数字(1-10)手写?我试过tesseract,但我得到的只是垃圾。 理想情况下是 OSS,但商业也可以。 最佳答案 OpenCV 现在带有手写数字识别 OCR 示例。
在服务器应用程序上,我们有以下内容:一个称为 JobManager 的单例类。另一个类,Scheduler,不断检查是否需要向 JobManager 添加任何类型的作业。 当需要这样做时,调度程序会执
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 5年前关闭。 Improve this qu
当您尝试从 GitHub 存储库安装某些 R 包时 install_github('rWBclimate', 'ropensci') 如果您遇到以下错误: Installing github repo
问题在以下链接中进行了描述和演示: Paul Stovell WPF: Blurry Text Rendering www.gamedev.net forum Microsoft Connect: W
我正在寻找一种解决方案,使用标准格式 a × 10 b 在科学记数法下格式化 R 中的数字。一些同行评审的科学期刊都要求这样做,并且手动修改图表可能会变得乏味。 下面是 R 标准“E 表示法”的示例,
已编辑解决方案(如下...) 我有一个启动画面,它被打包到它自己的 jar 中。它有效。 我可以通过以下方式从另一个 java 应用程序内部调用 Splash.jar: Desktop.getDesk
什么是创建像 PageFlakes 或 iGoogle 这样的门户网站的好框架/包? ?我们希望创建一个为员工提供 HR 服务的员工/HR 门户,但我们也需要一种足够灵活的产品,以便我们可以使用它来为
我正在寻找一种解决方案,使用标准格式 a × 10 b 在科学记数法下格式化 R 中的数字。一些同行评审的科学期刊都要求这样做,并且手动修改图表可能会变得乏味。 下面是 R 标准“E 表示法”的示例,
如何将 solr 与 heritrix 集成? 我想使用 heritrix 归档一个站点,然后使用 solr 在本地索引和搜索该文件。 谢谢 最佳答案 使用 Solr 进行索引的问题在于它是一个纯文本
完整日历不包含工作时间功能选项(在任何一天的议程 View 中选择第一行和最后一行 - 例如公司不工作)。我做到了类似的事情: viewDisplay: function(view){
我正在使用 bootstrap 作为我的下拉菜单。但有一个问题, 如果我的下拉菜单有多级子菜单,那么它会显示在屏幕上,并出现底部滚动条。 如何将子菜单保留在屏幕内,我需要一个 jQuery 解决方案。
我有一个要转换为 C# 的 Excel 宏。目前我手动转到一个已经打开的 IE 窗口,从中复制所有内容(html 表)并粘贴到 excel 工作表中。然后我正在处理数据。这非常有效,因为将 html
我用谷歌搜索了一下,但没有找到好的结果。 现在我正在构建一个网站,我试图从一开始就从设计的角度使其尽可能正确。 我现在面临的问题是,在决定开始使用日志记录时,我需要一个项目来放置这段代码。由于我无法在
我是一名优秀的程序员,十分优秀!