【问题标题】:How to speed up Azure deployment from Visual Studio 2010如何从 Visual Studio 2010 加速 Azure 部署
【发布时间】:2011-05-27 21:18:45
【问题描述】:

我有一个Visual Studio 2010 解决方案,其中一个Azure Service 和一个ASP.NET MVC 3 解决方案用作Azure 服务的Web Role。除此以外,没有其他角色附加到该服务。

从我在 Visual Studio 上单击发布的那一刻起,直到所有实例 (2) 启动为止,到 Azure 暂存(或生产)环境的每次部署最多需要 20 分钟才能完成。

您可以想象,这使它成为经常发布或快速修复一些错误的 PITA。有没有办法加快这个过程?将包上传到 de Blob 存储并从那里升级会更快吗?我将如何实现这一目标?

我觉得 Azure 上的在线文档还有很多不足之处。顺便说一下,尤其是在故障排除方面。

谢谢。

【问题讨论】:

    标签: visual-studio-2010 deployment azure


    【解决方案1】:

    大部分时间上传本身需要一分钟多一点的时间。这是占用大部分时间的实例的启动。

    您可以做的是首先将您的修复部署到 staging(请注意,这需要花钱,所以不要让它存在太久)。从登台切换到生产只需要几秒钟。因此,当您的应用程序仍在运行时,您可以上传已修补的版本,让您的测试人员在暂存时对其进行测试,当他们放弃时,只需将其切换到生产环境。

    我还没有通过首先上传到 blob 存储来测试您可能的替代方法。但我认为这是开销,因为它不会加快实例的启动速度。

    【讨论】:

    • 谢谢,这就是我目前的做法,而且确实 VIP 交换效果很好,而且速度很快,无需停机。但是让暂存部署运行起来非常缓慢,我无法想象没有更好的方法:)
    • 我自己刚从为期 2 天的 Microsoft 课程回来。专家也提到它太糟糕了。微软可能会在未来投资以加快这一进程。但要知道,云在普通硬件上运行以保持成本低廉和冗余。
    【解决方案2】:

    先尝试将项目上传到 blob 存储是个好主意,但不幸的是,无论如何,这正是 Visual Studio 在幕后为您所做的事情。正如其他地方所指出的那样,进行部署的大部分时间不是上传本身,而是所有更新域的停止和启动。

    如果您只是在开发环境中运行此站点,那么我所知道的加速它的唯一方法就是只运行一个实例。如果这是现场环境,那么……对不起,我认为你不走运。

    所以我不必部署到云来测试微小的更改,我发现很好的方法是对站点进行工程设计,使其在本地 IIS 中运行时就像任何其他 MVC 站点一样工作。

    这项工作的最大障碍是您在云配置中的设置。我们解决这个问题的方法是复制云配置中的所有设置,并将它们放在 appSettings 中的 web.config 中。然后,不要使用RoleEnvironment.GetConfigurationSettingValue(),而是创建一个您调用的包装类。这个包装类检查RoleEnvironment.IsAvailable 看它是否在Azure Fabric 中运行,如果是,它调用上面通常的配置函数,如果不是,它调用WebConfigurationManager.AppSettings[]

    围绕获取配置设置更改事件,您还需要做一些其他事情,希望您可以从下面的代码中弄清楚:

    public class SmartConfigurationManager
    {
        private static bool _addConfigChangeEvents;
        private static string _configName;
    
        private static Func<string, bool> _configSetter;
    
        public static bool AddConfigChangeEvents
        {
            get { return _addConfigChangeEvents; }
            set
            {
                _addConfigChangeEvents = value;
    
                if (value)
                {
                    RoleEnvironment.Changing += RoleEnvironmentChanging;
                }
                else
                {
                    RoleEnvironment.Changing -= RoleEnvironmentChanging;
                }
            }
        }
    
        public static string Setting(string configName)
        {
            if (RoleEnvironment.IsAvailable)
            {
                return RoleEnvironment.GetConfigurationSettingValue(configName);
            }
            return WebConfigurationManager.AppSettings[configName];
        }
    
        public static Action<string, Func<string, bool>> GetConfigurationSettingPublisher()
        {
            if (RoleEnvironment.IsAvailable)
            {
                return AzureSettingsGet;
            }
            return WebAppSettingsGet;
        }
    
        public static void WebAppSettingsGet(string configName, Func<string, bool> configSetter)
        {
            configSetter(WebConfigurationManager.AppSettings[configName]);
        }
    
        public static void AzureSettingsGet(string configName, Func<string, bool> configSetter)
        {
            // We have to store these to be used in the RoleEnvironment Changed handler
            _configName = configName;
            _configSetter = configSetter;
    
            // Provide the configSetter with the initial value
            configSetter(RoleEnvironment.GetConfigurationSettingValue(configName));
    
            if (AddConfigChangeEvents)
            {
                RoleEnvironment.Changed += RoleEnvironmentChanged;
            }
        }
    
    
        private static void RoleEnvironmentChanged(object anotherSender, RoleEnvironmentChangedEventArgs arg)
        {
    
            if ((arg.Changes.OfType<RoleEnvironmentConfigurationSettingChange>().Any(change => change.ConfigurationSettingName == _configName)))
            {
                if ((_configSetter(RoleEnvironment.GetConfigurationSettingValue(_configName))))
                {
                    RoleEnvironment.RequestRecycle();
                }
            }
        }
    
    
        private static void RoleEnvironmentChanging(object sender, RoleEnvironmentChangingEventArgs e)
        {
            // If a configuration setting is changing
            if ((e.Changes.Any(change => change is RoleEnvironmentConfigurationSettingChange)))
            {
                // Set e.Cancel to true to restart this role instance
                e.Cancel = true;
            }
        }
    }
    

    【讨论】:

    • 嗨 knightpfhor,感谢您的回答。我可能在这里错过了您的答案,但要检查是否有小的更改(css、javascript、buigfixes 等)我可以将 MVC 项目设置为启动项目并查看是否一切正常。当我确定我的更改有效并且真的想将它们放到云端时,我的问题就来了! :)
    • 是的,你是对的。但有时网站会与云配置中的内容捆绑在一起,因此这可能会阻止您仅在本地运行它。我的回答解决了这个问题。由于我已经停止使用开发存储,我很难考虑发生在云中的问题,这不是本地发生的,与配置无关。我还扩展了对我的问题的介绍,希望能解决您的特定问题。
    【解决方案3】:

    减少重新部署需求(和频率)的一个想法是将静态内容移动到包外部的 blob 存储中。例如,将您的 css 和 javascript 连同图像一起移动到 blob 存储。完成此操作后,您只需为 .NET 代码更改重新编译/重新部署。您可以随时将更新的 CSS 上传到 Blob 存储。如果您想先在 staging 中进行测试,您总是可以为静态内容设置一个 staging 与 production 容器名称,并将该容器名称存储在配置设置中。

    当您确实需要重新部署时,这不会改变部署时间,但至少您可以减少执行该过程的频率...

    【讨论】:

    • 我开始越来越喜欢你的方法了。但是有一个问题:然后您是否将所有 js 文件、图像等与 de 项目(即在 VS 中)分开,或者只是将它们配置为不属于已发布包的一部分?
    • 我决定采用这个答案,因为当最终接受完全部署无论如何都是一个缓慢的过程时,这似乎是最实用的。
    【解决方案4】:

    我对此问题的解决方案是仅在我更改 RoleEntryPoint 中的代码或使用服务定义时推送一个新包。在 Azure 1.3 中,您现在可以使用远程桌面连接。使用 RDC,我将在本地编译我的代码并使用复制/粘贴将其放置在 Azure 服务器上的相应目录中。一旦生产代码正确运行,我就可以将经过全面测试的版本推送到暂存,然后进行 VIP 交换。这限制了我实际必须部署包的次数。

    实际上,您有一个相当长的窗口,您可以在其中不断修改 Azure 中的代码,然后才能发布新包。只有在 Azure 必须关闭/重新启动您的角色实例的情况下才真正需要新包。

    【讨论】:

    • 感谢您的回答,我升级到了 Azure 1.3,但不知何故我错过了。我会尝试RDP,谢谢。 :)
    • 在进行性能调整、上传和检查性能时,使用 RDP 并复制/粘贴 .dll 文件为我节省了大量时间。巨大的。谢谢。
    • 如果您重新启动该辅助角色,您的更改是否会丢失?此外,我很确定您将无法扩大规模,因为新的工作人员角色不会有您的更改
    【解决方案5】:

    您应该在您的 Azure 项目中启用 Web 部署。它是这样工作的:

    1/ 创建一个 RDP 帐户(不要忘记,您需要上传带有其私钥的证书,以便 Azure 可以破译密码)。这隐藏在 Azure 部署项目的“部署”对话框中。

    2/ 启用 Web 部署 - 同一个地方

    以这种方式发布应用程序后,右键单击 Web 应用程序(不是 azure 部署项目)并选择发布。弹出窗口已定义除密码之外的所有内容,也可以输入密码,您将在几秒钟内将更改上传到 Azure。

    CAVEAT :这适用于单实例 Web 应用程序,绝对不是生产升级策略的方式,并且已经提到的 Blob 存储答案是这种情况下的最佳选择。

    皮埃尔

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多