上一篇博文介紹瞭如何鏈接Windows Azure: http://www.cnblogs.com/teld/p/5113063.htmlhtml
本篇咱們繼續上次的示例代碼,獲取虛擬機的監控定義和監控數據。windows
有人會問,Azure Portal上已經有了監控數據,經過代碼獲取有意思嗎?咱們計劃基於性能計數器的監控數據來實現應用的自動伸縮,所以能夠獲取到監控指標定義和監控數據應該是第一步。api
在Azure的管理Portal中咱們能夠看到虛擬機的監控數據,目前,提供的主要有如下監控指標:app
CPU Percentage;Disk Read; Disk Write; Network in;NetWork Out。函數
Azure中監控的Nuget主要是這個:Microsoft Azure Management Libraries性能
核心的幾個namespace有:測試
咱們本篇用的是Metric這個命名空間,核心類MetricClient:ui
namespace AzureTest { using Microsoft.WindowsAzure; using Microsoft.WindowsAzure.Management.Monitoring.Metrics; using Microsoft.WindowsAzure.Management.Monitoring.Metrics.Models; using Microsoft.WindowsAzure.Management.Monitoring.Utilities; /// <summary> /// 監控客戶端 /// </summary> class MonitorClient { private SubscriptionCloudCredentials credentials; public MonitorClient(SubscriptionCloudCredentials credentials) { this.credentials = credentials; } /// <summary> /// 獲取全部的監控指標 /// </summary> public void GetMetricDefinitions() { var metricsClient = new MetricsClient(credentials); // Build the resource ID string. var resourceId = ResourceIdBuilder.BuildVirtualMachineResourceId("cloudServiceName", "deploymentName"); Console.WriteLine("Resource Id: {0}", resourceId); //Get the metric definitions. var metricListResponse= metricsClient.MetricDefinitions.List(resourceId, null, null);34 MetricDefinitionCollection metricDefinitions = metricListResponse.MetricDefinitionCollection; // Display the metric definitions. int count = 0; foreach (MetricDefinition metricDefinition in metricDefinitions.Value) { Console.WriteLine("MetricDefinitio: " + count++); Console.WriteLine("Display Name: " + metricDefinition.DisplayName); Console.WriteLine("Metric Name: " + metricDefinition.Name); Console.WriteLine("Metric Namespace: " + metricDefinition.Namespace); Console.WriteLine("Is Altertable: " + metricDefinition.IsAlertable); Console.WriteLine("Min. Altertable Time Window: " + metricDefinition.MinimumAlertableTimeWindow); Console.WriteLine(); } } } }
使用上一篇咱們的Azure 憑據驗證器,獲取一個令牌憑據TokenCloudCredentials,而後構造一個MonitorClient,獲取指定虛擬機的監控數據。this
static void Main(string[] args) { var credential = Authorizator.GetCredentials(); var client = new MonitorClient(credential); client.GetMetricDefinitions(); Console.ReadLine(); }
第一塊代碼中:spa
var resourceId = ResourceIdBuilder.BuildVirtualMachineResourceId("cloudServiceName", "deploymentName");
這個地方通ResourceIDBuilder獲取虛擬機的資源ID,對應的參數分別爲:cloudServiceName和deploymentName,第一個是虛擬機使用的雲服務名稱,第二個是虛擬機名稱便可。
Run...
出錯了:
{"ForbiddenError: The server failed to authenticate the request. Verify that the certificate is valid and is associated with this subscription."}
一番Google後未果,咋整,再分析下錯誤信息:
能夠看到,請求的Uri:
{https://management.core.windows.net/37*****-5107-*****-*******6/services/monitoring/metricdefinitions/query?&resourceId=%2Fhostedservices%2Fteldptapp%2Fdeployments%2Fteldptapp}
請求又跑到Azure Global那去了。
這個錯誤困擾了很久,還在StackOverflow上發了英文諮詢貼,不知道洋人們如何回答了。在此多謝鞠強老大的指導,想辦法將請求的Uri定位到中國區的Azure。
從新分析了代碼,找到了Monitor的構造函數中,能夠指定Uri,將中國區Azure的Uri指定一下:https://management.core.chinacloudapi.cn
MetricsClient metricsClient = new MetricsClient(credentials, new Uri("https://management.core.chinacloudapi.cn/"));
測試經過,ok。
獲取到了監控指標定義,接下來咱們獲取監控數據:
namespace AzureTest { using Microsoft.WindowsAzure; using Microsoft.WindowsAzure.Management.Monitoring.Metrics; using Microsoft.WindowsAzure.Management.Monitoring.Metrics.Models; using Microsoft.WindowsAzure.Management.Monitoring.Utilities; /// <summary> /// 監控客戶端 /// </summary> class MonitorClient { private SubscriptionCloudCredentials credentials; public MonitorClient(SubscriptionCloudCredentials credentials) { this.credentials = credentials; } /// <summary> /// 獲取全部的監控指標數據 /// </summary> public void GetMetricData() { var metricsClient = new MetricsClient(credentials, new Uri("https://management.core.chinacloudapi.cn/")); // Build the resource ID string. var resourceId = ResourceIdBuilder.BuildVirtualMachineResourceId("cloudServiceName", "deploymentName"); Console.WriteLine("Resource Id: {0}", resourceId); //Get the metric definitions. var metricListResponse = metricsClient.MetricDefinitions.List(resourceId, null, null); MetricDefinitionCollection metricDefinitions = metricListResponse.MetricDefinitionCollection; var metricNamespace = ""; var metricNames = new List<string>(); // Display the metric definitions. int count = 0; foreach (MetricDefinition metricDefinition in metricDefinitions.Value) { Console.WriteLine("MetricDefinitio: " + count++); Console.WriteLine("Display Name: " + metricDefinition.DisplayName); Console.WriteLine("Metric Name: " + metricDefinition.Name); if (!metricNames.Contains(metricDefinition.Name)) metricNames.Add(metricDefinition.Name); Console.WriteLine("Metric Namespace: " + metricDefinition.Namespace); metricNamespace = metricDefinition.Namespace; Console.WriteLine("Is Altertable: " + metricDefinition.IsAlertable); Console.WriteLine("Min. Altertable Time Window: " + metricDefinition.MinimumAlertableTimeWindow); Console.WriteLine(); } // timeGrain must be 5, 60 or 720 minutes. TimeSpan timeGrain = TimeSpan.FromMinutes(5); DateTime startTime = DateTime.UtcNow.AddHours(-1); DateTime endTime = DateTime.UtcNow; MetricValueListResponse response = metricsClient.MetricValues.List(resourceId, metricNames, metricNamespace, timeGrain, startTime, endTime); foreach (MetricValueSet value in response.MetricValueSetCollection.Value) { String valueName = value.Name; Console.WriteLine("MetricValue:{0}", valueName); foreach (MetricValue metricValue in value.MetricValues) { Console.WriteLine("Maximum:{0}{1}", metricValue.Maximum, value.Unit); Console.WriteLine("Average:{0}{1}", metricValue.Average, value.Unit); Console.WriteLine("Minimum:{0}{1}", metricValue.Minimum, value.Unit); } } } } }
Run...
程序在metricsClient.MetricValues.List(resourceId, metricNames, metricNamespace, timeGrain, startTime, endTime);
出錯了:
Additional information: <string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">{"Code":"InvalidRequest","Message":"Could not retrieve metrics."}</string>
爲啥不能獲取監控指標呢?
這個錯誤,Google一番依舊未果,諮詢了微軟的技術工程師,給了以下指導,resouceID必須執行RoleName:
var resourceId = ResourceIdBuilder.BuildVirtualMachineResourceId("cloudService", "deploymentName", "roleName");
修改以後,問題解決。
至此,咱們已經能夠獲取到監控指標和監控數據,下一步咱們要獲取自定義的性能計數器,基於自定義的性能計數器來實現自動伸縮。
周國慶
2016/3