分期或生产实例?

时间:2010-12-01 19:53:12

标签: azure azure-cloud-services

服务运行时中是否有任何地方可以告诉我当前是否正在运行'Staging'或'Production'?手动修改配置到生产和生产似乎有点麻烦。

6 个答案:

答案 0 :(得分:77)

如果您处于Prod或Staging状态,则不应该更改配置。暂存区域不是设计为“QA”环境,而是在部署生产之前仅设置保留区域。

当您上传新部署时,您上传软件包的当前部署插槽将被销毁,并且在上传和启动VM时会停机10-15分钟。如果您直接上传到生产中,则需要15分钟的生产停机时间。因此,发明了临时区域:您上传到临时,测试东西,然后单击“交换”按钮,您的临时环境神奇地变为生产(虚拟IP交换)。 因此,您的升级应该与您的生产完全相同。

我认为您正在寻找QA /测试环境?您应该使用自己的Prod / Staging为Testing环境打开一个新服务。在这种情况下,您需要维护多个配置文件集,每个部署环境一套(生产,测试等)

管理配置的方法有很多种,特别是对于拥有.config文件的Azure,它自己的* .cscfg文件。我喜欢用Azure项目做的方式如下: 设置一个小的Config项目,在那里创建与Deployment类型匹配的文件夹。在每个文件夹设置中设置* .config& * .cscfg文件与特定部署环境匹配:Debug,Test,Release ......这些文件也在Visual Studio中设置,作为构建目标类型。我有一个小的xcopy命令,在每次编译Config项目期间发生,它将Config项目的Build Target文件夹中的所有文件复制到Config项目的根文件夹中。

然后解决方案中的每个其他项目,从Config项目的根文件夹链接到.config或.cscfg文件。

Voila,我的配置自动地适应每个构建配置。我还使用.config转换来管理Release与非Release版本目标的调试信息。

如果您已阅读所有这些内容并且仍希望在运行时生产与暂存状态,则: 从deploymentId获取RoleEnvironment.DeploymentId 然后使用具有适当X509 certificate的Management API来获取Azure structure of your Service并调用GetDeployments方法(它是rest api但是有一个抽象库)。

希望这有帮助

编辑:博客文章根据要求设置配置字符串并在环境之间切换@ http://blog.paraleap.com/blog/post/Managing-environments-in-a-distributed-Azure-or-other-cloud-based-NET-solution

答案 1 :(得分:51)

有时我希望人们只回答这个问题......不解释道德规范或最佳实践......

Microsoft已在此处发布了一个代码示例:https://code.msdn.microsoft.com/windowsazure/CSAzureDeploymentSlot-1ce0e3b5

image showing Staging instance

image showing Production instance

protected void Page_Load(object sender, EventArgs e) 
{ 
    // You basic information of the Deployment of Azure application. 
    string deploymentId = RoleEnvironment.DeploymentId; 
    string subscriptionID = "<Your subscription ID>"; 
    string thrumbnail = "<Your certificate thumbnail print>"; 
    string hostedServiceName = "<Your hosted service name>"; 
    string productionString = string.Format(
        "https://management.core.windows.net/{0}/services/hostedservices/{1}/deploymentslots/{2}",
        subscriptionID, hostedServiceName, "Production"); 
    Uri requestUri = new Uri(productionString); 

    // Add client certificate. 
    X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine); 
    store.Open(OpenFlags.OpenExistingOnly); 
    X509Certificate2Collection collection = store.Certificates.Find(
        X509FindType.FindByThumbprint, thrumbnail, false); 
    store.Close(); 

    if (collection.Count != 0) 
    { 
        X509Certificate2 certificate = collection[0]; 
        HttpWebRequest httpRequest = (HttpWebRequest)HttpWebRequest.Create(requestUri); 
        httpRequest.ClientCertificates.Add(certificate); 
        httpRequest.Headers.Add("x-ms-version", "2011-10-01"); 
        httpRequest.KeepAlive = false; 
        HttpWebResponse httpResponse = httpRequest.GetResponse() as HttpWebResponse;

        // Get response stream from Management API. 
        Stream stream = httpResponse.GetResponseStream(); 
        string result = string.Empty; 
        using (StreamReader reader = new StreamReader(stream)) 
        { 
            result = reader.ReadToEnd();
        } 
        if (result == null || result.Trim() == string.Empty) 
        {
            return;
        }
        XDocument document = XDocument.Parse(result); 
        string serverID = string.Empty; 
        var list = from item
                   in document.Descendants(XName.Get("PrivateID",
                       "http://schemas.microsoft.com/windowsazure")) 
                   select item; 

        serverID = list.First().Value; 
        Response.Write("Check Production: "); 
        Response.Write("DeploymentID : " + deploymentId
            + " ServerID :" + serverID); 
        if (deploymentId.Equals(serverID)) 
            lbStatus.Text = "Production"; 
        else 
        { 
            // If the application not in Production slot, try to check Staging slot. 
            string stagingString = string.Format(
                "https://management.core.windows.net/{0}/services/hostedservices/{1}/deploymentslots/{2}",
                subscriptionID, hostedServiceName, "Staging"); 
            Uri stagingUri = new Uri(stagingString); 
            httpRequest = (HttpWebRequest)HttpWebRequest.Create(stagingUri); 
            httpRequest.ClientCertificates.Add(certificate); 
            httpRequest.Headers.Add("x-ms-version", "2011-10-01"); 
            httpRequest.KeepAlive = false; 
            httpResponse = httpRequest.GetResponse() as HttpWebResponse; 
            stream = httpResponse.GetResponseStream(); 
            result = string.Empty; 
            using (StreamReader reader = new StreamReader(stream)) 
            { 
                result = reader.ReadToEnd();
            } 
            if (result == null || result.Trim() == string.Empty) 
            {
                return;
            }
            document = XDocument.Parse(result); 
            serverID = string.Empty; 
            list = from item
                   in document.Descendants(XName.Get("PrivateID",
                       "http://schemas.microsoft.com/windowsazure")) 
                   select item; 

            serverID = list.First().Value; 
            Response.Write(" Check Staging:"); 
            Response.Write(" DeploymentID : " + deploymentId
                + " ServerID :" + serverID); 
            if (deploymentId.Equals(serverID)) 
            {
                lbStatus.Text = "Staging";
            }
            else 
            {
                lbStatus.Text = "Do not find this id";
            }
        } 
        httpResponse.Close(); 
        stream.Close(); 
    } 
}

