WCF:除了Stream和Message之外的流传输模式和方法返回类型

时间:2013-05-30 06:16:47

标签: wcf streaming

我有返回大对象的服务,默认transfermode(缓冲)不符合我们的要求。

实际上,服务已经编写,项目团队正在经历内存不足异常并且间歇性地降低性能。现在需要通过一些补丁修复,重新启动所有服务都不是一个选项,因为项目团队接近交付。

我理解将transfermode更改为StreamedResponse / Streamed可能会有很大帮助+选择net.tcp而不是http绑定(使用胖客户端的Intranet应用程序)。我需要知道我是否会获得所有操作合同或仅返回Stream / Message的那些操作。

我创建了一个小样本来检查它是否对其他返回类型(DataTable / DataSet)有任何影响,并且似乎它会影响所有返回类型,包括DataTable / DataSet。我检查了WCF HttpTransport: streamed vs buffered TransferMode,看起来其他人也经历过同样的行为。

这里唯一缺少的是一些具体的文档,它清楚地表明它会影响所有的操作契约,而不管返回类型如何。我需要一些参考资料,以便我可以推荐我的推荐。

请不要建议不要从服务中返回DataTable / DataSet; 我知道这是一个糟糕的做法,应该一直避免,但在这种情况下,服务已经存在,我现在不能要求他们改变一切。

更新 我的看法基于以下测试

我的界面

[ServiceContract]
public interface IMediaManager
{
    [OperationContract]
    Stream Play(int mediaId);

    [OperationContract]
    DataSet GetJunk();
}

我的实施

public class MediaManager : IMediaManager
{
    public Stream Play(int mediaId)
    {
        String path = GetMedia(mediaId);
        FileStream fStream = new FileStream(path, FileMode.Open, FileAccess.Read,FileShare.Read);
        return fStream;
    }

    public DataSet GetJunk()
    {
        return GetLargeJunkDataSet20PlusMegs();
    }
}

通过IIS托管 - 非Http WAS,服务器配置文件(剥离标签,仅限相关标签)

<system.serviceModel>
<services>
  <service name="MediaService.MediaManager" behaviorConfiguration="MediaServiceBehavior">
    <host>
      <baseAddresses>
        <add baseAddress="net.tcp://localhost:9876/MediaService/MediaManager.svc" />
      </baseAddresses>
    </host>
    <endpoint address="" binding="customBinding"
              bindingConfiguration="StreamedTcpBinding" name="MediaManagerTcp"
              contract="MediaService.IMediaManager" />
    <endpoint address="mexTcp" binding="mexTcpBinding" name="mexTcp"
              contract="IMetadataExchange" />
  </service>
</services>
<bindings>
  <customBinding>
    <binding name="StreamedTcpBinding" sendTimeout="00:10:00" receiveTimeout="00:10:00">
      <binaryMessageEncoding />
      <tcpTransport transferMode="Streamed" portSharingEnabled="true"  />
    </binding>
  </customBinding>
</bindings>

客户端配置文件(仅限相关标签)

<binding name="MediaManagerTcp" closeTimeout="00:01:00" openTimeout="00:01:00"
      receiveTimeout="00:10:00" sendTimeout="00:01:00" transactionFlow="false"
      transferMode="Streamed" transactionProtocol="OleTransactions"
      hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="2147483647"
      ***maxBufferSize="1001"*** maxConnections="10" maxReceivedMessageSize="2147483647">
      <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
      <reliableSession ordered="true" inactivityTimeout="00:10:00"
        enabled="false" />
      <security mode="None">
        <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
        <message clientCredentialType="Windows" />
      </security>
    </binding>

如果你看到上面的内容, maxBufferSize 是1001字节,但实际的消息是20+ mb。这让我觉得Streamed也适用于DataSet(一切,不仅限于Stream和Message)。我希望我的解释是正确的maxBufferSize(它将在一个块中接收的最大大小)。 我还必须补充说,如果我切换到缓冲模式,同样的方法就会失败。

我希望我的分析有道理,如果不清楚那么请告诉我,我会再试一次?

我会再次重复我的问题,以免它迷失:)

这里唯一缺少的是一些具体的文档,它清楚地表明它会影响所有的操作契约,而不管返回类型如何。我需要一些参考/经验,以便我可以推荐我的推荐。

非常感谢任何帮助!

谢谢,

A

1 个答案:

答案 0 :(得分:1)

终于找到了相关的东西。

DataSet是IXMLSerializable的继承子,因此它是流式传输的候选者。从MSDN(Streaming Message Transfer

中挑选了以下内容
  

流式传输中发生的操作最多只能包含一个输入或输出参数。该参数对应于消息的整个主体,并且必须是Message,派生类型的Stream或 IXmlSerializable 实现。具有操作的返回值等同于具有输出参数。

和DataSet是 IXmlSerializable 的实现。 DataSet的definition

[SerializableAttribute]
public class DataSet : MarshalByValueComponent, IListSource, 
IXmlSerializable, ISupportInitializeNotification, ISupportInitialize,ISerializable

谢谢,

A