2012-02-23 26 views
10

Tôi có vai trò công nhân hoạt động hoàn hảo trong phát triển nhưng không hoạt động khi được triển khai. "Không hoạt động" là khá mơ hồ, nhưng đó thực sự là tất cả những gì tôi phải tiếp tục vì tôi không thấy bất kỳ lỗi nào hay bất cứ điều gì (trong bản ghi sự kiện anyway - có thể có một nơi khác tôi có thể xem). Tôi đã thêm một số phát biểu dấu vết vào mã của tôi và tôi thấy cái đầu tiên xuất hiện, nhưng không có cái nào khác.Windows Azure Worker Vai trò không vượt qua dòng mã đầu tiên

Mã WorkerRole:

public class WorkerRole : RoleEntryPoint 
{ 
    #region Member variables 

    private IWindsorContainer _container; 

    private IJob[] _jobs; 

    #endregion 

    #region Methods 

    public override bool OnStart() 
    { 
     ConfigureDiagnostics(); 

     Trace.WriteLine("WorkerRole.OnStart()"); 

     try 
     { 
      Initialize(); 

      Trace.WriteLine("Resolving jobs..."); 
      _jobs = _container.ResolveAll<IJob>(); 

      StartJobs(); 

      return base.OnStart(); 
     } 
     catch (Exception ex) 
     { 
      TraceUtil.TraceException(ex); 
      throw; 
     } 
     finally 
     { 
      Trace.WriteLine("WorkerRole.OnStart - Complete"); 
      Trace.Flush(); 
     } 
    } 

    /// <summary> 
    /// Sets up diagnostics. 
    /// </summary> 
    private void ConfigureDiagnostics() 
    { 
     DiagnosticMonitorConfiguration dmc = 
      DiagnosticMonitor.GetDefaultInitialConfiguration(); 

     dmc.Logs.ScheduledTransferPeriod = TimeSpan.FromMinutes(1); 
     dmc.Logs.ScheduledTransferLogLevelFilter = LogLevel.Verbose; 

     DiagnosticMonitor.Start(Constants.DiagnosticsConnectionString, dmc); 
    } 

    /// <summary> 
    /// Sets up the IoC container etc. 
    /// </summary> 
    private void Initialize() 
    { 
     Trace.WriteLine("WorkerRole.Initialize()"); 

     try 
     { 
      Trace.WriteLine("Configuring AutoMapper..."); 
      AutoMapperConfiguration.Configure(); 

      Trace.WriteLine("Configuring Windsor..."); 
      _container = new WindsorContainer(); 

      Trace.WriteLine(string.Format("Installing assemblies from directory...{0}", 
       Path.Combine(Environment.GetEnvironmentVariable(Constants.RoleRoot), Constants.AppRoot))); 

      _container.Install(FromAssembly.InDirectory(
       new AssemblyFilter(Path.Combine(Environment.GetEnvironmentVariable(Constants.RoleRoot), Constants.AppRoot)))); 

      Trace.WriteLine(string.Format("Setting the default connection limit...")); 
      ServicePointManager.DefaultConnectionLimit = 12; 
     } 
     finally 
     { 
      Trace.WriteLine("WorkerRole.Initialize - Complete"); 
     } 
    } 

    /// <summary> 
    /// Starts all of the jobs. 
    /// </summary> 
    private void StartJobs() 
    { 
     Trace.WriteLine("WorkerRole.StartJobs()"); 

     try 
     { 
      foreach (IJob job in _jobs) 
      { 
       job.Start(); 
      } 
     } 
     finally 
     { 
      Trace.WriteLine("WorkerRole.StartJobs - Complete"); 
     } 
    } 

    public override void OnStop() 
    { 
     Trace.WriteLine("WorkerRole.OnStop()"); 

     try 
     { 
      foreach (IJob job in _jobs) 
      { 
       job.Stop(); 
      } 
      _container.Dispose(); 
     } 
     finally 
     { 
      Trace.WriteLine("WorkerRole.OnStop - Complete"); 
     } 
    } 

    #endregion 

    #region Private util classes 

    public static class AutoMapperConfiguration 
    { 
     public static void Configure() 
     { 
      Mapper.Initialize(x => x.AddProfile<ModelProfile>()); 
     } 
    } 

    #endregion 
} 

TraceUtil Code:

