WCF - Cách tăng hạn ngạch kích thước thư


454

Tôi có Dịch vụ WCF trả về 1000 bản ghi từ cơ sở dữ liệu cho khách hàng. Tôi có một máy khách ASP.NET WCF (Tôi đã thêm tham chiếu dịch vụ trong dự án ứng dụng web asp.net để sử dụng WCF).

Tôi nhận được thông báo sau khi chạy ứng dụng khách:

Hạn mức kích thước thư tối đa cho các tin nhắn đến (65536) đã bị vượt quá. Để tăng hạn ngạch, hãy sử dụng thuộc tính MaxReceuredMessageSize trên phần tử ràng buộc thích hợp.

Có ai giúp đỡ không? Làm thế nào để tăng hạn ngạch kích thước tin nhắn?


Tôi gặp vấn đề tương tự nhưng tôi chỉ gặp phải lỗi mạng không thân thiện 400 nhưng giải pháp là kích thước tin nhắn ..
Mr W

2
Tôi đã giải quyết vấn đề bằng cách sử dụng các bước được đề cập trong [liên kết] [1] [1]: stackoverflow.com/questions/7476853/ Kẻ
Ram

Tại sao nó được đặt quá thấp theo mặc định? Bảo vệ?
Coops

@Coops cho bảo mật thực sự. Bằng cách đặt hạn ngạch trên các thông báo, ví dụ các cuộc tấn công DDOS khó thực hiện hơn (ít nhất một chút).
Peter van Kekem

Câu trả lời:


608

Bạn sẽ muốn một cái gì đó như thế này để tăng hạn ngạch kích thước thư, trong tệp App.config hoặc Web.config :

<bindings>
    <basicHttpBinding>
        <binding name="basicHttp" allowCookies="true"
                 maxReceivedMessageSize="20000000" 
                 maxBufferSize="20000000"
                 maxBufferPoolSize="20000000">
            <readerQuotas maxDepth="32" 
                 maxArrayLength="200000000"
                 maxStringContentLength="200000000"/>
        </binding>
    </basicHttpBinding>
</bindings>

Và sử dụng tên ràng buộc trong cấu hình điểm cuối của bạn, vd

...
bindingConfiguration="basicHttp"
...

Sự biện minh cho các giá trị rất đơn giản, chúng đủ lớn để chứa hầu hết các tin nhắn. Bạn có thể điều chỉnh số đó để phù hợp với nhu cầu của bạn. Giá trị mặc định thấp về cơ bản là có để ngăn chặn các cuộc tấn công kiểu DOS. Làm cho nó 20000000 sẽ cho phép một cuộc tấn công DOS phân tán có hiệu quả, kích thước mặc định 64k sẽ yêu cầu một số lượng lớn máy khách để chế ngự hầu hết các máy chủ hiện nay.


20
Cảm ơn..Thay đổi này cần được thực hiện trong tệp web.config của ứng dụng khách.
bugBurger

8
Bạn cũng có thể cần thay đổi nó trên máy chủ - trong trường hợp bạn cần gửi một tập dữ liệu lớn dưới dạng tham số cho Phương thức WCF.
Nate

9
Nó có hiệu quả lớn để chứa hầu hết các tin nhắn. Bạn có thể điều chỉnh số đó để phù hợp với nhu cầu của bạn. Về cơ bản nó là để ngăn chặn các cuộc tấn công kiểu DOS. Làm cho nó 20000000 sẽ cho phép một cuộc tấn công DOS phân tán có hiệu quả, kích thước mặc định là 64k sẽ yêu cầu một số lượng lớn máy khách để chế ngự hầu hết các máy chủ trong những ngày này
Nate

18
Đối với những người khác quan tâm, tôi đọc trên một blog khác rằng kích thước tối đa là 2147483647. 20000000 nhỏ hơn một chút so với con số này, vì vậy sử dụng số nhỏ nhất bạn có thể thoát khỏi mà không làm gián đoạn dịch vụ.
kiêu hãnh

5
@Slauma Sẽ cần phải thay đổi trên máy chủ nếu tham số đến đó quá lớn; mặt khác (và nhiều khả năng) thay đổi cần phải được thực hiện trong tệp cấu hình máy khách, vì đó là phản hồi của dịch vụ (không phải tham số của nó) quá lớn.
Nate

155

Nếu bạn vẫn nhận được thông báo lỗi này trong khi sử dụng Máy khách thử nghiệm WCF, thì đó là do máy khách có cài đặt MaxBufferSize riêng .

Để khắc phục sự cố:

  1. Nhấp chuột phải vào nút Cấu hình tệp ở dưới cùng của cây
  2. Chọn Chỉnh sửa với SvcConfigEditor

Một danh sách các cài đặt có thể chỉnh sửa sẽ xuất hiện, bao gồm MaxBufferSize.

Lưu ý: Các máy khách proxy được tạo tự động cũng đặt MaxBufferSize thành 65536 theo mặc định.


8
Tại sao oh tại sao tôi luôn quên về điều này? +1
James Skemp

9
Trên vs2013 SvcConfigEditor được thay thế bằng cấu hình Chỉnh sửa WCF nếu mọi người đang tìm kiếm nó.
ZoomVirus

Không thể tìm thấy SVCconfigEditor?
Arul Sidthan

Bạn sẽ tìm thấy nó trong thư mục Bindings, nhấp vào ràng buộc cho dịch vụ và nó ở đó.
Sameer Alibhai

Nếu tập tin cấu hình của bạn được tạo tự động, bạn hoàn toàn nên làm theo cách này. Bất cứ khi nào bạn cập nhật tài liệu tham khảo của mình, nó sẽ lấy lại app.config và bạn sẽ phải thay đổi lại theo cách thủ công. Nếu bạn thay đổi VS mặc dù, những thay đổi mới sẽ phù hợp với các cài đặt bạn đã chọn.
kingfrito_5005

104

Nếu bạn đang tạo các ràng buộc WCF của mình một cách linh hoạt thì đây là mã để sử dụng:

BasicHttpBinding httpBinding = new BasicHttpBinding();
httpBinding.MaxReceivedMessageSize = Int32.MaxValue;
httpBinding.MaxBufferSize = Int32.MaxValue;
// Commented next statement since it is not required
// httpBinding.MaxBufferPoolSize = Int32.MaxValue;

Bạn có thể sử dụng nó khởi tạo. Rõ ràng bạn có thể sử dụng nó phương thức xây dựng của bạn.
aemre

45

Các khách hàng WCF thử nghiệm có cấu hình của nó khách hàng riêng.

Chạy thử nghiệm máy khách và cuộn xuống phía dưới. Nếu bạn nhấp đúp vào nút Cấu hình tệp, bạn sẽ thấy biểu diễn XML. Như bạn có thể thấy maxReceivedMessageSize65536.

Để chỉnh sửa điều này, Nhấp chuột phải vào nút Cây cấu hình tệp và chọn Chỉnh sửa với SvcConfigEditor. Khi trình chỉnh sửa mở ra Bindings mở rộng và nhấp đúp vào liên kết được tạo tự động.

Bạn có thể chỉnh sửa tất cả các thuộc tính ở đây, bao gồm maxReceivedMessageSize. Khi bạn hoàn tất, nhấp vào Tệp - Lưu .

Cuối cùng, khi bạn quay lại cửa sổ WCF Test Client, bấm Công cụ - Tùy chọn .

LƯU Ý : Bỏ chọn cấu hình Luôn tái tạo khi khởi chạy dịch vụ .


2
Có lẽ câu trả lời tốt nhất ở đây!
Haris

3
upvote vì ghi chú để bỏ Always regenerate configchọn tùy chọn.
Furier

Giải quyết đơn giản nhất theo ý kiến ​​của tôi. Cứu tôi đau đầu.
Bãi biển Jared

Trên vs2013 SvcConfigEditor được thay thế bằng cấu hình Chỉnh sửa WCF nếu mọi người đang tìm kiếm nó.
ZoomVirus

Cảm ơn bạn. Đã phá vỡ đầu tôi một lúc, thay đổi cấu hình máy chủ nhiều lần, khi sự cố xảy ra với cấu hình Máy khách Kiểm tra!
Fahad

24

Tôi tìm thấy cách dễ dàng

--- nhấp chuột phải vào tệp cấu hình webconfig hoặc ứng dụng và nhấp vào EDIT WCF CONFIGURATION và nhận được bingdigs ans chọn dịch vụ yore và bên phải hiển thị maxReciveMessageSize cho một số lượng lớn ---


2
Đó là một câu trả lời tuyệt vời, tôi không biết rằng tôi có thể chỉnh sửa từ đây, Cảm ơn
albert sh

8

Tôi giải quyết vấn đề ... như sau

    <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>

20
Điều này khác với giải pháp của tôi như thế nào? Khác với bạn bao gồm tất cả các phần không liên quan trong cấu hình của bạn cũng như các phần có liên quan và bạn đã chọn giá trị tối đa có thể thay vì 200m tôi đã chọn?
Nate

3
Bối cảnh cũng tốt ... có lẽ hai câu trả lời này có thể được hợp nhất?
Jeff

1
cài đặt đó có được cấu hình trong máy chủ hoặc máy khách không?
John Kenedy

8

Tôi đã giải quyết vấn đề của mình trên Bing Maps WPF trong dự án của mình bằng tính toán tính toán (). Giải pháp trong trường hợp của tôi là cài đặt maxReceuredMessageSize và maxReceuredMessageSize trên thuộc tính "httpTransport" cho phần "customBinding".

Tôi đặt trong tệp apps.config (es. MyApp.config) cấu hình này:

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="BasicHttpBinding_IGeocodeService" />
            <binding name="BasicHttpBinding_IRouteService" />
        </basicHttpBinding>
        <customBinding>
            <binding name="CustomBinding_IGeocodeService">
                <binaryMessageEncoding />
              <httpTransport manualAddressing="false" maxBufferPoolSize="524288"
                                maxReceivedMessageSize="2147483647" allowCookies="false" authenticationScheme="Anonymous"
                                bypassProxyOnLocal="false" decompressionEnabled="true" hostNameComparisonMode="StrongWildcard"
                                keepAliveEnabled="true" maxBufferSize="2147483647" proxyAuthenticationScheme="Anonymous"
                                realm="" transferMode="Buffered" unsafeConnectionNtlmAuthentication="false"
                                useDefaultWebProxy="true" />
            </binding>
            <binding name="CustomBinding_IRouteService">
                <binaryMessageEncoding />
              <httpTransport manualAddressing="false" maxBufferPoolSize="524288"
                                maxReceivedMessageSize="2147483647" allowCookies="false" authenticationScheme="Anonymous"
                                bypassProxyOnLocal="false" decompressionEnabled="true" hostNameComparisonMode="StrongWildcard"
                                keepAliveEnabled="true" maxBufferSize="2147483647" proxyAuthenticationScheme="Anonymous"
                                realm="" transferMode="Buffered" unsafeConnectionNtlmAuthentication="false"
                                useDefaultWebProxy="true" />
            </binding>
        </customBinding>
    </bindings>
    <client>
        <endpoint address="http://dev.virtualearth.net/webservices/v1/geocodeservice/GeocodeService.svc"
            binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IGeocodeService"
            contract="BingServices.IGeocodeService" name="BasicHttpBinding_IGeocodeService" />
        <endpoint address="http://dev.virtualearth.net/webservices/v1/geocodeservice/GeocodeService.svc/binaryHttp"
            binding="customBinding" bindingConfiguration="CustomBinding_IGeocodeService"
            contract="BingServices.IGeocodeService" name="CustomBinding_IGeocodeService" />
        <endpoint address="http://dev.virtualearth.net/webservices/v1/routeservice/routeservice.svc"
            binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IRouteService"
            contract="BingServices.IRouteService" name="BasicHttpBinding_IRouteService" />
        <endpoint address="http://dev.virtualearth.net/webservices/v1/routeservice/routeservice.svc/binaryHttp"
            binding="customBinding" bindingConfiguration="CustomBinding_IRouteService"
            contract="BingServices.IRouteService" name="CustomBinding_IRouteService" />
    </client>
</system.serviceModel>

6

<bindings>
  <wsHttpBinding>
    <binding name="wsHttpBinding_Username" maxReceivedMessageSize="20000000"          maxBufferPoolSize="20000000">
      <security mode="TransportWithMessageCredential">
        <message clientCredentialType="UserName" establishSecurityContext="false"/>
      </security>
    </binding>
  </wsHttpBinding>
</bindings>

<client>
  <endpoint
            binding="wsHttpBinding"
            bindingConfiguration="wsHttpBinding_Username"
            contract="Exchange.Exweb.ExchangeServices.ExchangeServicesGenericProxy.ExchangeServicesType"
            name="ServicesFacadeEndpoint" />
</client>


Tuyệt vời cho việc đăng câu trả lời của bạn. Điều quan trọng là giá trị "bindConfiguration" khớp với tên ràng buộc. Trong ví dụ của bạn "wsHttpBinding_Username".
Bruno Bieri

6

Đối với HTTP:

<bindings>
  <basicHttpBinding>
    <binding name="basicHttp" allowCookies="true"
             maxReceivedMessageSize="20000000" 
             maxBufferSize="20000000"
             maxBufferPoolSize="20000000">
        <readerQuotas maxDepth="200" 
             maxArrayLength="200000000"
             maxBytesPerRead="4096"
             maxStringContentLength="200000000"
             maxNameTableCharCount="16384"/>
    </binding>
  </basicHttpBinding>
</bindings>

Đối với TCP:

<bindings>
  <netTcpBinding>
    <binding name="tcpBinding"
             maxReceivedMessageSize="20000000"
             maxBufferSize="20000000"
             maxBufferPoolSize="20000000">
      <readerQuotas maxDepth="200"
           maxArrayLength="200000000"
           maxStringContentLength="200000000"
           maxBytesPerRead="4096"
           maxNameTableCharCount="16384"/>
    </binding>
  </netTcpBinding>
</bindings>

QUAN TRỌNG:

Nếu bạn cố gắng vượt qua đối tượng phức tạp có nhiều đối tượng được kết nối (ví dụ: cấu trúc dữ liệu cây, danh sách có nhiều đối tượng ...), giao tiếp sẽ thất bại cho dù bạn có tăng Quotas như thế nào. Trong các trường hợp như vậy, bạn phải tăng số lượng đối tượng chứa:

<behaviors>
  <serviceBehaviors>
    <behavior name="NewBehavior">
      ...
      <dataContractSerializer maxItemsInObjectGraph="2147483646"/>
    </behavior>
  </serviceBehaviors>
</behaviors>

Đó maxItemsInObjectGraphlà giải pháp (nhanh chóng) cho tôi. Nhưng khi tăng điều này, bạn nên suy nghĩ xem liệu giải pháp tốt hơn cho ứng dụng của bạn có yêu cầu dữ liệu theo từng khối hay không, trái ngược với biểu đồ đối tượng khổng lồ có thể làm căng tài nguyên.
Paul

6

Đối với tôi, tất cả những gì tôi phải làm là thêm maxReceivedMessageSize="2147483647"vào ứng dụng khách.config. Các máy chủ bị bỏ hoang.


5

Một điều quan trọng khác để xem xét từ kinh nghiệm của tôi ..

Tôi đặc biệt khuyên KHÔNG nên tối đa hóa maxBufferPoolSize, vì bộ đệm từ nhóm không bao giờ được phát hành cho đến khi miền ứng dụng (tức là Nhóm ứng dụng) tái chế.

Một khoảng thời gian lưu lượng truy cập cao có thể khiến rất nhiều bộ nhớ được sử dụng và không bao giờ được phát hành.

Thêm chi tiết tại đây:


3

Đừng quên rằng app.config của điểm nhập thực thi sẽ được xem xét, không phải là một trong dự án thư viện lớp quản lý các cuộc gọi Dịch vụ Web nếu có.

Ví dụ: nếu bạn gặp lỗi trong khi chạy thử nghiệm đơn vị, bạn cần thiết lập cấu hình phù hợp trong dự án thử nghiệm.


0

tôi đã gặp lỗi này khi sử dụng cài đặt này trên web.config

System.ServiceModel.ServiceActivationException

tôi đặt các cài đặt như thế này:

      <service name="idst.Controllers.wcf.Service_Talks">
    <endpoint address="" behaviorConfiguration="idst.Controllers.wcf.Service_TalksAspNetAjaxBehavior"
      binding="webHttpBinding" contract="idst.Controllers.wcf.Service_Talks" />
  </service>
  <service name="idst.Controllers.wcf.Service_Project">
    <endpoint address="" behaviorConfiguration="idst.Controllers.wcf.Service_ProjectAspNetAjaxBehavior"
      binding="basicHttpBinding" bindingConfiguration="" bindingName="largBasicHttp"
      contract="idst.Controllers.wcf.Service_Project" />
  </service>
</services>

<bindings>
<basicHttpBinding>
    <binding name="largBasicHttp" allowCookies="true"
             maxReceivedMessageSize="20000000"
             maxBufferSize="20000000"
             maxBufferPoolSize="20000000">
        <readerQuotas maxDepth="32"
             maxArrayLength="200000000"
             maxStringContentLength="200000000"/>
    </binding>
</basicHttpBinding>


4
Vì vậy, bạn đã khắc phục vấn đề của mình bằng cách sử dụng câu trả lời của Nate và sau đó đăng nó thành của bạn. Không mát mẻ.
Arcain

@arcain Câu trả lời của Nates rất chung chung, sử dụng tên chứng khoán và số có thể được dự kiến ​​sẽ xuất hiện thường xuyên. Câu trả lời này không bị đánh cắp, nó chỉ đơn giản là câu trả lời đúng. Vì chỉ có một câu trả lời đúng, nó nhất định phải được lặp lại.
kingfrito_5005

@ kingfrito_5005 Câu trả lời "đúng" đã có ở đây khi người trả lời đăng bài này. Anh ấy rõ ràng đã nâng bindingsyếu tố của Nate và đăng lại nó như một phần câu trả lời của anh ấy. Những 2000000giá trị này khá khác biệt.
Arcain 24/07/2015

@arcain, tôi không đồng ý đó là những giá trị rất chuẩn, công ty tôi cũng sử dụng chúng trong các yếu tố ràng buộc của chúng tôi.
kingfrito_5005 24/07/2015
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.