WCF Message Size Quotas

http://geekswithblogs.net/smyers/archive/2011/10/05/wcf-service-message-timeouts-size-limits-tips-and-tricks.aspxvice Message Timeouts, Size Limits, Tips and Tricks

Wednesday, October 05, 2011 4:23 PM
Is your WFC Service hitting the Maximum Limits set on the default service configurations? Open up the artificial constraints of the WCF Service Debugging WCF Services and message sizes. Caveat emptor: If you need to increase the size of the of the contracts, it probably indicates that you should reexamine the design of your data contract.  In any case, to “Open Up” the service, you will need to set on both the client and server side configurations:
1.        Timeouts
2.       Message Sizes
3.       Max Objects In Graph
Service side configurations
<system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behaviorname="Server.WcfService.MyServiceBehavior">
          <serviceMetadata httpGetEnabled="truehttpsGetEnabled="false" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <dataContractSerializer maxItemsInObjectGraph="2147483647" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="Server.WcfService.MyServiceBehavior" 
       
name="Server.WcfService.MyService">
<endpoint address="http://MyServer:1260/MyService.svc" 
binding="wsHttpBinding"
bindingConfiguration="MyServiceBinding" 
contract="Server.WcfService.IMyService" />
        <endpoint address="mexbinding="mexHttpBindingcontract="IMetadataExchange" />
      </service>
    </services>
    <bindings>
      <wsHttpBinding>
        <binding name="MyServiceBinding"
                 maxReceivedMessageSize="2147483647"
                 openTimeout="00:10:00"
                 receiveTimeout="00:10:00"
                 sendTimeout="00:10:00"
                 closeTimeout="00:10:00"
                 maxBufferPoolSize="2147483647" >
        </binding>
      </wsHttpBinding>
    </bindings>
 </system.serviceModel>
 
Client side configurations
<system.serviceModel>
    <bindings>
      <wsHttpBinding>
<binding name="WSHttpBinding_IMyService" 
closeTimeout="00:10:00" 
openTimeout="00:10:00" 
receiveTimeout="00:10:00" 
sendTimeout="00:10:00"
bypassProxyOnLocal="false"
transactionFlow="false"
hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="2147483647" 
maxReceivedMessageSize="2147483647" 
messageEncoding="Text"
textEncoding="utf-8"
useDefaultWebProxy="true"
allowCookies="false">
      <readerQuotas maxDepth="32"
maxStringContentLength="2147483647"
maxArrayLength="2147483647" 
maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
<reliableSessionordered="true"
inactivityTimeout="00:10:00"
enabled="false"/>
        </binding>
      </wsHttpBinding>
    </bindings>
    <client>
<endpoint 
address=http://MyServer/MyService.svc
binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IMyService"
contract="MyServiceReference.IMyService"
name="WSHttpBinding_IMyService"
      behaviorConfiguration="MyServiceBehavior"/>
    </client>
    <behaviors>
      <endpointBehaviors>
        <behavior name="MyServiceBehavior">
<dataContractSerializer 
maxItemsInObjectGraph="2147483647" />
        </behavior>
      </endpointBehaviors>
    </behaviors>
 </system.serviceModel>
What is this 2,147,483,647business? It is equal to 231 – 1, the max value of a 32 bit signed integer. 
When setting these tags, you should save yourself some headaches and use the Configuration Editor (SvcConfigEditor.exe):
http://msdn.microsoft.com/en-us/library/ms732009.aspx
To test out your developed client, you can call the WCF service directly without writing your own client. Microsoft has provided one: 
http://msdn.microsoft.com/en-us/library/bb552364.aspx
Security: use it. Make sure your client and service side tags match. You may have noticed that it is absent from the above example.  That means that it is going to use the default which is Message for this particular binding type.  
http://msdn.microsoft.com/en-us/library/ms731059.aspx
When the errors you are receiving don’t seem to make any sense, you can add robust diagnostics by adding the following tag (make sure the service has write access to the location specified in the InitializeData):
 <system.diagnostics>
    <trace autoflush="true" />
    <sources>
      <source name="System.ServiceModel"
              switchValue="Information, ActivityTracing"
              propagateActivity="true">
        <listeners>
          <add name="sdt"
              type="System.Diagnostics.XmlWriterTraceListener"
              initializeData"serviceLog.svcLog" />
        </listeners>
      </source>
    </sources>
 </system.diagnostics>
Call the WCF Service and then view the output file with the SVC Trace viewer tool:
http://msdn.microsoft.com/en-us/library/ms732023.aspx