public static class TraceUtil 
{ 
    public static void TraceException(Exception ex) 
    { 
     StringBuilder buffer = new StringBuilder(); 

     while (ex != null) 
     { 
      buffer.AppendFormat("{0} : ", ex.GetType()); 
      buffer.AppendLine(ex.Message); 
      buffer.AppendLine(ex.StackTrace); 

      ex = ex.InnerException; 
     } 
     Trace.TraceError(buffer.ToString()); 
    } 
} 

Config:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    ... 
    <system.diagnostics> 
    <trace autoflush="true"> 
     <listeners> 
     <add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" 
      name="AzureDiagnostics"> 
      <filter type="" /> 
     </add> 
     </listeners> 
    </trace> 
    </system.diagnostics> 
</configuration> 

Khi người lao động có s tarted, nếu tôi nhìn vào WADLogsTable, tất cả những gì tôi thấy là "WorkerRole.OnStart()" và không có gì khác!

Bất kỳ ý tưởng nào về vấn đề có thể là gì hoặc cách khắc phục sự cố này sẽ được đánh giá cao.

Cập nhật: Nếu tôi dừng vai trò, tôi cũng không thấy bất kỳ câu lệnh gỡ lỗi nào từ phương thức OnStop().

Cập nhật: I phải có cấu hình nào đó không chính xác với chẩn đoán của tôi. Tôi nghĩ rằng tôi đã nhìn thấy gỡ lỗi của tôi đi ra một cách chính xác khi gỡ lỗi tại địa phương, nhưng nó quay ra tôi không. Tôi thấy mọi thứ trong cửa sổ đầu ra, nhưng tôi không thấy mọi thứ trong bảng lưu trữ. Tôi nhìn thấy các mục sau trong phát triển:

WorkerRole.OnStart() 
WorkerRole.Initialize() 
Configuring AutoMapper... 

Tôi nhận ra rằng những dấu vết đầu ra được chỉ định kỳ tải lên, nhưng tôi đã chờ 5 phút hoặc lâu hơn, vì vậy tôi nghĩ rằng đây sẽ là đủ dài, kể từ khi tôi có nó đặt thành 1 phút.

Cập nhật: Theo đề nghị của @kwill trong phần ý kiến ​​tôi đã cố gắng thêm một tập tin dấu vết người nghe như sau:

<system.diagnostics> 
    <trace autoflush="true"> 
     <listeners> 
     <add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" 
      name="AzureDiagnostics"> 
     </add> 
     <add name="File" type="System.Diagnostics.TextWriterTraceListener" initializeData="C:\TextWriterOutput.log" /> 
     </listeners> 
    </trace> 
    </system.diagnostics> 

này hoạt động tốt trong môi trường phát triển của tôi và dường như đáng tin cậy hơn cũng như tôi nhận được tất cả các gỡ lỗi mà tôi mong đợi. Tuy nhiên, khi triển khai nó để dàn dựng, tệp TextWriterOutput.log thậm chí không được tạo!

Tôi thực sự cần một cách đáng tin cậy để gỡ lỗi vai trò công nhân để tôi có thể khắc phục vấn đề cuối cùng, đó là công việc của tôi không hoạt động - tại thời điểm này tôi vẫn không biết họ đang cố gắng gì để làm như tôi không thể nhận được bất kỳ gỡ lỗi ra!

Cập nhật: Tôi khá chắc chắn rằng ý tưởng dll bị thiếu được đề xuất bởi hầu hết mọi người không phải là vấn đề. Để hy vọng chứng minh điều này, tôi đã ghi đè lên phương thức chạy như hình dưới đây và tôi thấy lỗi "Nhịp tim ..." xuất hiện. Dường như với tôi rằng chức năng chẩn đoán hoặc ít nhất là cách tôi đã cấu hình nó là không đáng tin cậy, điều đó ngăn cản tôi điều tra lý do tại sao trên trái đất công việc của tôi không chạy.

public override void Run() 
    { 
     Trace.WriteLine("LearningMiles.JobProcessor.WorkerRole.Run()", "Information"); 

     try 
     { 
      while (true) 
      { 
       Thread.Sleep(10000); 
       Trace.WriteLine("Heartbeat...", "Verbose"); 
      } 
     } 
     catch (Exception ex) 
     { 
      TraceUtil.TraceException(ex); 
      throw; 
     } 
     finally 
     { 
      Trace.WriteLine("LearningMiles.JobProcessor.WorkerRole.Run() - Complete", "Information"); 
     } 
    } 

