Windows Azure Worker Role 沒有通過第一行程式碼
我有一個工人角色,在開發中完美地工作,但在部署時不起作用。“不起作用”相當模糊,但這就是我必須繼續做的所有事情,因為我沒有看到任何錯誤或任何東西(無論如何在事件日誌中 - 也許還有其他地方我可以查看)。我在我的程式碼中添加了一些跟踪語句,我看到第一個出現了,但其他的都沒有。
工人角色程式碼:
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 程式碼:
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()); } }配置:
<?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>一旦工人開始,如果我查看 WADLogsTable,我看到的只是“WorkerRole.OnStart()”,沒有別的!
任何有關問題可能是什麼或如何解決此問題的想法將不勝感激。
**更新:**如果我停止該角色,我也看不到該
OnStop()方法中的任何調試語句。**更新:**我的診斷必須有一些配置不正確。我以為我在本地調試時看到我的調試正確,但事實證明我不是。我在輸出視窗中看到了所有內容,但在儲存表中沒有看到所有內容。我在開發中看到以下條目:
WorkerRole.OnStart() WorkerRole.Initialize() Configuring AutoMapper...我意識到跟踪輸出只是定期上傳,但我已經等了 5 分鐘左右,所以我認為這應該足夠長,因為我將它設置為 1 分鐘。
**更新:**正如@kwill 在評論部分所建議的,我嘗試添加一個文件跟踪偵聽器,如下所示:
<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>這在我的開發環境中執行良好,並且看起來更可靠,並且我得到了我期望的所有調試。但是,當我將其部署到登台時,甚至沒有創建 TextWriterOutput.log 文件!
我真的需要一種可靠的方法來從我的工人角色中進行調試,以便我可以解決最終問題,即我的工作無法正常工作 - 在這一點上,我仍然不知道他們甚至試圖做什麼,因為我無法進行任何調試!
**更新:**我很確定大多數人建議的缺失 dll 想法不是問題所在。為了希望證明這一點,我重寫了 run 方法,如下所示,我看到“Heartbeat …”調試出來了。在我看來,診斷功能或至少我配置它的方式是不可靠的,這使我無法調查究竟為什麼我的工作沒有執行。
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"); } }**更新:**我現在已經在Windows Azure MSDN 論壇上交叉發布了這個問題。
**更新:**正如評論中所建議的,我現在嘗試刪除所有“有用”的程式碼。在開發中,這導致所有調試都被輸出。然後我嘗試刪除呼叫,因為之前
AutomapperConfiguration.Configure()我沒有看到該呼叫後出現任何內容。這導致一些跟踪語句不再出現。然而重要的是,我看到了我在“工作”中放入的跟踪語句。由於我最終想要解決的是未執行的作業,因此我將該版本的程式碼部署到暫存,但在那裡我只看到了 OnStart() 跟踪和“心跳”跟踪。我不認為這真的有幫助,但也許它會給某人一些想法。
鑑於呼叫了 OnStart() 跟踪,但沒有呼叫 Initialize(),我的猜測是 Initialize() 中的程式碼引用的程序集之一沒有被複製到部署中。請記住,.Net JIT 一次編譯一個方法,並且由於這種行為,顯示 OnStart 跟踪消息是有意義的(因為到目前為止,除了 Windows Azure 和標準 .Net 框架程序集之外幾乎沒有引用) . 但是,當 CLR 轉到 JIT Initialize 方法時,它會嘗試載入幾個第三方程序集(AutoMapper 和 Windsor),這些程序集可能未正確打包,但可能在模擬器執行時被 GACced 或以其他方式在本地可用。
有幾件事可以嘗試:
- 從 Visual Studio 手動“打包”您的部署並仔細查看建構輸出。很多時候,VS 會擷取你失去的程序集並告訴你(不幸的是作為警告,而不是錯誤)你失去了一些東西。
- 如果您在輸出中看不到任何明顯的內容,請查看 cspkg 文件本身(記住它只是一個包含更多 ZIP 文件的 ZIP 文件)並確保您的應用程序/角色需要的任何引用程序集都在那裡. 或者,連接到 VM 並檢查這些程序集的 approot。
- 您可能會在 VM 的事件日誌中找到一個條目,表明您的應用程序無法載入程序集。
通常,此類問題的根本原因是缺少依賴項。在之前的答案中已經有這方面的好建議。
根據您的配置,跟踪日誌每分鐘傳輸一次到 Azure 儲存。如果您的工作程序崩潰,您可能會失去一些最後的跟踪消息。要解決此問題,請嘗試在異常處理程序中添加 Thread.Sleep(TimeSpan.FromMinutes(2)) 以確保將異常日誌刷新到儲存中。
最後,如果一切都失敗了,我建議您嘗試使用 WinDbg 調試您的角色。為您的角色啟用遠端桌面。登錄角色並關閉 IE 安全瀏覽,以便您可以安裝東西。然後從http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=8279下載並安裝適用於 Windows 的調試工具。此軟體包包含整個 Windows SDK,但您可以選擇僅安裝適用於 Windows 的調試工具。
然後執行 WinDbg 並附加到 WaWorkerHost.exe。在 WinDbg 中,執行
.loadby sos clr // load the SOS extension that allows you to do managed debugging sxe clr // break on CLR exceptions g // continueWinDbg 現在應該在出現 CLR 異常時中斷執行。當它中斷時,執行
!PrintException查看異常詳細資訊。您可能希望在角色啟動中添加另一個 Thread.Sleep 呼叫,以便在程序退出之前有時間附加調試器。