Tips:

Endpoint Behavior and Service Behavior

Service behaviors

You can define service-level behavior to control elements such as concurrency, transactions, and debugging for a particular service. You can either define it on the service implementation class by using the ServiceBehavior attribute, or in an external configuration file by using the serviceBehaviors element.

Endpoint behaviors

Behaviors at the endpoint level can control aspects of security and transport. You can define behaviors for each endpoint that is exposed by your service. These behaviors come into force when a call to the particular endpoint is made.

You can define your endpoint-level behavior configuration in an external configuration file by using the endpointBehaviors element and the behaviorConfiguration attribute.


Sample Configuration:

<basicHttpBinding>
        <binding name="CMDServiceBinding"
                 receiveTimeout="00:10:00" 
                 closeTimeout="00:10:00" 
                 openTimeout="00:10:00"
                 sendTimeout="00:10:00"
                 maxBufferSize="2147483647"
                 maxBufferPoolSize="2147483647"
                 maxReceivedMessageSize="2147483647">

          <readerQuotas maxDepth="2147483647"
                        maxStringContentLength="2147483647"
                        maxArrayLength="2147483647"
                        maxBytesPerRead="2147483647"
                        maxNameTableCharCount="2147483647" />
        </binding>
</basicHttpBinding>

<behaviors>
    <endpointBehaviors>
      <behavior>
        <dataContractSerializer maxItemsInObjectGraph="10000000"/>
      </behavior>
    </endpointBehaviors>
    <serviceBehaviors>
      <behavior>
        <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
        <serviceMetadata httpGetEnabled="true" />            
        <serviceDebug includeExceptionDetailInFaults="true" />
      </behavior>
    </serviceBehaviors>
  </behaviors>

 <system.web>
    <httpRuntime maxRequestLength="2147483647" />
  </system.web>

Message Size Quotas
There are several settings that influence how the service model processes messages. Some are specific settings that limit the size of strings, array lengths, object graphs, XML nesting and overall message size. Other settings control how buffering is handled and act as a throttle for memory usage and garbage collection overhead. The following are the different binding properties and behaviors that control these settings. I've broken them down into three categories:
The following properties are binding quotas—a direct property of the binding:
MaxBufferPoolSize
Pre allocates the buffer to process incoming requests instead of allocating from the heap. You can tune this to reduce pressure on the garbage collector. 
MaxBufferSize
Limits the buffer size of incoming messages. When messages are buffered, this must match MaxReceivedMessageSize, and for streaming, this should be less to reduce buffering. 
MaxReceivedMessageSize
Limits the overall serialized message size received by services and clients. This has nothing to do with memory usage—deserialized messages may consume additional memory.
The following properties are reader quotas—part of the ReaderQuotas binding property that affects how XML readers process messages
MaxArrayLength
Limits the length of strings and other arrays including byte arrays for large binary transfers. 
MaxBytesPerRead Limits the number of bytes per read operation. 
MaxDepth
Limits the nesting depth of XML elements. Data contracts with nested objects will generate nested XML, for example. 
MaxNameTableCharCount
Limits the size of the reader nametable, which includes prefixes and namespaces in the XML stream.
MaxStringContentLength
Limits the length of string elements.
The last behavior is a data contract serializer quota. This quota is provided through a behavior, as opposed to a binding property:
MaxItemsInObjectGraph Limits the number of objects that can be present in an object graph during serialization. If you are passing around objects with many nested reference types, you may exceed this limit.
DataContractSerializer.MaxItemsInObjectGraph: Gets the maximum number of items in an object graph to serialize or deserialize.
First, if the DataContractSerializer behavior is supplied as a service behavior, it applies to all of the non-metadata endpoints in your service.
Tip:

An object graph is not a single object, but rather a set of related objects. For a simple example, consider:

public class Node {
    public string Name {...}
    public Node Parent {...}
    public List<Node> Children {...}
}

where each child knows about the parent (and the parent knows about the child).

The problem is that xml is a tree based on object properties... and it wants to just walk them - i.e. with the simple parent/child:

  • A (knows that B is its child)
    • B (knows that A is its parent)

that would serialize as:

<Node>
  <Name>A</Name>
  <!-- no Parent as A is the top node, so null -->
  <Children>
     <Node>
        <Name>B</Name>
        <Parent>
           <Node>
              <Name>A</Name>
              *** boom ***

You can see that we got back to A, so we're now in an endless loop

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章