答案 2 :(得分:8)

暂存是一个临时部署插槽,主要用于无停机升级和回滚升级的能力。

建议不要将您的系统(代码或配置中)与此类Azure特性结合使用。

答案 3 :(得分:5)

Windows Azure Management Libraries以来,感谢@GuaravMantri answer提出另一个问题,您可以这样做:

using System;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using Microsoft.Azure;
using Microsoft.WindowsAzure.Management.Compute;
using Microsoft.WindowsAzure.Management.Compute.Models;

namespace Configuration
{
    public class DeploymentSlotTypeHelper
    {
        static string subscriptionId = "<subscription-id>";
        static string managementCertContents = "<Base64 Encoded Management Certificate String from Publish Setting File>";// copy-paste it
        static string cloudServiceName = "<your cloud service name>"; // lowercase
        static string ns = "http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration";

        public DeploymentSlot GetSlotType()
        {
            var managementCertificate = new X509Certificate2(Convert.FromBase64String(managementCertContents));
            var credentials = new CertificateCloudCredentials(subscriptionId, managementCertificate);

            var computeManagementClient = new ComputeManagementClient(credentials);
            var response = computeManagementClient.HostedServices.GetDetailed(cloudServiceName);
            return response.Deployments.FirstOrDefault(d => d.DeploymentSlot == DeploymentSlot.Production) == null ? DeploymentSlot.Staging : DeploymentSlot.Production;
        }
    }
}

答案 4 :(得分:4)

解决此问题的一种简单方法是在您的实例中设置一个键,以确定它正在运行的环境。

1)设置在您的制作位置: 将其设置为&gt;&gt;应用程序设置&gt;&gt;应用设置 并创建一个名为SLOT_NAME的密钥,并创建&#34; production&#34;。重要信息:检查插槽设置。

2)设置在您的临时插槽中: 将其设置为&gt;&gt;应用程序设置&gt;&gt;应用设置 并创建一个名为SLOT_NAME的密钥,并将值&#34; staging&#34;。重要信息:检查插槽设置。

从应用程序访问变量并确定应用程序正在运行的环境。在Java中,您可以访问:

String slotName = System.getenv("APPSETTING_SLOT_NAME");

答案 5 :(得分:1)

这里有4点需要考虑

  1. 当您的服务面向外部世界时,VIP交换才有意义。 AKA,当它暴露API并对请求作出反应时。
  2. 如果您的所有服务都是从队列中提取消息并处理它们,那么您的服务是主动的,VIP交换对您来说不是一个好的解决方案。
  3. 如果您的服务既具有反应性又具有主动性,您可能需要重新考虑您的设计。也许将服务分成两种不同的服务。
  4. 如果您的服务的主动部分可以缩短停机时间,那么Eric建议在VIP交换之前和之后修改cscfg文件是好的(因为您首先将Staging和Production配置为不提取消息,然后执行VIP交换,然后更新Production的配置以开始提取消息)。