2012-06-27 50 views
9

Tôi đang làm việc trên một thử nghiệm hiệu suất trong đó bao gồm một số khách hàng bắn phá máy chủ với 150 yêu cầu mỗi, nhanh nhất có thể.Tại sao ứng dụng của tôi đợi đồng bộ hóa quá nhiều?

Máy chủ được xây dựng từ 3 dịch vụ WCF, một máy chủ được mở ra bên ngoài với httpbinding, nó nói chuyện với 2 dịch vụ khác thông qua net.pipe (IPC). một trong những dịch vụ chịu trách nhiệm về các kết nối DB (SQL server 2008 R2).

dịch vụ kết nối

DB này sử dụng những nâng cao chuỗi kết nối sau:

Min Pool Size=20; Max Pool Size=1000; Connection Timeout=20; 

và là WCF Throttled (giống như tất cả các dịch vụ WCF khác).

Tôi nhận thấy rằng khi tôi kích hoạt 1 ứng dụng, có thể mất 3 giây, nhưng khi tôi kích hoạt 3 khách hàng, nó có thể mất 8-9 hoặc hơn.

Tôi đã kiểm tra với trình lược tả máy chủ SQL để xem có bao nhiêu tiến trình đồng thời được sử dụng và tôi thấy rằng chỉ có khoảng 8 quy trình đang được sử dụng.

Vì vậy, tôi nhận ra rằng ở đâu đó trong máy chủ, các yêu cầu được xếp hàng đợi thay vì đồng thời được xử lý.

Để có được để dưới cùng của nó, tôi đã sử dụng một hồ sơ hoạt động (ANts để được chính xác) mà chỉ cho tôi rằng khoảng 70% thời gian bị lãng phí trên "Chờ đợi để đồng bộ hóa

Khi tôi mở đồ thị gọi tôi thấy hai điều mà trông lạ nhưng tôi không chắc chắn những gì họ có nghĩa là:

  1. System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke đang được sử dụng ở phía trên cùng của cây, là ok mà để xử lý đồng thời?
  2. Tất cả sự cố đồng bộ hóa liên quan đến một số loại hoạt động của SQL Server, như ExecuteNonQuery, ExecuteReader và như vậy (Khi tôi đến cuối cây gọi)

Tôi nhận thấy rằng dịch vụ kết nối DB sử dụng dự án DAL (một số mã cũ, thật không may)) hoàn toàn tĩnh.

Sau khi đọc this Tôi không chắc chắn nếu mã của DAL có vấn đề hay không, dưới đây là ví dụ về cuộc gọi thủ tục được lưu trữ.

public static int PerformStoredProcedure(string storedP,string ext,out string msg) 
    { 
     msg = ""; 
     SqlCommand command = GetSqlCommand(storedP,ext); 
     command.Connection.Open(); 
     int result = (int)PerformStoredProcedure(command,out msg); 
     command.Connection.Close(); 
     return result; 
    } 

Phương pháp này được gọi là thường là từ các dịch vụ kết nối DB:

public static int PerformStoredProcedureWithParams(string storedP,string ext,out string msg, params object[] pars) 
    { 
     msg = ""; 
     SqlCommand command = GetSqlCommand(storedP,ext); 
     UpdateCommandParams(command, pars); 
     command.Connection.Open(); 
     int result = (int)PerformStoredProcedure(command,out msg); 
     command.Connection.Close(); 
     return result; 
    } 

Vì vậy, có gì sai ở đây?

Hoặc có lẽ tôi nên tìm một nơi khác?

Edit:

Sau khi bình luận Brijesh của tôi nhận ra tôi đã không thay đổi InstanceContextMode mặc định và ConcurrencyMode của các dịch vụ WCF ... Loại sai lầm mới bắt đầu tôi đoán.

Tôi vẫn không chắc chắn liệu mình có nên sử dụng PerSession/Multiple hoặc PerCall/Single hay không. Như tôi thấy, mỗi dịch vụ sẽ xử lý từng yêu cầu như đối tượng, bất kể khách hàng.

