我使用basicHttpBinding在IIS中托管WCF服务。 WCF Web服务使用ADO.Net查询后端SQL Server 2008,并将DataTable返回到WCF服务的客户端。
我发现当返回的DataTable很大时,会有异常表示http连接被IIS关闭。任何想法有什么不对,以及如何设置更大的响应大小?另一个想法是对象的序列化大小是否有任何硬性限制(我想可能DataTable实例太大而不能序列化?)
IIS返回的错误信息是:
异常消息:
接收时发生错误 HTTP响应 http://labmachine1/service.svc。这个 可能是由于服务端点 绑定不使用HTTP协议。 这也可能是由于HTTP造成的 请求上下文被中止 服务器(可能是由于服务 关闭)。请参阅服务器日志 更多细节。
{“基础连接已关闭:发生意外错误 收到。“}
这是我服务器端的完整源代码,对于我在web.config中托管的服务器,默认值没有变化。由于我在IIS中托管,我使用basicHttpBinding。
public class StudentManagement : IStudentManagement
{
public DataTable Poll(int Id)
{
return MakeParentTable();
}
private DataTable MakeParentTable()
{
// Create a new DataTable.
System.Data.DataTable table = new DataTable("ParentTable");
// Declare variables for DataColumn and DataRow objects.
DataColumn column;
DataRow row;
// Create new DataColumn, set DataType,
// ColumnName and add to DataTable.
column = new DataColumn();
column.DataType = System.Type.GetType("System.Int32");
column.ColumnName = "id";
column.ReadOnly = true;
column.Unique = true;
// Add the Column to the DataColumnCollection.
table.Columns.Add(column);
// Create second column.
column = new DataColumn();
column.DataType = System.Type.GetType("System.String");
column.ColumnName = "ParentItem";
column.AutoIncrement = false;
column.Caption = "ParentItem";
column.ReadOnly = false;
column.Unique = false;
// Add the column to the table.
table.Columns.Add(column);
// Make the ID column the primary key column.
DataColumn[] PrimaryKeyColumns = new DataColumn[1];
PrimaryKeyColumns[0] = table.Columns["id"];
table.PrimaryKey = PrimaryKeyColumns;
// Create three new DataRow objects and add
// them to the DataTable
for (int i = 0; i <= 1000000; i++)
{
row = table.NewRow();
row["id"] = i;
row["ParentItem"] = "ParentItem " + i;
table.Rows.Add(row);
}
return table;
}
}
客户端代码:
static void Main(string[] args)
{
StudentIdentifier identifier = new StudentIdentifier();
identifier.Id = 100;
StudentManagementClient client = new StudentManagementClient();
DataTable student = client.Poll(identifier);
Console.WriteLine(student.Rows.Count);
}
客户端web.config:
<binding name="BasicHttpBinding_IStudentManagement" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false"
hostNameComparisonMode="StrongWildcard"
maxBufferSize="1000000000" maxBufferPoolSize="1000000000"
maxReceivedMessageSize="1000000000"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="1000000000"
maxArrayLength="1000000000"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
</binding>
编辑2:
客户端app.config的流模式配置,
<basicHttpBinding>
<binding name="BasicHttpBinding_IStudentManagement" closeTimeout="00:01:00"
openTimeout="00:20:00" receiveTimeout="01:00:00" sendTimeout="01:00:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="1500000000" maxBufferPoolSize="1500000000" maxReceivedMessageSize="1500000000"
messageEncoding="Mtom" textEncoding="utf-8" transferMode="Streamed"
useDefaultWebProxy="true">
<readerQuotas maxDepth="1500000000" maxStringContentLength="1500000000"
maxArrayLength="1500000000" maxBytesPerRead="1500000000" maxNameTableCharCount="1500000000" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
用于流模式的服务器端web.config,
<basicHttpBinding>
<binding name="BasicHttpBinding_IStudentManagement" closeTimeout="00:01:00"
openTimeout="00:20:00" receiveTimeout="01:00:00" sendTimeout="01:00:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="1000000000" maxBufferPoolSize="1000000000" maxReceivedMessageSize="1000000000"
messageEncoding="Mtom" textEncoding="utf-8" transferMode="Streamed"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="1000000000" maxArrayLength="1000000000"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
答案 0 :(得分:5)
您可以使用多种缓冲区大小 - 默认情况下它们保持相当小(64K)以避免拒绝服务攻击,但如果您需要,可以增加这些:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="largebuffers" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false"
hostNameComparisonMode="StrongWildcard"
maxBufferSize="524288" maxBufferPoolSize="524288"
maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192"
maxArrayLength="16384" maxBytesPerRead="4096"
maxNameTableCharCount="16384" />
</binding>
</basicHttpBinding>
</bindings>
查看绑定中的“MaxBufferSize”,“MaxBufferPoolSize”,“MaxReceivedMessageSize”设置,以及<readerQuotas>
部分中的各种设置。
我会首先尝试增加“MaxBufferSize”和“MaxBufferPoolSize”,看看是否有帮助 - 大多数其他设置应该更加适应服务接收和需要处理消息的时间。
对于序列化的对象有多大没有硬性限制。但是,DataTable确实会带来很大的开销,如果您在客户端并不真的需要DataTable功能,那么您也可以在服务器上进行转换以仅发回一个集合或通用的对象列表 - 而不是重型DataTable对象。
此外,如果您经常发回大量数据,您可能也需要调查WCF的流媒体功能(例如,如果您返回图片,视频,那种东西)。 马克
答案 1 :(得分:2)
乔治,当这样的事情发生时,请务必查看事件日志。查看WCF或任何其他组件是否记录了错误。
此外,尝试启用WCF跟踪并查看是否存在未以某种方式记录的内部错误。您可能需要使跟踪详细,以便查看它,但看一看,看看有什么。
仅仅因为你从IIS中得到了一个模糊的错误,并不意味着某些地方没有更多更好的信息。毕竟,错误消息 说“请参阅服务器日志以获取更多详细信息。”
答案 2 :(得分:0)
请参阅以下代码段..
<bindings>
<netTcpBinding>
<binding name="ECMSBindingConfig" closeTimeout="00:10:00" openTimeout="00:10:00"
sendTimeout="00:10:00" maxBufferPoolSize="2147483647" maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647" portSharingEnabled="true">
<readerQuotas maxArrayLength="2147483647" maxNameTableCharCount="2147483647"
maxStringContentLength="2147483647" maxDepth="2147483647"
maxBytesPerRead="2147483647" />
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="ECMSServiceBehavior">
<dataContractSerializer ignoreExtensionDataObject="true" maxItemsInObjectGraph="2147483647" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceTimeouts transactionTimeout="00:10:00" />
<serviceThrottling maxConcurrentCalls="200" maxConcurrentSessions="100"
maxConcurrentInstances="100" />
</behavior>
</serviceBehaviors>
</behaviors>
答案 3 :(得分:0)
也许对某人有帮助。
我有同样的错误。它是通过在服务器端web.config中设置MaxItemsInObjectGraph属性(为大值)来解决的:
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<dataContractSerializer maxItemsInObjectGraph="100000"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="MyServiceBehavior" name="Company.MyService">
<!-- etc -->
</service>
</services>