camel丢失请求body问题排查

发布时间:2023年12月18日

项目组要和被收购的公司做接口对接,使用camel进行集成。在使用的过程当中,我们几个小伙伴都遇到了一个相同的问题:请求request body的内容失踪了。这里贴出有问题的路由配置:

<?xml version="1.0"  encoding="UTF-8"?>
<routes xmlns="http://camel.apache.org/schema/spring">
    <route>
        <from uri="rest:post:sett/pay/apply.json"/>
        <log message="接收clivet请求, ${body}"/>
        <setProperty name="template_code">
            <constant>clivet_payment_request_json</constant>
        </setProperty>
        <process ref="json2TemplateProcessor"/>
        <to uri="netty-http:http://127.0.0.1:1234/****/save.json"/>
        <!-- ?httpMethod=POST&amp;transferExchange=true -->
    </route>
</routes>

原因是from接口后紧随的log把HttpRequest的InputStream给消费掉了。导致转发的请求的springmvc读不到数据。把 ${body}去掉即可解决问题。
给出我的排查过程。

排查过程

debug CamelServlet的入口方法

  1. CamelServlet先把request的InputStream读出来,构成成一个InputStreamCache对象,然后写入Exchange的in字段里面。调用堆栈如下:
	  at org.apache.camel.http.common.HttpHelper.readRequestBodyFromServletRequest(HttpHelper.java:147)
	  at org.apache.camel.http.common.DefaultHttpBinding.parseBody(DefaultHttpBinding.java:646)
	  at org.apache.camel.http.common.HttpMessage.createBody(HttpMessage.java:101)
	  at org.apache.camel.support.MessageSupport.getBody(MessageSupport.java:65)
	  at org.apache.camel.http.common.DefaultHttpBinding.readBody(DefaultHttpBinding.java:193)
	  at org.apache.camel.http.common.DefaultHttpBinding.readRequest(DefaultHttpBinding.java:118)
	  at org.apache.camel.http.common.HttpMessage.init(HttpMessage.java:73)
	  at org.apache.camel.http.common.HttpMessage.<init>(HttpMessage.java:39)
	  at org.apache.camel.http.common.CamelServlet.doExecute(CamelServlet.java:274)
	  at org.apache.camel.http.common.CamelServlet.doService(CamelServlet.java:214)
	  at org.apache.camel.http.common.CamelServlet.service(CamelServlet.java:130)

在这里插入图片描述
2. 进入 org.apache.camel.processor.LogProcessor#process 方法这里camel会消费exchange的InputStreamCahce。
在这里插入图片描述
在这里插入图片描述
读完之后,这个流就close了,你是无法再次读出来了。至此,破案。

我们组三个小伙伴都遇到了这个问题,camel官方也意识到了这个问题。官方faq :WHY IS MY MESSAGE EMPTY?

In Camel the message body can be of any types. Some types are safely readable multiple times, and therefore do not ‘suffer’ from becoming ‘empty’. So when you message body suddenly is empty, then that is often related to using a message type that is no re-readable; in other words, the message body can only be read once. On subsequent reads the body is now empty. This happens with types that are streaming based, such as java.util.InputStream, etc.

意即inputstream不能重复消费。

解决方案

1 官方解决方案

camel给出的解决方案 STREAM CACHING,把inputstream缓存起来,供后续重复读。

需要增加如下配置

context.getStreamCachingStrategy().setSpoolEnabled(true);
context.getStreamCachingStrategy().setSpoolDirectory("/tmp/cachedir");
context.getStreamCachingStrategy().setSpoolThreshold(64 * 1024);
context.getStreamCachingStrategy().setBufferSize(16 * 1024);


context.setStreamCaching(true);

2 去掉from节点后的${body}

${body}可以在某个processor消费了inputstream后再使用,但决不能紧跟着from节点用。

文章来源:https://blog.csdn.net/bruce128/article/details/135069410
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。