Tôi nên sử dụng thông tin gì?

2 EDIT:

Sau khi sử dụng PerCall và PerSession/Nhiều, tôi nhận thấy rằng vẫn không có thay đổi (ít nhất là trong dịch vụ DB). những gì tôi thấy là dịch vụ điểm vào chính có thể mở ra rất nhiều chủ đề, nhưng chỉ một vài (vẫn còn khoảng 8-10 chủ đề) được mở tại dịch vụ kết nối DB.

có bất kỳ lý do nào khác khiến điều này có thể xảy ra không? Tôi loại trừ khả năng Dal là một vấn đề vì không đủ yêu cầu đi trong dịch vụ DB vì vậy tôi tìm một cái gì đó của mình trong dịch vụ hoặc một cái gì đó trong các khách hàng ...

EDIT 3:

Dưới đây là các tập tin cấu hình :

phần dịch vụ WCF cấu hình của người quản lý: khách hàng

<services> 
    <service behaviorConfiguration="ServicesBehavior" name="Verifone.GenericPP.GPPManagerService.GPPManagerServiceImpl"> 
    <host> 
     <baseAddresses> 
     <add baseAddress="http://localhost:9090/GPPManagerService/"/> 
     </baseAddresses> 
    </host> 
    <endpoint contract="Verifone.GenericPP.GPPManagerService.IGPPManagerService" binding="basicHttpBinding" address="GPPManagerService"></endpoint> 
    </service> 
</services> 
<behaviors> 
    <serviceBehaviors> 
    <behavior name="ServicesBehavior"> 
     <!--amith 13-05-2012--> 
     <serviceThrottling 
     maxConcurrentCalls="1000" 
     maxConcurrentSessions="1000" 
     maxConcurrentInstances="1000" 
     /> 
     <serviceMetadata httpGetEnabled="true" /> 
     <serviceDebug includeExceptionDetailInFaults="true" /> 
    </behavior> 
    </serviceBehaviors> 
</behaviors> 
<bindings> 
    <basicHttpBinding> 
    <binding name="basicHttpBinding" maxBufferSize="10000000" maxReceivedMessageSize="10000000"> 
     <readerQuotas maxStringContentLength="10000000" maxArrayLength="10000000"/> 
     <security mode="None"> 
     <transport clientCredentialType="None"/> 
     </security> 
    </binding> 

Manager:

 <endpoint name="endpoint1" contract="IDBConnectionContract" bindingConfiguration="basicHttpBinding" binding="basicHttpBinding" address="http://localhost:9010/DBConnectionService/DBService"></endpoint> 
    <endpoint name="endpoint2" contract="IGPPService" bindingConfiguration="basicHttpBinding" binding="basicHttpBinding" address="http://localhost:9095/GenericPPService/GenericPPService"></endpoint> 

Dịch vụ kết nối DB:

<service behaviorConfiguration="ServicesBehavior" name="Verifone.DBConnectionService.DBConnectionContracImpl"> 
    <host> 
     <baseAddresses> 
     <add baseAddress="http://localhost:9010/DBConnectionService/"/> 
     <add baseAddress="net.pipe://localhost/DBConnectionService/"/> 
     </baseAddresses> 
    </host> 
    <endpoint contract="Verifone.DBConnectionService.IDBConnectionContract" binding="basicHttpBinding" address="DBService"></endpoint> 

    <endpoint contract="Verifone.DBConnectionService.IDBConnectionContract" binding="netNamedPipeBinding" bindingConfiguration="NetNamedPipeBinding_Configuration" address="" name="pipeEndpoint"/> 
    </service> 

client Logic dịch vụ của doanh nghiệp là khá nhiều giống như người quản lý của.

Tất cả các dịch vụ đều tự tổ chức và tôi có một lớp DBConnectionProxy tại của người quản lý và mã kinh doanh mà họ kích hoạt như thế này:

DBConnectionContractClient _dbConnectionContractClient = null; 
     try 
     { 
      objDBConnectionContractClient = new DBConnectionContractClient(); 
      objDBConnectionContractClient.ExecuteStoredProcedure(input, out result); 
     } 
