实现 IBM Integration Bus 中的内部缓冲区和字符串处理结构的数据类型,可能限制一条消息中可以处理的数据大小。IBM Integration Bus 具有两个主要的数据大小限制。首先,它对一个位流中的位置索引的大小具有 2-Gb 的限制。第二,它对内部数据缓冲区的大小具有 4-Gb 的限制。本教程将演示如何使用 MTOM 和 MIME 解析器发送和接收具有大型附件的 SOAP 消息。
解析器接口使用一种有符号 int 数据类型来记录位流中的位置。有符号 int 类型具有 2-Gb 的限制。由此推断,解析器接口无法访问位流中超出 2-Gb 标记的任何点。
第二个限制位于存储数据缓冲区的数据结构中,数据缓冲区表示一个消息的逻辑模型中的解析树数据。此结构使用无符号 int 数据类型来表示一个内部缓冲区的大小和此缓冲区中的任何位置信息。无符号 int 数据类型具有 4-Gb 的限制。
最初,似乎无法使用数据缓冲区中提供的额外的 2 Gb,因为输入位流的大小限制为 2 Gb。但是,在解析树中存储 CHARACTER 数据的地方,使用 UCS-2(一种 UTF-16 变形)来表示。此代码页是一个双字节代码页。因此,单字节代码页中的每个字符(比如 ASCII 或 UTF-8)在消息树中是通过两个字符表示的。例如,考虑解析树中表示为单个 CHARACTER 元素的一个完整的 2-Gb 输入流。
类似地,您可以使用扩展的 SQL (ESQL)、Java、C 或 .NET 接口直接在树中创建元素。在某些情况下,很难在不使用缓冲区扩展来快速耗尽系统上的可用内存的情况下创建元素。但是,在理论上,您可以直接使用大于 2 Gb 的数据缓冲区创建元素。但是 4-Gb 限制仍然有效。
这些限制的最明显后果是,对输入节点的一次调用所读取的单个输入消息的最大大小限制为 2 Gb。类似地,因为 CHARACTER 数据会在消息树中展开,所以消息树中的单个元素的最大大小为 2-Gb 字符。
此外,一些处理类型(比如需要对数据采用 Base64 编码或十六进制编码)可能导致在树中存储输出所需的空间比原始来源数据更大。例如,如果处理需要对 UTF-8 数据执行 hexBinary 编码,那么解析树中需要 4 倍的空间。与输入数据相比,每个字节表示为包含十六进制表示的 2 字节。然后,每 2 个字节被存储为 2 字节 UCS-2 字符。这些因素将经历这种处理类型的元素的大小限制到 1 Gb 输入数据。
在某些情况下,使用流传输(比如 FileInput 节点或 TCP/IP 节点)支持将完整的大型消息拆分为多个较小的记录。通过使用此技术,可以处理大于 2 Gb 的输入消息。但是,对消息流的单次调用绝不会获得超过 2 Gb 的数据。
在其他情况下,传输方式的选择受到约束。不是 IBM Integration Bus 中的所有传输方式都支持流的概念。在这种情况下,应该小心地使用消息树和了解数据存储和扩展方式,这可能改进消息流可处理的消息的最大大小。例如,二进制大对象 (BLOB) 数据不会在树中扩展为 UCS-2。如果消息的各部分可表示为二进制内容,那么确保将此数据视为二进制吞吐量来处理可能允许处理更大的消息。
回页首
考虑 IBM Integration Bus 可集成的各种后端系统,一些系统在集成方法上具有限制。具体地讲,限制在于使用 Web 服务发送和接收大型文件的能力。使用 HTTP 或 Web 服务传输大型文件不是最高效的方法。但是,有时此集成方法是唯一可用的方法。
您可以从一些方法中选择使用 Web 服务调用来发送和接收文件:
有关使用 Web 服务的不同方法和文件传输的信息,请参阅 WebSphere Message Broker V6.1 中的文件处理 。对于本教程中的用例,后端服务支持 MTOM。下一节将介绍如何使用 MTOM 发送和接收文件,同时绕过 IBM Integration Bus 中对文件大小的内部限制。
回页首
在典型场景中,IBM Integration Bus 中的 SOAP 请求在以下条件下支持 MTOM:
没有了 IBM Integration Bus 中对树中的元素大小的限制,此解决方案可能在处理时间和内存消耗上可能具有很高的成本。此成本的很大一部分可能是验证大量 SOAP 消息所导致的。此外,使用 Base64 编码或十六进制编码来对数据编码的成本也会随消息大小增加而增加。成本可能花在验证大量 SOAP 消息和在 SOAP 请求节点之前将文件编码为 Base64 的需求上。
此限制的解决办法在处理时间和内存消耗上提供了更高效的解决方案。此解决方案避免了验证 SOAP 请求和在将文件发送到 Web 服务之前编码为 Base64。
以下各节将介绍如何使用 HTTP 节点和 MIME 解析器来发送和接收大型文件。在这个示例中,同一个服务需要请求消息中包含一个文件并在响应中返回该文件。
使用 HTTP 节点和 MIME 解析器,为您提供了绕过 IBM Integration Bus 中的文件大小限制的能力。在本质上,MTOM 消息是一个在连接上传输的多部分消息。消息的第一部分是按照标识符 (ID) 来引用该文件的 SOAP 信封。消息的第二部分是由一个 ID 标识的文件。
清单 1 给出了在连接上传输的 MTOM 消息的示例。
清单 1. 在连接上传输的 MTOM 消息
Content-Type: multipart/related; boundary= dwMIMEBoundry ; type="application/xop+xml"; start="<soap@ibm.com>"; start-info="text/xml"; charset=UTF-8 u --dwMIMEBoundary content-type: application/xop+xml; charset=UTF-8; type="text/xml"; content-transfer-encoding: binary content-id: <soap@ibm.com> <?xml version="1.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header/> <soapenv:Body> <Request> <input> <fileName></fileName> <file> <xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:thefile@ibm.com"/> </file> </input> </Request> </soapenv:Body> </soapenv:Envelope> --dwMIMEBoundary content-type: text/plain content-transfer-encoding: binary content-id: <thefile@ibm.com> ... binary data goes here ...
前面已经提到,MTOM 和 MIME 解析器可帮助绕过大小限制。
图 1显示了使用 MIME 实现 MTOM 的子工作流的一部分。
图 1. 实现 MTOM 的子工作流
构建 MIME 消息的过程在 BuildRequest ESQL Compute 节点中执行。清单 2 给出了此代码的实现。在此代码中,该文件存在于 Compute 节点前面的环境变量中。该代码有 3 节。每节对应于 MTOM 消息的一部分:
清单 2. 节点实现
点击查看代码清单
关闭 [x]
------------------------------------------Section 1-------------------------------------------- DECLARE MIMEBoundary CHAR 'dwMIMEBoundary'; DECLARE url char ''; SET OutputLocalEnvironment = InputLocalEnvironment; SET OutputLocalEnvironment.Destination.HTTP.RequestURL ='theWebService.com'; SET OutputRoot.Properties.ContentType = 'multipart/form-data; boundary=' || '"'|| MIMEBoundary||'"'; SET OutputRoot.HTTPRequestHeader."X-Original-HTTP-URL" ='theWebService.com'; SET OutputRoot.HTTPRequestHeader."Content-Type" = 'multipart/related; type="application/xop+xml"; start="<soapenv@ibm.com>"; start-info="text/xml"; boundary=' || '"'|| MIMEBoundary||'"'; SET OutputRoot.HTTPRequestHeader."SOAPAction"=''; SET OutputRoot.HTTPRequestHeader."MIME-Version"='1.0'; CREATE FIELD OutputRoot.MIME TYPE Name; DECLARE mm REFERENCE TO OutputRoot.MIME; CREATE LASTCHILD OF mm TYPE Name NAME 'Parts'; CREATE LASTCHILD OF mm.Parts TYPE Name NAME 'Part'; ------------------------------------------Section 2-------------------------------------------- Creating the Soap Request message in the environment in order to cast as BLOB later. CREATE LASTCHILD OF Environment.Variables DOMAIN 'XMLNSC' NAME 'XMLNSC'; DECLARE soapenv NAMESPACE 'http://schemas.xmlsoap.org/soap/envelope/'; DECLARE xop NAMESPACE 'http://www.w3.org/2004/08/xop/include'; CREATE FIELD Environment.Variables.XMLNSC.soapenv:Envelope.soapenv:Body; SET Environment.Variables.XMLNSC.soapenv:Envelope.soapenv:Body.ns:Request.input.fileName='theFilename'; SET Environment.Variables.XMLNSC.soapenv:Envelope.soapenv:Body.ns:Request.input.file.xop:Include.(XMLNSC.Attribute)href='cid:thefile@ibm.com'; DECLARE soapEnv BLOB ; SET soapEnv = CAST (ASBITSTREAM( Environment.Variables.XMLNSC) AS BLOB CCSID 1208); ------Doing first part of the message which contains the soap envelope------------- DECLARE Part1 REFERENCE TO mm.Parts.Part[1]; CREATE FIELD Part1."Content-Type" TYPE NameValue VALUE 'application/xop+xml; charset=UTF-8; type="text/xml"'; CREATE FIELD Part1."Content-ID" TYPE NameValue VALUE '<soapenv@ibm.com>'; CREATE LASTCHILD OF Part1 TYPE Name NAME 'Data'; CREATE LASTCHILD OF Part1.Data DOMAIN('BLOB') PARSE(soapEnv); ------------------------------------------Section 3------------------------------------------------ Adding file in the second part of the message CREATE LASTCHILD OF mm.Parts TYPE Name NAME 'Part'; DECLARE refPart REFERENCE TO mm.Parts; DECLARE Part2 REFERENCE TO refPart; MOVE Part2 TO refPart.Part[2]; CREATE FIELD Part2."Content-Disposition" TYPE NameValue VALUE 'attachment; name='||'"file"; filename='||'"thefile.zip"'; CREATE FIELD Part2."Content-Type" TYPE NameValue VALUE 'application/octet-stream'; CREATE FIELD Part2."Content-Transfer-Encoding" TYPE NameValue VALUE 'binary'; CREATE FIELD Part2."Content-ID" TYPE NameValue VALUE '<thefile@ibm.com>'; CREATE LASTCHILD OF Part2 TYPE Name NAME 'Data'; CREATE LASTCHILD OF Part2.Data DOMAIN('BLOB') PARSE(Environment.Variables.file);
文件大小限制也适用于从 SOAP 调用响应接收文件时。为了绕过大小限制,我们使用了一个 MIME 解析器和 HTTP 节点,通过 MTOM 接收大型文件。
为了确保后端服务使用一个多部分消息和 MTOM 来响应,服务请求必须是一个由多个部分组成的消息。但是,后端服务必须支持 MTOM。
图 2显示了使用 MIME 实现 MTOM 的子工作流的一部分。
图 2. 实现 MTOM 的子工作流
将 SOAP 请求消息构建为由多个部分组成的消息的过程在 TransSoapToBlob Compute 节点中执行。在清单 3 中,SOAP 消息位于 Compute 节点前面的一个环境变量中。
清单 3. TransSoapToBlob Compute 节点实现
DECLARE soapString CHAR; SET soapString= Environment.Variables.SoapString; SET Environment.MIMEBoundary = 'MIMEBoundary'; SET OutputLocalEnvironment = InputLocalEnvironment; SET OutputLocalEnvironment.Destination.HTTP.RequestURL = 'theservice.com'; SET OutputRoot.Properties.ContentType = 'multipart/form-data; boundary=' || '"'|| Environment.MIMEBoundary||'"'; SET OutputRoot.HTTPRequestHeader."X-Original-HTTP-URL" ='theservice.com'; SET OutputRoot.HTTPRequestHeader."Content-Type" = 'multipart/related; type="application/xop+xml"; start="<rootpart@ibm.com>"; start-info="text/xml"; boundary=' || '"'|| Environment.MIMEBoundary||'"'; SET OutputRoot.HTTPRequestHeader."SOAPAction"=''; SET OutputRoot.HTTPRequestHeader."MIME-Version"='1.0'; CREATE FIELD OutputRoot.MIME TYPE Name; DECLARE mm REFERENCE TO OutputRoot.MIME; CREATE LASTCHILD OF mm TYPE Name NAME 'Parts'; CREATE LASTCHILD OF mm.Parts TYPE Name NAME 'Part'; DECLARE soapEnv BLOB ; SET soapEnv = CAST (soapString AS BLOB CCSID 1208); DECLARE Part1 REFERENCE TO mm .Parts.Part[1]; CREATE FIELD Part1."Content-Type" TYPE NameValue VALUE 'application/xop+xml; charset=UTF-8; type="text/xml"'; CREATE FIELD Part1."Content-ID" TYPE NameValue VALUE '<rootpart@ibm.com>'; CREATE LASTCHILD OF Part1 TYPE Name NAME 'Data'; CREATE LASTCHILD OF Part1.Data DOMAIN('BLOB') PARSE(soapEnv);
显示的流的第二个节点是 HTTP 调用。确保 Response Message Parsing 的解析器被设置为 MIME,比如 图 3 所示。
图 3. Response Message Parsing 设置
如果服务返回一个有效响应,那么它将包含两个部分。消息的第一部分是 SOAP 响应。消息的第二部分是文件。
第二个 Compute 节点 SaveFileAndExtractResponse 被作为 BLOB 传输的 SOAP 响应而接受,并将文件保存在环境中。清单 4 显示了实现它的代码。
清单 4. SaveFileAndExtractResponse Compute 节点实现
SET OutputRoot.BLOB.BLOB = InputRoot.MIME.Parts.Part[1].Data.BLOB.BLOB; Set Environment.Variables.File = InputRoot.MIME.Parts.Part[2].Data.BLOB.BLOB;
工作流的这个分支中的最后一个节点是 ResetContentDescriptor 节点,它将 BLOB(SOAP 响应)解析为 XMLNSC。
回页首
本教程介绍了如何最大化一个消息流可处理的消息大小。您学习了如何使用 MIME 解析器来确保树的二进制部分没有不必要地扩展为字符数据。处理这种大小的消息要求承载 IBM Integration Bus 运行时的系统上有非常大的内存空间。一般而言,会将这种规模的消息视为流数据。但是,在无法采用此方法的地方,可以使用本教程中描述的技术,使用 MIME 消息向(或从)Web 服务发送和接收大型文件。在此方法可用时,请遵守 IBM Integration Bus 中提供的数据结构的限制。
回页首