2008-11-24 34 views
30

Tôi có một Dịch vụ WCF không nên vào trạng thái bị lỗi. Nếu có một ngoại lệ, nó phải được ghi lại và dịch vụ sẽ tiếp tục không bị gián đoạn. Dịch vụ này có hợp đồng hoạt động một chiều và đang đọc tin nhắn từ MSMQ.Làm cách nào để ngăn dịch vụ WCF xâm nhập vào trạng thái bị lỗi?

vấn đề của tôi là gồm hai phần:

  1. Dịch vụ này dường như nuốt một ngoại lệ/lỗi vì vậy tôi không thể debug nó. Làm thế nào để tôi nhận được dịch vụ để lộ ngoại lệ để tôi có thể đăng nhập hoặc xử lý nó?
  2. Dịch vụ là nhập vào trạng thái bị lỗi sau ngoại lệ này bị nuốt. Làm thế nào để Tôi ngăn dịch vụ xâm nhập vào trạng thái bị lỗi?
+0

ở đây bạn có thể nhận được tất cả các lý thuyết http://msdn.microsoft.com/en-us/library/ms789041(v=vs.110).aspx –

Trả lời

18

Hầu hết, nếu không phải tất cả các trường hợp ngoại lệ đều có thể được nhìn thấy trong Dấu vết WCF (Configuring Tracing) và theo dõi được xem tốt nhất với Service Trace Viewer.

Rõ ràng, đây không phải là điều bạn nên chạy cả ngày trong môi trường sản xuất, nhưng nó vẫn giúp khắc phục sự cố.

Ngoài ra, lưu ý rằng oneways có thể không chạy dưới dạng "fire and forget" đúng tùy thuộc vào SessionMode bạn sử dụng. Nếu bạn có dịch vụ của bạn được cấu hình cho SessionMode.Allowed hoặc thậm chí SessionMode.Required, hoạt động oneway sẽ chạy như thể nó không phải là oneway ở tất cả (điều này có thể được quan sát thấy khi sử dụng oneways qua netTcpBinding). Để thẳng thắn, tuy nhiên, tôi không biết nếu điều đó thay đổi loại ngoại lệ bạn có thể nhận được hoặc khi bạn nhận được chúng. Tuy nhiên, trong mọi trường hợp, bạn sẽ nhận được ngoại lệ nếu yêu cầu không thể gửi được. AFAIK, oneway "kết thúc" khi nó được đánh bại thành công ở phía máy chủ. Vì vậy, có một số nơi cho (WCF khuôn khổ liên quan) ngoại lệ cho đến khi đó (serialization/deserialization đến tâm). Sau đó, các ngoại lệ liên quan đến khung như vậy được nhìn thấy rõ nhất (ngay cả IErrorHandler không nhận được tất cả do thực tế khi nó được gọi trong luồng yêu cầu/đáp ứng) bằng cách sử dụng dấu vết/traceviewer đã đề cập ở trên.

+0

Tôi đang gặp vấn đề tương tự. Tôi có dịch vụ đang chạy trên Sản xuất với netTcpBinding có ít phương pháp như IsOneway = True và SessionMode Để yêu cầu nó hoạt động tôi phải khởi động lại nó –

11

Ngoại lệ sẽ báo lỗi proxy. Bạn không thể AFAIK làm nhiều về điều đó: không gây ra ngoại lệ ;-p

Tôi hơi ngạc nhiên rằng một chiều vẫn gây ra vấn đề, nhưng vì nuốt trong chi l, có 3 các khía cạnh:

  1. bạn có đang ném faults không? hoặc ngoại lệ? nó quan trọng (và phải là "lỗi")
  2. như là một hack, bạn có thể kích hoạt thông báo gỡ lỗi ngoại lệ - nhưng tắt nó đi xin vui lòng !!!
  3. bạn có đang "sử dụng" đối tượng dịch vụ không? Tôi đã chỉ blogged về chủ đề chính xác này ... về cơ bản, "sử dụng" của bạn có thể nuốt được ngoại lệ. 3 lựa chọn:

    • không sử dụng "sử dụng"
    • lớp proxy và ghi đè Dispose()
    • quấn nó, theo blog
+0

Cảm ơn các bình luận Marc. Tôi đã ngừng sử dụng để thử và theo dõi các ngoại lệ nhưng không may mắn. Lớp kinh doanh mà dịch vụ WCF đang gọi là ném ngoại lệ nhưng chúng đang bị nuốt chửng ở đâu đó ... Bí ẩn ... – Guy

+1

Bạn có thể thử chuyển sang FaultException trong đó T là lỗi được xuất bản - có thể giúp ích.Và lưu ý nó vẫn rất quan trọng để đóng proxy; đơn giản là "sử dụng" không nhất thiết phải làm những gì chúng tôi muốn trong dịp này. –

+0

Tôi nghĩ rằng chỉ những trường hợp ngoại lệ không bị bắt và bị dịch vụ bao trả sẽ lỗi proxy, nhưng không phải tất cả ngoại lệ –

