获取群集性能历史记录

适用于:Azure Stack HCI 版本 23H2 和 22H2;Windows Server 2022、Windows Server 2019

运行状况服务减少了从存储空间直通群集获取实时性能和容量信息所需的工作量。 有一个 cmdlet 可以提供基本指标的特选列表,这些指标是通过内置逻辑从各个节点有效收集并动态聚合的,可用于检测群集成员身份。 所有值均仅是实时和时间点形式的。

PowerShell 中的用法

使用以下 cmdlet 获取整个存储空间直通群集的指标:

Get-ClusterPerformanceHistory

提示

使用 Get-ClusterPerf 别名保存一些击键事件。

还可以获取一个特定卷或服务器的指标:

Get-Volume -FileSystemLabel <Label> | Get-ClusterPerformanceHistory

Get-StorageNode -Name <Name> | Get-ClusterPerformanceHistory

.NET 和 C# 中的用法

本部分介绍如何连接到运行状况服务,使用“发现对象”并实现观察器以开始流式传输指标。

连接

为了查询运行状况服务,你需与群集建立一个 CimSession。 为此,需要使用一些仅在完整版 Microsoft .NET 中提供的内容,这意味着,你无法直接从 Web 或移动应用轻松执行此操作。 本部分中的代码示例使用 C#,这是此数据访问层的最直接的选择。

using System.Security;
using Microsoft.Management.Infrastructure;

public CimSession Connect(string Domain = "...", string Computer = "...", string Username = "...", string Password = "...")
{
    SecureString PasswordSecureString = new SecureString();
    foreach (char c in Password)
    {
        PasswordSecureString.AppendChar(c);
    }

    CimCredential Credentials = new CimCredential(
        PasswordAuthenticationMechanism.Default, Domain, Username, PasswordSecureString);
    WSManSessionOptions SessionOptions = new WSManSessionOptions();
    SessionOptions.AddDestinationCredentials(Credentials);
    Session = CimSession.Create(Computer, SessionOptions);
    return Session;
}

提供的用户名应为目标计算机的本地管理员。

建议直接根据用户输入实时构造 Password SecureString,这样密码就永远不会以明文方式存储在内存中。 这有助于缓解各种安全问题。 但在实践中,按如上所述构造它对于原型制作来说很常见。

发现对象

建立 CimSession 后,可查询群集上的 Windows Management Instrumentation (WMI)。

在获取故障或指标之前,需要获取多个相关对象的实例。 首先,获取表示群集上的存储空间直通的 MSFT_StorageSubSystem。 使用它可以获取群集中的每个 MSFT_StorageNode 和数据卷的每个 MSFT_Volume。 最后,需要获取 MSCluster_ClusterHealthService,即运行状况服务本身。

CimInstance Cluster;
List<CimInstance> Nodes;
List<CimInstance> Volumes;
CimInstance HealthService;

public void DiscoverObjects(CimSession Session)
{
    // Get MSFT_StorageSubSystem for Storage Spaces Direct
    Cluster = Session.QueryInstances(@"root\microsoft\windows\storage", "WQL", "SELECT * FROM MSFT_StorageSubSystem")
        .First(Instance => (Instance.CimInstanceProperties["FriendlyName"].Value.ToString()).Contains("Cluster"));

    // Get MSFT_StorageNode for each cluster node
    Nodes = Session.EnumerateAssociatedInstances(Cluster.CimSystemProperties.Namespace,
        Cluster, "MSFT_StorageSubSystemToStorageNode", null, "StorageSubSystem", "StorageNode").ToList();

    // Get MSFT_Volumes for each data volume
    Volumes = Session.EnumerateAssociatedInstances(Cluster.CimSystemProperties.Namespace,
        Cluster, "MSFT_StorageSubSystemToVolume", null, "StorageSubSystem", "Volume").ToList();

    // Get MSCluster_ClusterHealthService itself
    HealthService = session.QueryInstances(@"root\MSCluster", "WQL", "SELECT * FROM MSCluster_ClusterHealthService").First();
}