Cập nhật: bây giờ tôi đã qua bài đăng vấn đề này trên các Windows Azure MSDN forum.

Cập nhật: Như đã đề xuất trong nhận xét, tôi hiện đã thử xóa tất cả mã 'hữu ích'. Trong quá trình phát triển, điều này dẫn đến tất cả các lỗi được tạo ra. Sau đó tôi đã thử chỉ cần xóa cuộc gọi đến AutomapperConfiguration.Configure() vì trước đây tôi không thấy gì xảy ra sau cuộc gọi đó. Điều này dẫn đến một số câu lệnh theo dõi không xuất hiện trở lại. Tuy nhiên, quan trọng hơn, tôi đã nhìn thấy các phát biểu dấu vết mà tôi đã đưa vào "công việc". Vì đó là công việc không chạy mà cuối cùng tôi muốn giải quyết, tôi đã triển khai phiên bản mã đó để dàn dựng, nhưng tôi chỉ thấy dấu vết OnStart() và dấu vết "nhịp tim". Tôi không nghĩ rằng điều này thực sự hữu ích, nhưng có lẽ nó sẽ cung cấp cho ai đó một số ý tưởng.

+0

Bạn đã thiết lập đúng tài khoản lưu trữ của mình cho chẩn đoán chưa? Một số người quên bỏ cài đặt LocalStorage – Igorek

+0

Tôi tin như vậy. Tôi nhận được một mục trong bảng mà dường như chứng minh rằng lý thuyết. Ngoài ra, tôi đã làm sai lầm đó ban đầu, nhưng VS sẽ không xây dựng các gói với nó còn lại như thế. – s1mm0t

+1

Điều gì sẽ xảy ra nếu bạn xóa tất cả mã 'hữu ích' khỏi tất cả các phương thức và chỉ để lại các cuộc gọi 'Trace.WriteLine' và triển khai để dàn dựng? Vẫn không có tin nhắn ngoại trừ tin nhắn đầu tiên? –

Trả lời

1

Nhờ câu trả lời trên MSDN forum, tôi đã có thể khắc phục sự cố và giải quyết vấn đề của mình.

Lý do tại sao công việc của tôi đã không được thực hiện được do dòng dưới đây:

_container.Install(FromAssembly.InDirectory(
        new AssemblyFilter(Path.Combine(Environment.GetEnvironmentVariable(Constants.RoleRoot), Constants.AppRoot)))); 

Gốc vai trò trên dàn là E :. Path.Combine() có triển khai tối nghĩa mà bạn có thể đọc thêm về trong this SO answer. Điều này có nghĩa là Castle đang tìm kiếm các hội đồng trong E: phê duyệt thay vì E: \ approot như tôi mong đợi. Tôi hiện đang xây dựng đường dẫn phê duyệt bằng phương pháp bên dưới:

private string GetAppRoot() 
    { 
     string root = Environment.GetEnvironmentVariable(Constants.RoleRoot); 

     if (root.EndsWith(Path.VolumeSeparatorChar.ToString())) 
      root += Path.DirectorySeparatorChar; 

     return Path.Combine(root, Constants.AppRoot); 
    } 

Điều đó đã giải quyết được vấn đề chính của tôi và hiện tôi đang thấy công việc thực hiện như mong đợi.

Tôi chỉ có thể khắc phục sự cố này bằng cách chạy vai trò công nhân trong ngữ cảnh thực thi nâng cao để dữ liệu theo dõi của tôi có thể được ghi vào tệp. Tôi vẫn không biết tại sao, và muốn nghe bất kỳ ý tưởng nào tại sao, các phát biểu dấu vết đã không được chuyển sang lưu trữ một cách chính xác.

+0

Có vẻ như bây giờ nhân viên đang chạy trong một ngữ cảnh nâng cao, bây giờ tôi thấy tất cả các lỗi cũng xuất hiện trong bộ nhớ. Tôi sẽ cố gắng xác nhận điều này ngay khi tôi có thời gian. – s1mm0t

0

Bạn có nói rằng bạn sẽ có được dấu vết

"WorkerRole.OnStart()" 

nhưng không phải là dấu vết

"WorkerRole.Initialize()" 

Điều đó có vẻ rất khó kể từ khi hai báo cáo theo dõi thực hiện một trong những quyền sau khi khác.

Bạn đã thử RDP với máy ảo để xem quy trình WaWorkerHost.exe có bị lỗi không?

