3

我有返回大对象的服务,默认传输模式(缓冲)不适合我们的要求。

实际上,该服务已经编写好了,项目团队正在经历内存不足的异常和间歇性的性能下降。现在这需要通过一些补丁来解决,重写所有服务不是一个选项,因为项目团队即将交付。

我知道将传输模式更改为 StreamedResponse/Streamed 可能会大有帮助 + 选择 net.tcp 而不是 http 绑定(具有胖客户端的内联网应用程序)。我需要知道我是否会为所有操作合同或仅那些返回 Stream/Message 的操作合同受益。

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

这里唯一缺少的是一些具体的文档,清楚地表明它影响所有操作合同,而与返回类型无关。我需要一些参考资料,以便我可以推动我对这个 chnage 的建议。

请不要建议不要从服务中返回 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 的解释是正确的(它将在一个块中接收的最大大小)。我还必须补充一点,如果我切换到缓冲模式,同样的方法会失败。

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

我将再次重复我的问题,以免它丢失:)

这里唯一缺少的是一些具体的文档,清楚地表明它影响所有操作合同,而与返回类型无关。我需要一些参考/经验,以便我可以推动我对这个 chnage 的建议。

任何帮助都感激不尽!

谢谢,

一种

4

1 回答 1

3

终于找到了相关的东西。

DataSet 是 IXMLSerializable 的继承子代,因此它是流式传输的候选对象。以下摘自 MSDN(流式消息传输

流式传输中发生的操作最多可以与一个输入或输出参数签订合同。该参数对应于消息的整个主体,并且必须是 Message、Stream 的派生类型或IXmlSerializable实现。有一个操作的返回值相当于有一个输出参数。

并且 DataSet 是IXmlSerializable的实现。数据集的定义

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

谢谢,

一种

于 2013-06-03T08:27:57.420 回答