2013-01-23 33 views
18

Tôi hiện đang gặp sự cố khi gửi dữ liệu lớn bằng dịch vụ lưu trữ tự WCF (không có IIS). Truyền 500MB bằng cách sử dụng kết quả trực tuyến với dịch vụ của tôi gặp sự cố với System.OutOfMemoryException. Hoàn toàn có thể chuyển số lượng dữ liệu đó không?WCF Truyền dữ liệu lớn (500MB/1GB) trên dịch vụ tự lưu trữ

Dưới đây là cấu hình WCF của tôi:

<system.serviceModel> 
<services> 
    <service name="CIService" behaviorConfiguration="CIBehavior">   
    <host> 
     <baseAddresses> 
     <add baseAddress="net.tcp://localhost:6547/CIService/CIService.svc" /> 
     </baseAddresses> 
    </host> 
    <endpoint binding="netTcpBinding" 
     bindingConfiguration="netTcpBindingConfig" 
     behaviorConfiguration="CIBehavior.EndpointBehavior" 
     contract="CIService.ICreatable" /> 
    <endpoint address="mex" 
     binding="mexHttpBinding" 
     name="mexTcpBinding" 
     contract="IMetadataExchange" /> 
    </service> 
</services> 
<serviceHostingEnvironment multippleSiteBindingEnabled="True" /> 
<bindings> 
    <netTcpBinding> 
    <binding name="netTcpBindingConfig" closeTimeout="00:01:00" openTimeout="00:01:00" 
     receiveTimeout="01:00:00" sendTimeout="00:10:00" 
     hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxConnections="10" 
     maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" 
     transferMode="Streamed"> 
     <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" 
     maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" /> 
    </binding> 
    </netTcpBinding> 
</bindings> 

<behaviors> 
    <serviceBehaviors> 
    <behavior name="CIBehavior"> 
     <serviceMetadata httpGetEnabled="False" /> 
     <serviceDebug includeExceptionDetailInFaults="true" /> 
     <serviceThrottling maxConcurrentCalls="200" maxConcurrentInstances="2147483647" maxConcurrentSessions="100" /> 
     <dataContractSerializer maxItemsInObjectGraph="2147483647"/> 
    </behavior> 
    </serviceBehaviors> 
    <endpointBehavior> 
    <behavior name="CIBehavior.EndpointBehavior"> 
     <dataContractSerializer maxItemsInObjectGraph="2147483647" /> 
    </behavior> 
    </endpointBehavior> 
</behaviors> 
</system.serviceModel> 

cấu hình Khách hàng của tôi:

<system.serviceModel> 
<bindings> 
    <netTcpBinding> 
    <binding name="NetTcpBinding_ICreatable" 
      closeTimeout="00:01:00" openTimeout="00:01:00" 
      receiveTimeout="01:00:00" sendTimeout="00:10:00" 
      transactionFlow="false" 
      transferMode="Streamed" 
      transactionProtocol="OleTransactions" 
      hostNameComparisonMode="StrongWildcard" 
      listenBacklog="10" 
      maxBufferPoolSize="2147483647" 
      maxBufferSize="2147483647" 
      maxConnections="10" 
      maxReceivedMessageSize ="2147483647"> 
     <readerQuotas 
     maxDepth="2147483647" 
     maxStringContentLength="2147483647" 
     maxArrayLength="2147483647" 
     maxBytesPerRead="2147483647" 
     maxNameTableCharCount="2147483647" /> 
     <reliableSession ordered="true" inactivityTimeout="00:10:00" anabled="false" /> 
    </binding> 
    </netTcpBinding> 
</bindings> 
<client> 
    <endpoint name="NetTcpBinding_ICreatable" 
     address="net.tcp://localhost:6547/CIService/CIService.svc" 
     binding="netTcpBinding" 
     bindingConfiguration="NetTcpBinding_ICreatable" 
     behaviorConfiguration="CIBehavior.EndpointBehavior" 
     contract="ICreatable" /> 
</client> 
<behaviors> 
    <endpointBehavior> 
    <behavior name="CIBehavior.EndpointBehavior"> 
     <dataContractSerializer maxItemsInObjectGraph="2147483647" /> 
    </behavior> 
    </endpointBehavior> 
</behaviors> 
</system.serviceModel> 
+1

Bạn sẽ phải chia dữ liệu thành các phần nhỏ hơn. – TGlatzer

+0

Chuyển tin nhắn cỡ lớn chắc chắn là có thể. xem http://orand.blogspot.fr/2007/12/wcf-message-size-tester.html này –

Trả lời

35

Bạn không cần MaxBufferSize hoặc maxBufferPoolSize thiết lập quá cao này được thể gây ra lại memory exception . Các giá trị mặc định sẽ ổn.

Check-out Large Data and Streaming trên MSDN, đặc biệt là phần đặc biệt cân nhắc bảo mật cho dữ liệu lớn mảnh này của văn bản là quan trọng

Thuộc tính MaxBufferSize là cần thiết để hạn chế bộ nhớ đệm WCF. Điều quan trọng là đặt giá trị này thành giá trị an toàn (hoặc giữ giá trị an toàn ở mức giá trị mặc định) khi phát trực tuyến. Ví dụ: giả sử dịch vụ của bạn phải nhận các tệp có kích thước tối đa 4 GB và lưu trữ chúng trên đĩa địa phương . Giả sử rằng bộ nhớ của bạn bị hạn chế theo cách như vậy mà bạn chỉ có thể đệm 64 KB dữ liệu cùng một lúc. Sau đó, bạn sẽ đặt MaxReceivedMessageSize thành 4 GB và MaxBufferSize thành 64 KB. Ngoài ra, trong việc triển khai dịch vụ, bạn phải đảm bảo rằng bạn chỉ đọc từ luồng đến trong khối 64 KB và không đọc đoạn tiếp theo trước khi đoạn trước được ghi vào đĩa và loại bỏ khỏi bộ nhớ.

