2010-06-21 11 views
7

Chúng tôi đang sử dụng Nhà cung cấp phiên ngoài quy trình (ScaleOut) cho ứng dụng ASP.NET và chúng tôi nhận thấy rằng khi một đối tượng không được thiết lập chính xác để hủy tuần tự hóa. nó sẽ cuối cùng khiến toàn bộ quá trình chấm dứt.Làm thế nào để bảo vệ các hồ bơi ứng dụng khỏi các trường hợp ngoại lệ tuần tự hóa phiên?

Sao chép và xử lý trường hợp này là nơi nó trở nên thú vị hơn.

Trường hợp ngoại lệ mà chấm dứt quá trình trên được nêu ra trong AnyStaObjectsInSessionState mà thực hiện khá đơn giản:

internal static bool AnyStaObjectsInSessionState(HttpSessionState session) 
{ 
    if (session != null) 
    { 
     int count = session.Count; 
     for (int i = 0; i < count; i++) 
     { 
      object obj2 = session[i]; 
      if (((obj2 != null) && (obj2.GetType().FullName == "System.__ComObject")) 
       && (UnsafeNativeMethods.AspCompatIsApartmentComponent(obj2) != 0)) 
      { 
       return true; 
      } 
     } 
    } 
    return false; 
} 

Dưới đây là stack trace cho thấy cách ngoại lệ ở đây chấm dứt quá trình:

An unhandled exception occurred and the process was terminated. 

Application ID: /LM/W3SVC/1/ROOT 

Process ID: 4208 

Exception: System.Runtime.Serialization.SerializationException 

Message: The constructor to deserialize an object of type 'Lucene.Net.QueryParsers.ParseException' was not found. 

StackTrace: at System.Runtime.Serialization.ObjectManager.CompleteISerializableObject(Object obj, SerializationInfo info, StreamingContext context) 
    at System.Runtime.Serialization.ObjectManager.FixupSpecialObject(ObjectHolder holder) 
    at System.Runtime.Serialization.ObjectManager.DoFixups() 
    at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage) 
    at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage) 
    at System.Web.Util.AltSerialization.ReadValueFromStream(BinaryReader reader) 
    at System.Web.SessionState.SessionStateItemCollection.ReadValueFromStreamWithAssert() 
    at System.Web.SessionState.SessionStateItemCollection.DeserializeItem(String name, Boolean check) 
    at System.Web.SessionState.SessionStateItemCollection.DeserializeItem(Int32 index) 
    at System.Web.SessionState.SessionStateItemCollection.get_Item(Int32 index) 
    at System.Web.SessionState.HttpSessionStateContainer.get_Item(Int32 index) 
    at System.Web.Util.AspCompatApplicationStep.AnyStaObjectsInSessionState(HttpSessionState session) 
    at System.Web.HttpApplicationFactory.FireSessionOnEnd(HttpSessionState session, Object eventSource, EventArgs eventArgs) 
    at System.Web.SessionState.SessionOnEndTargetWorkItem.RaiseOnEndCallback() 
    at System.Web.Util.WorkItem.CallCallbackWithAssert(WorkItemCallback callback) 
    at System.Threading.ExecutionContext.runTryCode(Object userData) 
    at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData) 
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
    at System.Threading._ThreadPoolWaitCallback.PerformWaitCallbackInternal(_ThreadPoolWaitCallback tpWaitCallBack) 
    at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback(Object state) 

InnerException: System.Runtime.Serialization.SerializationException 

Message: The constructor to deserialize an object of type 'Lucene.Net.QueryParsers.ParseException' was not found. 

StackTrace: at System.Runtime.Serialization.ObjectManager.GetConstructor(Type t, Type[] ctorParams) 
    at System.Runtime.Serialization.ObjectManager.CompleteISerializableObject(Object obj, SerializationInfo info, StreamingContext context) 

Chúng tôi muốn hiểu hai điều:

  1. Khi nào FireSessionOnEnd lửa cho nhà cung cấp ngoài quy trình và, quan trọng hơn, làm cách nào chúng ta có thể bắt chước điều này trong môi trường phát triển không được tải? Tôi đã thử nghiệm với thời gian chờ phiên giảm xuống (đặt thành một phút), tự gọi Abandon() và tự gọi GC.Collect(), tất cả đều không có kết quả.

  2. Chúng tôi có thể bẫy lỗi xảy ra ở bước này để bảo vệ hồ bơi ứng dụng không? Các ngoại lệ được nêu ở đây được ghi lại w/Nguồn = ASP.NET 2.0.50727.0 và không đạt được trình xử lý lỗi ứng dụng trong global.asax. Những gì chúng ta có thể làm để bảo vệ chống lại kịch bản này, ngay cả sau khi kiểm tra thích hợp & số dư được áp dụng cho các đối tượng ràng buộc phiên?

