56

技术问题分析-报文解析(10.23)

 5 years ago
source link: http://blog.sina.com.cn/s/blog_493a84550102y14s.html?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

最近OSB服务运行,经常会在服务异常监控日志中发现调用异常,具体信息为:

OSB-382030: Failure while un-marshalling message: Unable to convert from this source type to XmlObjectSource: com.bea.wli.sb.sources.DataSourceSource。

该异常出现后由于输入的SOAP请求报文出现解析错误,因此对于输入日志无法完全获取和记录,即也无法判断究竟是消费方调用的时候本身报文不完整还是由于OSB在进行Xml Parse解析的时候出现错误。对于这个错误,在Oracle Support网站有专门一篇文章进行说明,具体地址为:

Unable to convert from this source type to XmlObjectSource

在这篇文章里面做了详细的分析,即该服务调用异常导致的原因为: xmlobject parse results in error either because the xml being parsed is bad or the inputstream is getting closed in the middle of a parse (which actually results in bad xml) interrupting the operation.

给出的解决方案为:

Login to the WebLogic Console

Go to DOMAIN -> Servers -> ManagedServer -> Protocols -> HTTP

1. Please keep the Keep Alive OFF

2. Increase the Post Timeout from 30 seconds to 120seconds

但是发现及时修改了该配置,仍然会出现上面这个错误,但是无法确定是否是消费方本身传入的报文就不完整导致的,因为消费方本身传入报文不完整提升的信息会有差异,即在XML本身报文结构不对或不完整的时候,体现的异常信息为 :OSB-382030: Failed to Parse Xml Text ,这个异常跟上面的错误异常还是有差别。因此暂时也无法确定是否是报文原因导致。

为排查这类问题,最好的方法仍然是需要消费方系统对传入到OSB服务总线的输入报文进行Log记录,以方便后续进一步排查问题。

为了进一步分析,我们在服务调用出现异常的时候增加了Http-Header头记录。在里面可以log到 Transfer-Encoding: chunked日志记录。

对里面传递的chunked参数做进一步分析,该参数说明在SOAP消息传输的时候可以分块传输,这个和前面谈到的Post Time Out设置也有关系。而对于Post Time Out解释为: 读取 servlet 请求中 HTTP POST 数据的超时 (秒)。如果 POST 数据已分块, 则为服务器在 HTTP POST 中完成接收上一个数据块到完成接收下一个数据块之间等待的时间长度, 超过此时间长度则会超时。

而客户端在消费和调用WS服务的时候,可以启用Chunk分块编码,具体说明见这篇文章:

https://www.cnblogs.com/xuehaoyue/p/6639029.html

启用Chunk分块传输的背景:

持续连接的问题:对于非持续连接,浏览器可以通过连接是否关闭来界定请求或响应实体的边界;而对于持续连接,这种方法显然不奏效。有时,尽管我已经发送完所有数据,但浏览器并不知道这一点,它无法得知这个打开的连接上是否还会有新数据进来,只能傻傻地等了。

用Content-length解决:计算实体长度,并通过头部告诉对方。浏览器可以通过 Content-Length 的长度信息,判断出响应实体已结束

Content-length引入的新问题:由于 Content-Length 字段必须真实反映实体长度,但是对于动态生成的内容来说,在内容创建完之前,长度是不可知的。这时候要想准确获取长度,只能开一个足够大的 buffer,等内容全部生成好再计算。但这样做一方面需要更大的内存开销,另一方面也会让客户端等更久。

我们需要一个新的机制:不依赖头部的长度信息,也能知道实体的边界——分块编码(Transfer-Encoding: chunked)

分块编码(Transfer-Encoding: chunked)

Transfer-Encoding,是一个 HTTP 头部字段(响应头域),字面意思是「传输编码」。最新的 HTTP 规范里,只定义了一种编码传输:分块编码(chunked)。

分块传输编码(Chunked transfer encoding)是超文本传输协议(HTTP)中的一种数据传输机制,允许HTTP由网页服务器发送给客户端的数据可以分成多个部分。分块传输编码只在HTTP协议1.1版本(HTTP/1.1)中提供。数据分解成一系列数据块,并以一个或多个块发送,这样服务器可以发送数据而不需要预先知道发送内容的总大小。

在HttpHeader头部加入 Transfer-Encoding: chunked 之后,就代表这个报文采用了分块编码。这时,报文中的实体需要改为用一系列分块来传输。每个分块包含十六进制的长度值和数据,长度值独占一行,长度不包括它结尾的 CRLF(\r\n),也不包括分块数据结尾的 CRLF。最后一个分块长度值必须为 0,对应的分块数据没有内容,表示实体结束。

但是暂时无法确认是否是和OSB对启用Chunk分块传输的支持有关系。由于本身服务异常调用的是少量服务,大部分服务调用仍然成功运行,因此获取消费端报文数据,然后进一步验证才能够从根源上找到原因。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK