2016-03-03 14 views
7

Tôi đang sử dụng CPU nặng khi thực hiện cuộc gọi đến API AXL SOAP của Cisco bằng WCF. Tôi bắt đầu bằng cách tạo một mô hình dịch vụ clientbase bằng cách sử dụng các lớp được tạo ra từ wsdl. Tôi đang sử dụng basichttpbinding và transfermode như đệm. Khi thực hiện một cuộc gọi, CPU maxes ra, và một hồ sơ CPU cho thấy 96% thời gian CPU là [email protected] từ clr.dll được gọi sau khi các cuộc gọi như base.Channel.getPhone(request);. Chính xác hơn, cuộc gọi sẽ làm tối đa lõi CPU mà quá trình đang chạy.WCF tối đa CPU khi đợi chức năng _TransparantProxyStub_CrossContext trong khi gọi

Dưới đây là một ảnh của việc tạo ra khách hàng từ wsdl tạo

[System.Diagnostics.DebuggerStepThroughAttribute()] 
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")] 
public partial class AXLPortClient : System.ServiceModel.ClientBase<AxlNetClient.AXLPort>, AxlNetClient.AXLPort 
{ 

    public AXLPortClient() 
    { 
    } 

    public AXLPortClient(string endpointConfigurationName) : 
      base(endpointConfigurationName) 
    { 
    } 

    ... 

Đây là cách tôi tạo cho khách hàng:

public class AxlClientFactory : IAxlClientFactory 
{ 
    private const string AxlEndpointUrlFormat = "https://{0}:8443/axl/"; 

