Windows Azure Worker角色未超过第一行代码

s1m*_*m0t 10 .net system.diagnostics azure azure-worker-roles

我有一个工作角色,在开发中完美运行但在部署时不起作用."不起作用"是相当模糊的,但这真的是我必须继续,因为我没有看到任何错误或任何事情(事件日志中无论如何 - 也许还有其他地方我可以看).我在我的代码中添加了一些跟踪语句,我看到第一个出现了,但没有其他的.

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
}
Run Code Online (Sandbox Code Playgroud)

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

配置:

<?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>
Run Code Online (Sandbox Code Playgroud)

一旦工作人员启动,如果我查看WADLogsTable,我所看到的只是"WorkerRole.OnStart()"而没有别的!

关于问题可能是什么或如何解决这个问题的任何想法将不胜感激.

更新:如果我停止该角色,我也没有看到该OnStop()方法的任何调试语句.

更新:必须有一些与我的诊断正确配置.我认为我在本地调试时看到我的调试正确,但事实证明我不是.我在输出窗口中看到了所有内容,但我没有看到存储表中的所有内容.我在开发中看到以下条目:

WorkerRole.OnStart()
WorkerRole.Initialize()
Configuring AutoMapper...
Run Code Online (Sandbox Code Playgroud)

我意识到跟踪输出只是定期上传,但是我已经等了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>
Run Code Online (Sandbox Code Playgroud)

这在我的开发环境中运行良好,看起来更可靠,并且我得到了我期望的所有调试.但是,当我将其部署到暂存时,甚至没有创建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");
        }
    }
Run Code Online (Sandbox Code Playgroud)

更新:我现在已经在Windows Azure MSDN论坛上发布了此问题.

更新:正如评论中所建议的那样,我现在尝试删除所有"有用的"代码.在开发中,这导致所有调试都被输出.然后,我尝试只是删除调用AutomapperConfiguration.Configure(),因为以前我看到什么电话后问世.这导致一些跟踪声明不再出现.但重要的是,我看到了我在"工作"中提出的跟踪声明.由于我最终想要解决的是没有运行的作业,我将该版本的代码部署到了暂存,但在那里我只看到OnStart()跟踪和"心跳"跟踪.我不认为这真的有帮助,但也许它会给某人一些想法.

Dou*_*rer 5

鉴于OnStart()跟踪被调用,而不是Initialize(),我猜测是由Initialize()中的代码引用的程序集之一未被复制到部署.请记住.Net JIT - 一次编译一个方法,并且由于这种行为,OnStart跟踪消息显示出来是有意义的(因为除了Windows Azure和标准.Net框架程序集之外没有其他内容) .但是,当CLR转到JIT初始化方法时,它会尝试加载可能未正确打包的多个第三方程序集(AutoMapper和Windsor),但可以在模拟器运行时进行GACced或本地可用.

有几件事要尝试:

  1. 从Visual Studio手动"打包"您的部署,并仔细查看构建输出.很多时候,VS会抓住你丢失的组件并告诉你(不幸的是作为警告,而不是错误),你错过了什么.
  2. 如果您在输出中看不到任何看起来很明显的内容,请查看cspkg文件本身(请记住它只是一个包含更多ZIP文件的ZIP文件),并确保您的应用程序/角色所需的任何引用程序集都在那里.或者,连接到VM并检查这些程序集的批准.
  3. 您可以在VM的事件日志中找到一个条目,该条目显示您的应用程序无法加载程序集.


s1m*_*m0t 1

感谢MSDN 论坛上的回答,我已经能够排除并解决我的问题。

我的工作没有被执行的原因是由于以下行:

_container.Install(FromAssembly.InDirectory(
                    new AssemblyFilter(Path.Combine(Environment.GetEnvironmentVariable(Constants.RoleRoot), Constants.AppRoot))));
Run Code Online (Sandbox Code Playgroud)

登台时的角色 root 是 E:。Path.Combine() 有一个晦涩的实现,您可以在这个 SO 答案中阅读更多信息。这意味着 Castle 正在 E:approot 中搜索程序集,而不是像我预期的那样在 E:\approot 中搜索。我现在正在使用以下方法构建 approot 路径:

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

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

        return Path.Combine(root, Constants.AppRoot);
    }
Run Code Online (Sandbox Code Playgroud)

这已经解决了我的主要问题,我现在看到作业按预期执行。

我只能通过在提升的执行上下文中运行辅助角色来解决此问题,以便我的跟踪数据可以写入文件。我仍然不知道为什么,并且想听听为什么跟踪语句没有正确传输到存储的任何想法。