Tôi kết hợp một ví dụ rất đơn giản về truyền dữ liệu từ dịch vụ tự lưu trữ cho máy khách bảng điều khiển. Để giữ bài viết ngắn, tôi chỉ thêm mã máy chủ và một phần của máy khách.

Hợp đồng dịch vụ

using System.IO; 
using System.ServiceModel; 

namespace Service 
{ 
    [ServiceContract] 
    public interface IStream 
    { 
     [OperationContract] 
     Stream GetLargeObject(); 
    } 
} 

Việc thực hiện dịch vụ

using System; 
using System.IO; 
using System.ServiceModel; 

namespace Service 
{ 
    [ServiceBehavior] 
    public class StreamService : IStream 
    { 
     public Stream GetLargeObject() 
     { 
      // Add path to a big file, this one is 2.5 gb 
      string filePath = Path.Combine(Environment.CurrentDirectory, "C:\\Temp\\BFBC2_PC_Client_R11_795745_Patch.exe"); 

     try 
     { 
      FileStream imageFile = File.OpenRead(filePath); 
      return imageFile; 
     } 
     catch (IOException ex) 
     { 
      Console.WriteLine(String.Format("An exception was thrown while trying to open file {0}", filePath)); 
      Console.WriteLine("Exception is: "); 
      Console.WriteLine(ex.ToString()); 
      throw; 
     } 
    } 
} 
} 

Các dịch vụ chính

using System; 
using System.ServiceModel; 

namespace Service 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      try 
      { 
       using (var serviceHost = new ServiceHost(typeof(StreamService))) 
       { 
        serviceHost.Open(); 

        Console.WriteLine("Press Any Key to end"); 
        Console.ReadKey(); 
       } 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex.ToString()); 
      } 
     } 
    } 
} 

Dịch vụ app.config

<?xml version="1.0"?> 
<configuration> 
    <startup> 
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/> 
    </startup> 

    <system.serviceModel> 
    <behaviors> 
     <serviceBehaviors> 
     <behavior name="StreamServiceBehavior"> 
      <serviceMetadata httpGetEnabled="True" /> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <bindings> 
     <netTcpBinding> 
     <binding name="NewBinding0" transferMode="Streamed"/> 
     </netTcpBinding> 
    </bindings> 
    <services> 
     <service behaviorConfiguration="StreamServiceBehavior" name="Service.StreamService"> 
     <endpoint address="net.tcp://localhost:9000/streamserver" binding="netTcpBinding" 
      bindingConfiguration="NewBinding0" bindingName="" contract="Service.IStream" /> 
     <endpoint address="mex" binding="mexHttpBinding" 
      contract="IMetadataExchange" /> 
     <host> 
      <baseAddresses> 
      <add baseAddress="http://localhost:8080/StreamService" /> 
      </baseAddresses> 
     </host> 
     </service> 
    </services> 
    </system.serviceModel> 
</configuration> 

Khởi chạy dịch vụ, có thể cần chạy dưới tài khoản quản trị để mở ổ cắm. Tạo ứng dụng bảng điều khiển máy khách và thêm tham chiếu dịch vụ bằng cách sử dụng url http: // localhost: 8080/StreamService, sử dụng Dịch vụ làm không gian tên cho ứng dụng khách được tạo.

Các khách hàng chính

using System; 
using System.IO; 
using Client.Service; 

namespace Client 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      try 
      { 
       using (StreamClient streamClient = new StreamClient()) 
       { 
        streamClient.Open(); 

        using (FileStream fileStream = new FileStream("c:\\temp\\bigfile.exe",FileMode.Create)) 
        { 
         streamClient.GetLargeObject().CopyTo(fileStream);  
        } 
       } 

       Console.WriteLine("Press any key to end"); 
       Console.ReadKey(); 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex); 
      } 
     } 
    } 
} 

Các tạo ra khách hàng tập tin cấu hình sẽ cần phải được sửa đổi một chút, tăng receiveTimeout và thiết lập maxReceivedMessageSize = "4294967295"

<system.serviceModel> 
    <bindings> 
     <netTcpBinding> 
      <binding name="NetTcpBinding_IStream" closeTimeout="00:01:00" 
       openTimeout="00:01:00" receiveTimeout="00:30:00" sendTimeout="00:01:00" 
       transactionFlow="false" transferMode="Streamed" transactionProtocol="OleTransactions" 
       hostNameComparisonMode="StrongWildcard" listenBacklog="10" 
       maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="10" 
       maxReceivedMessageSize="4294967295"> 
       <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" 
        maxBytesPerRead="4096" maxNameTableCharCount="16384" /> 
       <reliableSession ordered="true" inactivityTimeout="00:10:00" 
        enabled="false" /> 
       <security mode="Transport"> 
        <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" /> 
        <message clientCredentialType="Windows" /> 
       </security> 
      </binding> 
     </netTcpBinding> 
    </bindings> 
    <client> 
     <endpoint address="net.tcp://localhost:9000/streamserver" binding="netTcpBinding" 
      bindingConfiguration="NetTcpBinding_IStream" contract="Service.IStream" 
      name="NetTcpBinding_IStream"> 

     </endpoint> 
    </client> 
</system.serviceModel> 

Launch dịch vụ sau đó khách hàng. Nó sẽ phát một tệp lớn mà không có vấn đề.

Các vấn đề liên quan