    public AXLPortClient CreateClient(IUcClientSettings settings) 
    { 
     ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true; 
     ServicePointManager.Expect100Continue = false;      

     var basicHttpBinding = new BasicHttpBinding(BasicHttpSecurityMode.Transport); 
     basicHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic; 

     basicHttpBinding.MaxReceivedMessageSize = 20000000; 
     basicHttpBinding.MaxBufferSize = 20000000; 
     basicHttpBinding.MaxBufferPoolSize = 20000000; 

     basicHttpBinding.ReaderQuotas.MaxDepth = 32; 
     basicHttpBinding.ReaderQuotas.MaxArrayLength = 20000000; 
     basicHttpBinding.ReaderQuotas.MaxStringContentLength = 20000000; 

     basicHttpBinding.TransferMode = TransferMode.Buffered; 
     //basicHttpBinding.UseDefaultWebProxy = false; 

     var axlEndpointUrl = string.Format(AxlEndpointUrlFormat, settings.Server); 
     var endpointAddress = new EndpointAddress(axlEndpointUrl); 
     var axlClient = new AXLPortClient(basicHttpBinding, endpointAddress); 
     axlClient.ClientCredentials.UserName.UserName = settings.User; 
     axlClient.ClientCredentials.UserName.Password = settings.Password; 
     return axlClient; 
    } 
} 

Mã wsdl tạo ra cho các API Axl là rất lớn. Cả hai cuộc gọi ban đầu và tiếp theo đều có vấn đề về CPU, mặc dù các cuộc gọi tiếp theo nhanh hơn. Tôi có thể làm gì khác để gỡ lỗi vấn đề này không? Có cách nào để giảm mức sử dụng CPU cao này không? Thông tin

Cập nhật

hơn Một chút với bounty:

tôi đã tạo ra các lớp C# như sau:

svcutil AXLAPI.wsdl AXLEnums.xsd AXLSoap.xsd /t:code /l:C# /o:Client.cs /n:*,AxlNetClient 

Bạn cần phải tải về wsdl cho api Axl của Cisco từ một hệ thống quản lý cuộc gọi. Tôi đang sử dụng phiên bản 10.5 của API. Tôi tin rằng sự chậm lại lớn có liên quan đến việc xử lý XML. WSDL cho api là rất lớn với các lớp kết quả tạo ra một dòng mã 538406!

Cập nhật 2

Tôi đã bật WCF truy tìm với tất cả các cấp. Sự khác biệt lớn nhất về thời gian là trong hoạt động của quá trình hành động giữa "Một tin nhắn được viết" và "Đã gửi một tin nhắn qua một kênh" trong đó gần một phút trôi qua giữa hai hành động này. Các hoạt động khác (xây dựng kênh, cơ sở khách hàng mở và cơ sở khách hàng gần) tất cả hoạt động tương đối nhanh.

Cập nhật 3

Tôi đã thực hiện hai thay đổi đối với lớp khách hàng tạo ra. Trước tiên, tôi đã xóa ServiceKnownTypeAttribute khỏi tất cả các hợp đồng hoạt động. Thứ hai, tôi đã loại bỏ XmlIncludeAtribute khỏi một số lớp có thể tuần tự hóa được. Hai thay đổi này đã giảm kích thước tệp của ứng dụng khách được tạo ra nhiều hơn 50% và có tác động nhỏ đến thời gian kiểm tra (giảm khoảng 10 lần trên kết quả kiểm tra 70).

Tôi cũng nhận thấy rằng tôi có gần 900 hợp đồng hoạt động cho một giao diện dịch vụ và điểm cuối duy nhất. Điều này là do wsdl cho API AXL nhóm tất cả các hoạt động theo một không gian tên duy nhất. Tôi đang suy nghĩ về việc phá vỡ điều này, nhưng điều đó có nghĩa là tạo ra nhiều clientbases mà mỗi người sẽ thực hiện một giao diện giảm và cuối cùng phá vỡ tất cả mọi thứ mà thực hiện thư viện wcf này.

Cập nhật 4

Dường như số hoạt động là vấn đề trung tâm. Tôi đã có thể tách các hoạt động và định nghĩa giao diện bằng động từ (ví dụ:được, bổ sung, vv) vào cơ sở khách hàng và giao diện riêng của họ (một quá trình rất chậm sử dụng văn bản tuyệt vời và regex như resharper và codemaid không thể xử lý các tập tin lớn vẫn còn 250K + dòng). Một thử nghiệm của khách hàng "Get" với khoảng 150 hoạt động được định nghĩa dẫn đến việc thực hiện 10 giây cho getPhone so với kết quả 60 giây trước đó. Điều này vẫn còn chậm hơn rất nhiều so với việc chỉ đơn giản là tạo ra thao tác này trong các kết quả không thực hiện trong một lần thực hiện 2 giây. Giải pháp có thể sẽ giảm số lượng hoạt động nhiều hơn bằng cách cố gắng tách riêng các hoạt động. Tuy nhiên, điều này cho biết thêm một vấn đề mới của vi phạm tất cả các hệ thống sử dụng thư viện này như là một khách hàng duy nhất.

+0

Vì đó không phải là một câu trả lời kết luận, tôi sẽ chia sẻ một trải nghiệm tương tự. Tôi đã tạo ra một wcf với nhiều hoạt động ans wsdl lớn. Tôi đã có một vấn đề tương tự với việc sử dụng CPU cao. Tôi đã giải quyết vấn đề, thiết lập lắp ráp cho serialization trên dự án wcf. Trong thuộc tính dự án, xây dựng phần, bạn có thể thử thiết lập "Tạo nối tiếp nối tiếp" thành "Bật" và cũng đặt "Tài liệu Xml" vào thư mục "bin \ release" hoặc "bin \ debug" tùy thuộc vào cách bạn xây dựng giải pháp của bạn. Hãy cho tôi biết nếu làm việc để tôi có thể viết câu trả lời và đăng thêm thông tin về giải pháp này. –

+0

Tôi không nhận được hiệu suất tăng từ việc thiết lập hai tùy chọn này. Tôi đã chạy thử nghiệm đơn vị trong cấu hình phát hành với serialization thiết lập để tự động mà theo này (https://stackoverflow.com/questions/9187248/when-to-change-the-generate-serialization-assembly-value) có nghĩa là serialization là trên rồi. Tài liệu Xml là để dịch nhận xét thành afik intellisence, nhưng tôi đã thử anyway. –

Trả lời

1

Cuối cùng tôi đã giải quyết vấn đề này. Nguyên nhân gốc có vẻ là số lượng hoạt động. Sau khi chia nhỏ khách hàng được tạo ra từ 900+ hoạt động thành 12 mỗi (theo hướng dẫn từ this question), tôi đã có thể giảm thời gian xử lý cho các yêu cầu tạo ra gần như bằng không.

Đây là quá trình chính thức để tối ưu hóa cho khách hàng dịch vụ được tạo ra từ Axl wsdl của Cisco:

Tạo mã khách hàng sử dụng wsdl như vậy:

svcutil AXLAPI.wsdl AXLEnums.xsd AXLSoap.xsd /t:code /l:C# /o:Client.cs /n:*,AxlNetClient 

Process file client tạo ra để chia tay thành các khách hàng phụ:

Tôi đã tạo this script để xử lý mã được tạo. Kịch bản này thực hiện như sau:

  1. Di ServiceKnownType, FaultContract, và XmlInclude thuộc tính.

Chúng rất hữu ích cho việc xử lý xml, nhưng các lớp được tạo ra dường như không chính xác với những gì tôi hiểu. Serviceknowntype chẳng hạn, giống hệt nhau cho tất cả các hoạt động mặc dù nhiều người trong số các knowntypes là duy nhất cho mỗi operaiton. Điều này làm giảm tổng kích thước của tệp được tạo từ 500K + dòng thành 250K + với sự gia tăng hiệu suất nhỏ trong thời gian diễn giải của ứng dụng khách.

  1. Tách riêng các hợp đồng hoạt động tạo thành giao diện và phương thức từ cơ sở khách hàng thực hiện giao diện.

  2. Tạo từng khách hàng với 12 hoạt động và triển khai tương ứng của chúng.

Những khách hàng này có ba phần chính. Phần đầu tiên là một phần của lớp client client gốc. Tôi muốn giải pháp này được tương thích ngược vì vậy tôi đã có phương pháp ở đây mà tham khảo subclient để các cuộc gọi đến các siêu khách hàng cũ vẫn làm việc bằng cách gọi subclient mới. Một accessor tĩnh sẽ khởi tạo subclient nếu bất kỳ hoạt động nào được thực thi được tham chiếu. Ngoài ra còn có các sự kiện được thêm vào khi được đóng hoặc hủy bỏ được gọi để các subclients vẫn có thể chạy các hoạt động này.

Phần thứ hai và thứ ba của lớp con là giao diện và lớp con thực hiện 12 thao tác.

Sau đó tôi đã xóa giao diện và phương thức khách hàng khỏi ứng dụng khách được tạo ban đầu. Tôi đã thay thế các trình xây dựng máy khách cho máy khách gốc để lưu trữ dữ liệu ràng buộc và điểm cuối cho các trình khách để sử dụng khi cần thiết. Đóng và hủy bỏ các cuộc gọi được tái tạo như là người hút sự kiện mà mỗi subclient sẽ đăng ký khi instantiated.

Cuối cùng, tôi đã di chuyển xác thực đến hành vi điểm cuối tùy chỉnh tương tự như những gì described here. Sử dụng IClientMessageInspector để gửi tiêu đề xác thực ngay lập tức lưu trong một cuộc gọi chuyến đi vòng tới máy chủ nơi WCF thích gửi yêu cầu ẩn danh trước khi xác thực. Điều này cho tôi tăng khoảng 2 giây tùy thuộc vào máy chủ.

Nhìn chung, tôi có hiệu suất tăng từ 70 đến 2,5 giây.

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