【问题标题】:Worker Role process - Configuration value pollingWorker Role 流程 - 配置值轮询
【发布时间】:2013-10-28 07:24:02
【问题描述】:

我有一个工作人员角色,负责处理队列中的项目。它基本上是一个无限循环,将项目从队列中弹出并异步处理。

我有两个配置设置(PollingIntervalMessageGetLimit),我希望工作人员角色在更改时能够使用它们(因此不需要重新启动)。

private TimeSpan PollingInterval 
{
    get
    {
        return TimeSpan.FromSeconds(Convert.ToInt32(RoleEnvironment.GetConfigurationSettingValue("PollingIntervalSeconds")));
    }
}

private int MessageGetLimit 
{ 
    get 
    {
        return Convert.ToInt32(RoleEnvironment.GetConfigurationSettingValue("MessageGetLimit"));
    } 
}

public override void Run()
{
    while (true)
    {
        var messages = queue.GetMessages(MessageGetLimit);

        if (messages.Count() > 0)
        {
            ProcessQueueMessages(messages);
        }
        else
        {
            Task.Delay(PollingInterval);
        }
    }
}

问题:

在高峰时段,while 循环可能每秒运行几次。这意味着它将每天查询配置项多达 100,000 次。

这是有害的还是低效的?

【问题讨论】:

    标签: c# .net azure azure-web-roles azure-worker-roles


    【解决方案1】:

    John 的回答是一个很好的答案,它使用环境更改/更改事件来修改您的设置而无需重新启动,但我认为也许更好的方法是让您使用指数退避策略来提高轮询效率。通过让代码行为更智能,您将减少在那里调整它的频率。请记住,每次更新这些环境设置时,都必须将其推广到所有实例,这可能需要一些时间,具体取决于您运行的实例数量。此外,您在这里迈出了一步,必须有人参与。

    您正在使用 Windows Azure 存储队列,这意味着每次执行 GetMessages 时,它都会调用服务并检索 0 条或更多消息(直至您的 MessageGetLimit)。每次它要求时,您都会被收取一笔交易费用。现在,明白交易真的很便宜。即使每天 100,000 笔交易也是 0.01 美元/天。但是,不要低估循环的速度。 :) 您可能会获得比这更多的吞吐量,并且如果您有多个工作角色实例,这加起来(尽管与实际运行实例本身相比仍然是一笔非常小的钱)。

    更有效的方法是采用指数退避方法从队列中读取消息。查看 Maarten 的这篇文章,上面有一个简单的例子:http://www.developerfusion.com/article/120619/advanced-scenarios-with-windows-azure-queues/。将退避方法与基于队列深度的工作角色自动缩放相结合,您将获得一个较少依赖人工调整设置的解决方案。输入实例计数的最小值和最大值,根据您下次请求消息时出现的次数调整要提取的消息数量等。这里有很多选项可以减少您的参与并拥有一个高效的系统。

    此外,您可能会看到 Windows Azure 服务总线队列,因为它们实现了长轮询,因此在等待工作进入队列时会产生更少的事务。

    【讨论】:

    • 我实际上实现了这个,它造成的问题多于帮助。使用队列,我实现了具有某种预期延迟的迷你作业。不幸的是,通过回退轮询,我遇到了客户一次发送 30 个请求/迷你作业的情况,而我正在努力节省几美元/月,而这些请求被不必要的阈值延迟了。
    • 延迟只是您愿意等待处理消息的最长时间。如果那是 2 秒,则它不应等待超过 2 秒。系统应始终在处理完一条消息后立即检查是否有另一条消息,然后再开始回退。如果您一直在寻找即时响应,那么请保持紧密循环或查看队列以外的其他内容。我同意在某些情况下这可能是一分钱一分货,但是放入需要定期人工干预的东西也不好。这最终会花费更多。
    【解决方案2】:

    预先免责声明,我没有使用 RoleEnvironments。

    GetConfigurationSettingValue 的 MDSN 文档指出配置是从磁盘读取的。 http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.serviceruntime.roleenvironment.getconfigurationsettingvalue.aspx。所以经常调用肯定会很慢。

    MSDN 文档还显示设置更改时会触发一个事件。 http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.serviceruntime.roleenvironment.changed.aspx。您可以使用此事件仅在设置实际更改时重新加载设置。

    这是一种(未经测试,未编译)的方法。

    private TimeSpan mPollingInterval;
    private int mMessageGetLimit;
    
    public override void Run()
    {
        // Refresh the configuration members only when they change.
        RoleEnvironment.Changed += RoleEnvironmentChanged;
    
        // Initialize them for the first time
        RefreshRoleEnvironmentSettings();
    
        while (true)
        {
            var messages = queue.GetMessages(mMessageGetLimit);
    
            if (messages.Count() > 0)
            {
                ProcessQueueMessages(messages);
            }
            else
            {
                Task.Delay(mPollingInterval);
            }
        }
    }
    
    private void RoleEnvironmentChanged(object sender, RoleEnvironmentChangedEventArgs e)
    {
        RefreshRoleEnvironmentSettings();    
    }
    
    private void RefreshRoleEnvironmentSettings()
    {
        mPollingInterval = TimeSpan.FromSeconds(Convert.ToInt32(RoleEnvironment.GetConfigurationSettingValue("PollingIntervalSeconds")));
        mMessageGetLimit = Convert.ToInt32(RoleEnvironment.GetConfigurationSettingValue("MessageGetLimit"));
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-15
      • 2017-09-06
      • 2012-08-01
      • 2014-11-30
      • 2015-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多