上一篇博文介紹瞭如何連線Windows Azure: http://www.cnblogs.com/teld/p/5113063.html

本篇我們繼續上次的示例程式碼,獲取虛擬機器的監控定義和監控資料。

有人會問,Azure Portal上已經有了監控資料,通過程式碼獲取有意思嗎?我們計劃基於效能計數器的監控資料來實現應用的自動伸縮,因此可以獲取到監控指標定義和監控資料應該是第一步。

在Azure的管理Portal中我們可以看到虛擬機器的監控資料,目前,提供的主要有以下監控指標:

CPU Percentage;Disk Read; Disk Write; Network in;NetWork Out。

Azure中監控的Nuget主要是這個:Microsoft Azure Management Libraries

核心的幾個namespace有:

我們本篇用的是Metric這個名稱空間,核心類MetricClient:

 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);
MetricDefinitionCollection metricDefinitions = metricListResponse.MetricDefinitionCollection;
// Display the metric definitions.
int count = ;
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,獲取指定虛擬機器的監控資料。

static void Main(string[] args)
{
var credential = Authorizator.GetCredentials();
var client = new MonitorClient(credential);
client.GetMetricDefinitions();
Console.ReadLine();
}

第一塊程式碼中:

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 = ;
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();
DateTime startTime = DateTime.UtcNow.AddHours(-);
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");

修改之後,問題解決。

至此,我們已經可以獲取到監控指標和監控資料,下一步我們要獲取自定義的效能計數器,基於自定義的效能計數器來實現自動伸縮。

周國慶