Mọi thông tin chi tiết sẽ được đánh giá cao.

+1

Có thể họ nên sửa mã của họ để không cho phép ngoại lệ serialziation làm hỏng AppDomain. Chỉ là một ý nghĩ. –

+0

Đó là một suy nghĩ tốt, và tôi nghĩ rằng họ đồng ý; đó là một kịch bản cực kỳ hiếm nhưng một trong đó nên được bảo vệ chống lại dù sao. – Nariman

+0

@ John: Có vẻ như anh ấy đang sử dụng Lucene.net. Mặc dù nó là một ứng dụng của bên thứ 3, AFAIK, nguồn mở của nó và anh ta nên đánh dấu lớp vi phạm 'Serializable' – ram

Trả lời

3

Chúng tôi đã có thể giải quyết vấn đề này với sự giúp đỡ hỗ trợ kỹ thuật Soss - họ là rất hữu ích - đây là những chi tiết:

  • Khi phiên hết hạn, Soss đặt ra một sự kiện hết hạn trong thư viện của khách hàng, do đó phải chịu trách nhiệm cho bắn Session_End trong Global.asax (NB: dư tải ScaleOut sự kiện hết hạn trên khách hàng, vì vậy web máy chủ c reated phiên có thể không thường xuyên nhận được sự kiện hết hạn của nó - điều này là rất quan trọng cho việc cố gắng để tái sản xuất những vấn đề này).
  • Bởi vì điều này xảy ra bên ngoài ngữ cảnh của một yêu cầu, ngoại lệ bị hủy và giết chết nhóm ứng dụng;
  • Đó là một trường hợp cực kỳ hiếm gặp nhưng một trong số đó sẽ vẫn giải quyết trong các bản phát hành bảo trì sắp tới;
  • Các biện pháp như sau:

    1. System.Exception loại -derived (đó là serializable nhưng không unserializable);

    2. Di Session_End sự kiện trong Global.asax hoặc tắt sự kiện hết hạn (max_event_retries thiết lập để 0 trong soss_params.txt);

    3. Trong những tình huống, nó có khả năng mà người dùng gặp một SerializationException trên một trong yêu cầu của họ, có nghĩa là nó đạt Application_Error; tại đây bạn có thể xóa khóa phiên (phải xóa tất cả chúng) hoặc từ bỏ phiên hoàn toàn;

    4. Theo dõi AppDomain.UnhandledException là thông báo về trường hợp ngoại lệ unhandled, họ nên xảy ra (không tin tưởng ở đây, chỉ đăng nhập); họ cũng có thể bị vô hiệu hóa qua legacyUnhandledExceptionPolicy (không phải được đề nghị);

1

Can chúng tôi bẫy lỗi đó xảy ra tại bước này để bảo vệ hồ bơi ứng dụng? Các trường hợp ngoại lệ được nêu ở đây được ghi lại w/ Nguồn = ASP.NET 2.0.50727.0 và không tiếp cận trình xử lý lỗi ứng dụng trong global.asax. Chúng tôi có thể làm gì để bảo vệ chống lại tình huống này, thậm chí sau khi kiểm tra thích hợp & số dư được áp dụng cho các đối tượng bị ràng buộc theo phiên?

Tôi không biết nếu this sẽ làm việc, nhưng bạn có thể cho nó một shot

+0

Cảm ơn, nhưng điều này không thực sự bảo vệ chống lại kịch bản, nó chỉ cho phép bạn đăng nhập nó. Đây là một cách nhanh chóng để tái sản xuất: http://www.brianlow.com/index.php/2007/01/11/catching-unhandled-aspnet-exceptions/. Chủ đề nền * phải * bắt ngoại lệ hoặc con tàu bị hỏng. – Nariman

0

tôi cố định này bằng cách đơn giản loại bỏ các phương pháp SessionEnd hoàn toàn. Nó không phải là đủ để loại bỏ các nội dung của các phương pháp như Asp.net tìm kiếm sự tồn tại của phương pháp sử dụng sự phản ánh và sau đó chạy mã vi phạm.