这些是你在 PowerShell 中使用 cmdlet(如 Get-StorageSubSystem、Get-StorageNode 和 Get-Volume)得到的相同对象。

你可以访问记录在存储管理 API 类中的所有相同属性。

using System.Diagnostics;

foreach (CimInstance Node in Nodes)
{
    // For illustration, write each node's Name to the console. You could also write State (up/down), or anything else!
    Debug.WriteLine("Discovered Node " + Node.CimInstanceProperties["Name"].Value.ToString());
}

调用 GetMetric,以根据 MetricName 参数中提供的指标名称开始流式传输基本指标的专家特选列表的样本,这些指标是通过内置逻辑从各个节点有效收集并动态聚合的,可用于检测群集成员身份 。 样本根据 StreamName 参数中提供的时间范围抵达。

有关可用指标的完整列表,请参阅存储空间直通的性能历史记录

IObserver.OnNext()

此示例代码使用观察器设计模式来实现一个观察器,当每个新的指标样本抵达时,会调用该观察器的 OnNext() 方法。 流式传输结束时,将调用该观察器的 OnCompleted() 方法。 例如,可以使用它来重新启动流式传输,使流式传输无限期继续。

class MetricsObserver<T> : IObserver<T>
{
    public void OnNext(T Result)
    {
        // Cast
        CimMethodStreamedResult StreamedResult = Result as CimMethodStreamedResult;

        if (StreamedResult != null)
        {
            CimInstance Metric = (CimInstance)StreamedResult.ItemValue;
            Console.WriteLine("MetricName: " + Metric.CimInstanceProperties["MetricId"].Value);
            IEnumerable<CimInstance> Records = (IEnumerable<CimInstance>)Metric.CimInstanceProperties["Records"].Value;

            foreach (CimInstance Record in Records)
            {
                // Each Record has "TimeStamp" and "Value. For Illustration, just print the metric"
                Console.WriteLine(record.CimInstanceProperties["TimeStamp"] + ": " + record.CimInstanceProperties["Value"]);

            }

            // TODO: Whatever you want!
        }
    }
    public void OnError(Exception e)
    {
        // Handle Exceptions
    }
    public void OnCompleted()
    {
        // Reinvoke BeginStreamingMetrics(), defined in the next section
    }
}

开始流式传输

定义观察器后,可以开始流式传输。

指定要将指标范围限定到的目标 CimInstance。 它可以是群集、任一节点或任一卷。

count 参数是流式传输结束前的样本数。

CimInstance Target = Cluster; // From among the objects discovered in DiscoverObjects()

public void BeginStreamingMetrics(CimSession Session, CimInstance HealthService, CimInstance Target)
{
    // Set Parameters
    CimMethodParametersCollection MetricsParams = new CimMethodParametersCollection();
    string[] metricNames = new string[] { "ClusterNode.Cpu.Usage,ClusterNode=RRN44-13-01", "ClusterNode.Cpu.Usage.Host,ClusterNode=RRN44-13-01" };
    MetricsParams.Add(CimMethodParameter.Create("MetricName", metricNames, CimType.StringArray, CimFlags.In));
    MetricsParams.Add(CimMethodParameter.Create("StreamName", "LastHour", CimType.String, CimFlags.In));

    // Enable WMI Streaming
    CimOperationOptions Options = new CimOperationOptions();
    Options.EnableMethodResultStreaming = true;
    // Invoke API
    CimAsyncMultipleResults<CimMethodResultBase> InvokeHandler;
    InvokeHandler = Session.InvokeMethodAsync(
        HealthService.CimSystemProperties.Namespace, HealthService, "GetMetric", MetricsParams, Options
        );
    // Subscribe the Observer
    MetricsObserver<CimMethodResultBase> Observer = new MetricsObserver<CimMethodResultBase>(this);
    IDisposable Disposeable = InvokeHandler.Subscribe(Observer);
}

可以可视化这些指标,将其存储在数据库中,或者以你认为合适的任何方式使用它们。

其他参考