如何加速Visual Studio 2010中的Azure部署

时间:2010-12-19 15:40:44

标签: visual-studio-2010 deployment azure

我的Visual Studio 2010解决方案包含Azure ServiceASP.NET MVC 3解决方案,用作Azure服务的Web Role。除此之外,没有任何其他角色附加到服务上。

每次部署到Azure分段(或生产,就此而言)环境都需要20分钟才能完成,从我在Visual Studio上单击发布直到所有实例(2)都启动为止。

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

我觉得Azure上的在线文档还有很多不足之处。特别是在顺便排除故障时。

感谢。

5 个答案:

答案 0 :(得分:7)

减少重新部署的需求(和频率)的一个想法是将静态内容移动到包外部的blob存储中。例如,将您的css和javascript移动到blob存储,以及图像。完成此操作后,您只需重新编译/重新部署.NET代码更改。您可以随时将更新的css上传到blob存储。如果要首先在暂存中测试它,您可以始终拥有静态内容的暂存与生产容器名称,并将该容器名称存储在配置设置中。

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

答案 1 :(得分:4)

您应该在Azure项目中启用Web Deploy。它的工作原理如下:

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

2 /启用Web部署 - 同一地点

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

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

皮尔

答案 2 :(得分:3)

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

您实际上有一个很长的窗口,您可以在必须发布新程序包之前继续在Azure中修改代码。只有在Azure必须关闭/重新启动角色实例的情况下才真正需要新的包。

答案 3 :(得分:1)

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

如果您只是在开发环境中运行此站点,那么我知道加速它的唯一方法是只运行一个实例。如果这是现场环境,那么......对不起,我觉得你运气不好。

因此,我没有必要部署到云来测试微小的变化,我发现很有效的方法是设计网站,以便它在本地IIS中运行时就像任何其他MVC网站一样。< / p>

此工作的最大障碍是您在云配置中拥有的设置。我们解决这个问题的方法是复制云配置中的所有设置,并将它们放在appSettings中的web.config中。然后,而不是使用RoleEnvironment.GetConfigurationSettingValue()创建一个您调用的包装类。此包装器类检查RoleEnvironment.IsAvailable以查看它是否在Azure结构中运行,如果是,则调用上面的常用配置函数,如果没有,则调用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;
        }
    }
}

答案 4 :(得分:0)

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

您可以做的是首先将修复程序部署到暂存(注意它需要花钱,所以不要让它存在太长时间)。从分段交换到生产只需要几秒钟。因此,当您的应用程序仍在运行时,您可以上传修补版本,让测试人员在升级时测试它,当他们放弃时,然后将其交换到生产。

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