7

Khoảng 2) ...

Bí quyết là bạn nên sử dụng "sử dụng" và nên thường xuyên gọi Abort() trên proxy đó ném một ngoại lệ. Bài viết WCF Gotcha giải thích tất cả.

Chúng tôi sử dụng lớp dịch vụ được lấy cảm hứng từ bài viết đó kết thúc cuộc gọi dịch vụ. Đây là mã mẫu từ dự án của tôi:

ServiceHelper<CodeListServiceClient, CodeListService.CodeListService>.Use(
    proxy => seasonCodeBindingSource.DataSource = proxy.GetSeasonCodes(brandID); 
); 

Và đây là mã của ServiceHelper, được sửa đổi đôi chút so với bài viết. Cho đến nay nó đã phục vụ chúng tôi thực sự tốt.

using System; 
using System.ServiceModel; 

namespace Sportina.EnterpriseSystem.Client.Framework.Helpers 
{ 
    public delegate void UseServiceDelegate<TServiceProxy>(TServiceProxy proxy); 

    public static class ServiceHelper<TServiceClient, TServiceInterface> where TServiceClient : ClientBase<TServiceInterface>, new() where TServiceInterface : class 
    { 
     public static void Use(UseServiceDelegate<TServiceClient> codeBlock) 
     { 
      TServiceClient proxy = null; 
      bool success = false; 
      try 
      { 
       proxy = new TServiceClient();    
       codeBlock(proxy); 
       proxy.Close(); 
       success = true; 
      } 
      catch (Exception ex) 
      { 
       Common.Logger.Log.Fatal("Service error: " + ex);         
       throw; 
      } 
      finally 
      { 
       if (!success && proxy != null) 
        proxy.Abort(); 
      } 
     } 
    } 
} 
+3

Liên kết tới bài đăng 'WCF Gotcha' bị hỏng, nhưng tôi không có đủ đại diện để chỉnh sửa nó. Đây là liên kết tốt: http://old.iserviceoriented.com/blog/post/Indisposable+-+WCF+Gotcha+1.aspx. – yzorg

+0

@yzorg - Cảm ơn bạn đã liên kết, tôi vừa cập nhật câu trả lời. – LamonteCristo

6

Tôi gặp sự cố trong đó Kênh vẫn ở trạng thái bị lỗi sau ngoại lệ ReceiveTimeout. Điều này sẽ làm cho dịch vụ không được sử dụng bởi bất kỳ kết nối nào sau đó.

Việc sửa chữa cho việc khôi phục các dịch vụ từ tình trạng đứt gãy đối với tôi là để xử lý các sự kiện faulted của kênh thông tin liên lạc:

channelFactory = new ChannelFactory<IService>(endpoint); 
channelFactory.Faulted += OnChannelFaulted; 
var channel = channelFactory.CreateChannel(); 

Sau đó, xác định OnChannelFaulted:

void OnChannelFaulted(object sender, EventArgs e) 
{ 
    channelFactory.Abort(); 
} 

Lưu ý: Tôi đang chạy cấu hình WCF thông qua mã so với việc sử dụng các ràng buộc trong Web.config's.

8

Thông thường dịch vụ WCF được lưu trữ trong ServiceHost, nếu WCF-Service không thành công thì tùy chọn duy nhất là hủy dịch vụ WCF và bắt đầu dịch vụ WCF mới.

Các ServiceHost có kích hoạt sự kiện "đứt gãy" được kích hoạt khi các dịch vụ WCF thất bại:

ServiceHost host = new ServiceHost(new Service.MyService()); 
host.Faulted += new EventHandler(host_faulted); 
host.Open(); 

Có thể để có được ngoại lệ gây ra lỗi, nhưng nó đòi hỏi một chút công việc nhiều hơn:

public class ErrorHandler : IErrorHandler 
{ 
    public void ProvideFault(Exception error, MessageVersion version, ref Message fault) 
    { 

    } 

    public bool HandleError(Exception error) 
    { 
     Console.WriteLine("exception"); 
     return false; 
    } 
} 

public class ErrorServiceBehavior : IServiceBehavior 
{ 
    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
    { 

    } 

    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) 
    { 

    } 

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
    { 
     ErrorHandler handler = new ErrorHandler(); 
     foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers) 
     { 
      dispatcher.ErrorHandlers.Add(handler); 
     } 
    } 
} 

ServiceHost host = new ServiceHost(new Service.MyService()); 
host.Faulted += new EventHandler(host_faulted); 
host.Description.Behaviors.Add(new ErrorServiceBehavior()); 
host.Open(); 

Tín http://www.haveyougotwoods.ca/2009/06/24/creating-a-global-error-handler-in-wcf

+1

Đã thử điều này nhưng phương thức HandleError không bao giờ bị trúng, mặc dù tôi đã nhấn trình xử lý sự kiện bị lỗi. – Brent

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