+0

Đó là chính xác những gì tôi đang nói - Tôi biết nó có vẻ khó xảy ra, nhưng đó là tất cả những gì tôi thấy trong bảng WADLogs! Tôi sẽ RDP và kiểm tra quá trình WaWorkerHost vào ngày mai. – s1mm0t

+0

Tôi hiện đã kiểm tra và quá trình WaWorkerHost.exe có vẻ như đã hết. – s1mm0t

+0

Một vài điều tôi sẽ đề xuất: 1. Thêm một trình theo dõi tệp tin ngoài Trình phân tích chẩn đoán đối tượng. Điều này sẽ cho bạn biết sự cố là ứng dụng của bạn hay sự cố là chẩn đoán Azure. 2. Sử dụng một cái gì đó như DebugView (http://blog.toddysm.com/2011/05/using-debugview-to-troubleshoot-windows-azure-deployments.html). – kwill

5

Với dấu vết OnStart() được gọi, nhưng không phải là Initialize(), tôi đoán là một trong các assembly được tham chiếu bởi mã trong Initialize() không được sao chép vào triển khai. Hãy nhớ rằng .Net JIT-biên dịch một phương pháp tại một thời điểm, và vì hành vi đó nó sẽ có ý nghĩa rằng thông báo dấu vết OnStart xuất hiện (như có ít khác với Windows Azure và tiêu chuẩn. Net khung hội đồng tham chiếu đến điểm đó) . Tuy nhiên, khi CLR chuyển sang phương thức khởi tạo JIT, nó sẽ cố tải một số nhóm của bên thứ ba (AutoMapper và Windsor) có thể không được đóng gói chính xác, nhưng có thể được GACced hoặc có sẵn cục bộ khi trình mô phỏng chạy.

Một vài điều để thử:

  1. thủ "trọn gói" triển khai từ Visual Studio và có một cái nhìn cẩn thận vào việc xây dựng đầu ra. Nhiều lần, VS sẽ bắt các hội đồng còn thiếu của bạn và nói với bạn (thật không may là một lời cảnh báo, không phải là một lỗi) mà bạn đang thiếu một cái gì đó.
  2. Nếu bạn không thấy bất kỳ thứ gì trong đầu ra rõ ràng, hãy xem tệp cspkg (nhớ nó chỉ là tệp ZIP có nhiều tệp ZIP trong đó) và đảm bảo mọi assembly được ứng dụng/vai trò tham chiếu của bạn đang ở trong đó. Cách khác, kết nối với máy ảo và kiểm tra sự chấp thuận cho các hội đồng đó.
  3. Bạn có thể tìm thấy mục nhập trong nhật ký sự kiện của VM cho thấy rằng ứng dụng của bạn không thể tải một assembly.
+0

Tôi nghĩ rằng đây là câu trả lời đúng. Đảm bảo rằng tùy chọn "Sao chép cục bộ" được đặt thành true trên phần thứ ba được tham chiếu như AutoMapper hoặc Windows. Ngoài ra, kiểm tra xem các loại được nạp theo kiểu thực tế (từ Windsor) có được triển khai chính xác hay không. –

+0

Đây là * không * câu trả lời đúng - tôi thực sự muốn nó là mặc dù. Tôi đã xác minh rằng tất cả các yêu cầu của dll được triển khai cho VM. Ngoài ra, nếu đây là vấn đề tôi chắc chắn sẽ thấy đầu ra ngoại lệ cho các bản ghi. Như @sami gợi ý tôi cũng đã cố gắng thêm một giấc ngủ trong xử lý ngoại lệ của tôi trong trường hợp gỡ lỗi từ đó đã không được đẩy vào lưu trữ, nhưng vô ích. – s1mm0t

+0

Tôi tin rằng phiên bản SDK mới nhất là khá tốt khi chọn các vấn đề như thế này. Khi lần đầu tiên tôi cố gắng tạo gói triển khai, tôi đã gặp phải một số lỗi "tham chiếu" mà tôi phải giải quyết mà không xảy ra trong quá trình xây dựng bình thường. – s1mm0t

0

Tôi tin rằng Doug Rohrer có câu trả lời đúng. Có một cơ hội cao mà bạn có thiếu DLL trong dự án có thể được xác minh bằng cách kiểm tra gói. Lưu ý rằng gói cần được tạo không được mã hóa nếu bạn đang sử dụng phiên bản trước đó là SDK 1.6.

Tôi muốn thêm hai điểm.

  1. Thiết “Sao chép địa phương” true, trong một số trường hợp, chỉ hoạt động nếu hồ sơ dự án được chỉnh sửa bằng tay và được một cách rõ ràng đường dẫn đầy đủ của hội đồng. (Điều này xảy ra khi lắp ráp cũng có mặt trong GAC của máy cục bộ).

  2. Nếu phụ thuộc được tham chiếu trong một hội đồng, trong được tham chiếu bởi hội đồng vai trò Azure, phụ thuộc làm không nhận được bản sao. Trong trường hợp này, các phụ thuộc này cũng cần phải thêm vào assembly mặc dù chúng không được sử dụng. (Đây là loại khó tin nhưng tôi đã gặp phải vấn đề này).

+0

Thật không may @Doug Rohrer không có câu trả lời đúng - xem nhận xét tôi đã thêm để trả lời câu trả lời của anh ấy. – s1mm0t

+0

Cảm ơn bạn đã phản hồi. Như một câu hỏi cuối cùng trên cùng một dòng suy nghĩ, và có lẽ bạn đã xác minh điều này, nhưng có thể bạn có một DLL trong GAC cục bộ của bạn hơn là không phải là bản sao? – hocho

+0

Các tham chiếu duy nhất tới GAC mà tôi có thể thấy là các thư viện chuẩn .NET chẳng hạn như System.dll. Tôi đã thêm một bản cập nhật cho các câu hỏi ban đầu của tôi mà tôi cho rằng đây không phải là vấn đề. – s1mm0t

3

Thường thì nguyên nhân gốc rễ của các vấn đề như thế này là thiếu phụ thuộc. Đã có những gợi ý tốt về mặt trước này trong các câu trả lời trước.

Nhật ký theo dõi được chuyển sang bộ nhớ Azure một lần mỗi phút theo cấu hình của bạn. Nếu quá trình công nhân của bạn gặp sự cố, bạn có thể mất một số thông báo dấu vết cuối cùng. Để giải quyết vấn đề này, hãy thử thêm một Thread.Sleep (TimeSpan.FromMinutes (2)) trong các trình xử lý ngoại lệ của bạn để đảm bảo rằng bản ghi ngoại lệ được chuyển sang lưu trữ.

Cuối cùng, nếu mọi thứ khác không thành công, tôi khuyên bạn nên thử gỡ lỗi vai trò của mình bằng WinDbg. Bật Remote Desktop cho vai trò của bạn. Đăng nhập vào vai trò và tắt IE duyệt web an toàn để bạn có thể cài đặt công cụ. Sau đó tải xuống và cài đặt Công cụ gỡ lỗi cho Windows từ http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=8279. Gói này chứa toàn bộ Windows SDK, nhưng bạn có thể chọn để cài đặt Công cụ gỡ lỗi chỉ dành cho Windows.

Sau đó chạy WinDbg và đính kèm vào WaWorkerHost.exe. Trong WinDbg, hãy

.loadby sos clr // load the SOS extension that allows you to do managed debugging 
sxe clr   // break on CLR exceptions 
g     // continue 

WinDbg giờ đây sẽ ngắt khi thực hiện ngoại lệ CLR. Khi ngắt, hãy thực hiện

!PrintException 

để xem chi tiết ngoại lệ. Bạn có thể muốn thêm một cuộc gọi Thread.Sleep khác vào vai trò khởi động của bạn để cho bạn thời gian để đính kèm trình gỡ lỗi trước khi thoát khỏi quá trình.

+0

Đây là một gợi ý tuyệt vời mà tôi thực sự nghĩ sẽ giúp ích. Rất tiếc, tôi không thấy bất kỳ ngoại lệ nào. Điều này sẽ phá vỡ các ngoại lệ trên bất kỳ chủ đề hoặc chỉ là chủ đề chính? – s1mm0t

+0

Cũng nên thêm rằng sau khi phát hành lệnh g, có vẻ như nó chạy bình thường và bây giờ tôi thấy bản sửa lỗi "Heatbeat ..." mà tôi đã thêm (xem cập nhật cho câu hỏi gốc). – s1mm0t

+0

Sử dụng lệnh! Threads in các chuỗi hiện tại. Bạn cũng có thể thử đặt một điểm ngắt ở đâu đó trong mã công việc của bạn để xem nó có bị trúng hay không. – Sami

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