分段或生产实例?
服务运行时是否有任何地方可以告诉我目前是运行在“分段”还是“生产”? 手动修改生产configuration似乎有点麻烦。
如果您使用Prod或Staging,则基本上不应更改configuration。 暂存区域并非devise为“QA”环境,而是在生产部署之前只有一个控制区域。
当你上传一个新的部署时,你上传你的包的当前部署位置将被销毁,并在上传和启动虚拟机的过程中停止10-15分钟。 如果直接上传到生产环境,那就是15分钟的生产停机时间。 因此,Staging区域被发明了:您上传到舞台,testing东西,然后点击“Swap”button,您的Staging环境神奇地变成了Production(虚拟IP交换)。 因此,你的舞台应该和你的制作完全一样。
我认为你正在寻找的是QA /testing环境? 您应该为自己的Prod / Staging开发一个testing环境的新服务。 在这种情况下,您将需要维护多个configuration文件集,每个部署环境(生产,testing等)
有很多方法可以pipe理configuration – 发生的地狱,尤其是在configuration.config文件,自己的* .cscfg文件之上的Azure。 我更喜欢使用Azure项目的方式如下:设置一个小的Config项目,在那里创build与部署types相匹配的文件夹。 在每个文件夹内部设置与特定部署环境相匹配的* .config&* .cscfg文件集:Debug,Test,Release …这些在Visual Studio中也被设置为构build目标types。 我有一个小的xcopy命令,在Config项目的每次编译过程中都会发生,它将Config项目的Build Target文件夹中的所有文件复制到Config项目的根文件夹中。
然后在解决scheme的其他项目中,从Config项目的根文件夹链接到.config或.cscfg文件。
瞧,我的configuration自动适应每一个构buildconfiguration。 我还使用.config转换来pipe理Release和Non-Release构build目标的debugging信息。
如果您已经阅读了所有这些内容,并且仍然希望在运行时获得生产与暂存状态 ,那么:从RoleEnvironment.DeploymentId
获取deploymentId
然后使用具有适当X509 certificate
Management API来获取Azure structure of your Service
的Azure structure of your Service
并调用GetDeployments
方法(这是restAPI,但有一个抽象库)。
希望这可以帮助
编辑:按照要求提供关于configurationstring的设置和环境之间切换的博客文章@ http://www.paraleap.com/blog/post/Managing-Environments-in-a-distributed-Azure-or-other-cloud-based -NET-solution.aspx
有时我希望人们回答这个问题,而不是解释道德或最佳实践。
微软已经发布了一个代码示例在这里做到这一点: https : //code.msdn.microsoft.com/windowsazure/CSAzureDeploymentSlot-1ce0e3b5
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(); } }
分段是临时部署插槽,主要用于无宕机升级和回滚升级的能力。
build议不要将系统(无论是在代码中还是在configuration中)与这些Azure特性相结合。
从Windows Azurepipe理库和感谢@GuaravMantri 回答另一个问题,你可以这样做:
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; } } }
解决这个问题的一个简单的方法是在你的实例中设置一个键来标识它正在运行的环境。
1)在您的生产插槽中进行设置:设置设置>>应用程序设置>>应用程序设置然后创build一个名为SLOT_NAME的键并将值设置为“生产”。 重要:检查插槽设置。
2)在您的临时插槽中设置:设置设置>>应用程序设置>>应用程序设置然后创build一个名为“SLOT_NAME”的键并将其值设为“分段”。 重要:检查插槽设置。
从应用程序访问variables并确定应用程序正在运行的环境。 在Java中,您可以访问:
String slotName = System.getenv("APPSETTING_SLOT_NAME");
这里有4点要考虑
- 当您的服务面向外部世界时,VIP交换才有意义。 AKA,当它暴露一个API并对请求作出反应。
- 如果你所有的服务都是从队列中提取消息并处理它们,那么你的服务是主动的,VIP交换不是一个好的解决scheme。
- 如果您的服务是被动和主动的,您可能需要重新考虑您的devise。 也许把这个服务分成两个不同的服务。
- 如果您的服务的主动部分可能需要很短的停机时间,那么Ericbuild议修改cscfg文件的前后VIP交换是很好的(因为您首先configuration暂存和生产不提取消息,然后执行VIP交换,然后更新Production的configuration以开始拉取消息)。