+0

bạn đang sử dụng loại chế độ ví dụ và chế độ đồng nhất nào? –

+0

Có vẻ như tôi không đặt chế độ nào, vì vậy cài đặt mặc định được áp dụng ... Tôi nhớ tôi muốn thêm mỗi phiên/nhiều, nhưng có thể đã bỏ lỡ nó bằng cách nào đó, tôi có nên thêm nó không? – Mithir

+4

persession/single là mặc định, hãy thử với chế độ concurency nhiều –

Trả lời

4

PerCall Bạn có thể xem xét chế độ instancing này trong những trường hợp này.

  • Nếu dịch vụ của bạn là quốc tịch

  • Nếu dịch vụ của bạn có mã khởi tạo trọng lượng nhẹ (hoặc không có gì
    tất cả).

  • Nếu dịch vụ của bạn là một luồng đơn.

Một số hướng dẫn hay. Xem liên kết thứ ba trên điều chỉnh.

WCF Instancing, Concurrency, and Throttling – Part 1

WCF Instancing, Concurrency, and Throttling – Part 2

WCF Instancing, Concurrency, and Throttling – Part 3

+0

Cảm ơn bạn đã đề xuất, tôi đã thử cả hai nhưng vẫn yêu cầu được xếp hàng đợi trong khi gửi đến dịch vụ db – Mithir

+0

Chỉ cần một cách tiếp cận có thể xem xét cách bạn đang kích hoạt các khách hàng để kiểm tra. Bạn có thể lấy khóa độc quyền trên cùng một bàn không? – Paparazzi

+0

Sự cố không xảy ra trên DB thực tế nhưng trên một dịch vụ kích hoạt db. Các yêu cầu được xếp hàng đợi trước khi vào dịch vụ đó, trước khi các bảng thậm chí còn là một vấn đề. – Mithir

2

có thích mỗi cuộc gọi. Phiên sẽ hữu ích nếu bạn muốn giảm thiểu việc khởi tạo các đối tượng chuyên sâu tài nguyên hoặc chạy một số định tuyến tiền xử lý cho mỗi yêu cầu hoặc muốn duy trì trạng thái. Phiên có thể cung cấp cho bạn hiệu suất tốt hơn nhưng mỗi cuộc gọi luôn có quy mô tốt hơn. Trong mỗi cuộc gọi, bạn không phải lo lắng về tính đồng thời. Trong khi đó bất lợi với suy thoái/nhiều là bạn phải luôn luôn suy nghĩ về an toàn luồng trong mã của bạn.

+0

Tôi thực sự không biết vấn đề là gì ... Tôi đặt nó thành PerCall hoặc PerSession nhiều trên tất cả các dịch vụ nhưng nó vẫn không quan trọng, Dịch vụ wcf chính của http sẽ mở ra rất nhiều chủ đề, nhưng chỉ một vài Dịch vụ kết nối DB ... – Mithir

+0

có phải là vấn đề với yêu cầu đồng thời hay làm chậm doen bằng cách mở nhiều phiên bản? –

+0

Tôi đã thêm một số tệp cấu hình của các dịch vụ WCF, hy vọng nó giúp một chút – Mithir

1

tùy chọn xuất sắc nhất sẽ được cho mỗi cuộc gọi nếu bạn không quan tâm về tình trạng dịch vụ và nếu không nâng nặng được thực hiện trên khởi, tôi cho rằng mô tả trường hợp của bạn . Hãy thử và loại bỏ các cuộc gọi DAL và xem cách dịch vụ của bạn hoạt động, bằng cách này bạn sẽ có thể xác định xem đó có phải là cổ chai của bạn hay không.

+0

Điều này thực sự được kết nối với câu hỏi khác mà bạn đang trợ giúp, cảm ơn! :) – Mithir

+0

Tôi đã thêm một số tệp cấu hình trong câu hỏi. hệ điều hành là Windows Server 2008. – Mithir

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