0

我正在 BizTalk 中创建一个自定义接收管道,该管道将接收包含作为 base64 字符串的 word 文档的消息。这将从管道配置中的节点集中提取字符串到 memoryStream 并将其传递给 Apose.Words 以将其转换为 PDF 并将其保存到文件中。

从消息中删除 base64 字符串,然后将更新的消息分配回消息正文。然后在消息中提升新创建文件的路径。

我的问题是运行此管道的主机在内存中增加并且似乎没有释放任何资源。目前它以 250MB 运行,并且没有下降。这会导致问题,因为后续调用无法及时处理。

我的代码

管道组件:

public Microsoft.BizTalk.Message.Interop.IBaseMessage Execute(IPipelineContext pContext, Microsoft.BizTalk.Message.Interop.IBaseMessage pInMsg)
    {
        string fileName = GenerateFileName();

        XmlTextReader reader = new XmlTextReader(pInMsg.BodyPart.GetOriginalDataStream());
        var removeNodeReader = new StoreAndRemoveReader(reader, nodeNameOfEncodedFileContents, fileName);

        XmlTranslatorStream translatorStream = new XmlTranslatorStream(removeNodeReader);

        pInMsg.Context.Write(contextKeyForDocumentFilePath, contextNSForDocumentFilePath, fileName);

        pInMsg.BodyPart.Data = translatorStream;

        return pInMsg;          
    }

StoreAndRemoveReader:(取自http://biztalkmessages.vansplunteren.net/articles/dealing-with-base64/

public class StoreAndRemoveReader : XmlReader
{
    private bool inAttribute;
    private XmlReader wrappedReader;
    private string nodeNameOfEncodedFileContents;
    private string documentFilePath;

    public StoreAndRemoveReader(XmlReader wrappedReader,
                                    string nodeNameOfEncodedFileContents,
                                    string documentFilePath)
    {
        this.wrappedReader = wrappedReader;

        this.nodeNameOfEncodedFileContents = nodeNameOfEncodedFileContents;
        this.documentFilePath = documentFilePath;
    }

    public override bool Read()
    {
        Boolean result = wrappedReader.Read();

        if (wrappedReader.IsStartElement() && wrappedReader.LocalName == nodeNameOfEncodedFileContents)
        {
            if (wrappedReader.IsEmptyElement)
            {
                wrappedReader.Read();
            }
            else
            {
                Base64DecodeDocument(wrappedReader);
            }
        }

        return result;
    }

    private void Base64DecodeDocument(XmlReader reader)
    {
        byte[] buffer = new byte[1000];
        int readBytes = 0;

        //FileStream outputFile = new FileStream(this.documentFilePath, FileMode.CreateNew, FileAccess.Write, FileShare.Write);


        using (var outputStream = new MemoryStream(307200))
        {
           BinaryWriter bw = new BinaryWriter(outputStream);

           while ((readBytes = reader.ReadElementContentAsBase64(buffer, 0, 1000)) > 0)
           {
              bw.Write(buffer, 0, readBytes);
           }

            //File.WriteAllText(this.documentFilePath, "test");
           WordToPDFConversion.ConvertWordDocumentToPdf(outputStream, this.documentFilePath);
        }
    }

尝试修复

我尝试在 XmlTextReader 和 StoreAndRemoveReader 的管道组件中使用语句,但这不起作用,因为我假设它关闭了传入消息的流。

我尝试过独立运行 Aspose,它确实使用了大量内存,但之后它确实会清除它。

总之:

我可以在我的管道组件中处理 Readers,还是有更好的方法来提取数据?

4

2 回答 2

1

250MB 并不是特别大。你检查节流了吗?

另外,是否有理由初始化 300MB MemoryStream?MemoryStream 可以自动神奇地扩展。

建议:

  1. 使用 VirtualStream 而不是 MemoryStream 来用内存换磁盘。
  2. 也许你可以只使用 FileStream。

如果你真的想变得聪明一点,你可以将 ReadElementContentAsBase64 操作再次包装在一个 Stream 接口中。但我认为你不需要走那么远。

于 2014-06-23T15:24:41.750 回答
0

我太全神贯注于内存使用情况,以至于在尝试进行 pdf 转换时忽略了主机的 CPU 使用情况。我添加了一个额外的 BizTalk 服务器来分担负载,CPU 使用率从单个服务器上的 95%~ 下降到每台服务器上的 10%~ 左右。

于 2014-06-25T14:08:59.977 回答