【问题标题】:Identify the associated w3wp process for a web role instance识别 Web 角色实例的关联 w3wp 进程
【发布时间】:2012-11-22 10:45:14
【问题描述】:

我正在监控 Azure 服务的性能。

目前有两个 Web 角色实例(用于同一网站)正在运行 - 每个都有自己的 W3WP.exe(w3wp 和 w3wp#1)

如何找出哪个 w3wp 进程属于哪个角色实例?

有了这些信息,我想为 azure.diagnostics.monitor 提供一些性能计数器 - 即 Process(w3wp)\ProcessorTime (%) 和 Thread Count。 但为了获得任何有意义的数据,我必须将 w3wp 进程的进程 ID 附加到性能计数器(例如 Process(w3wp_PID)\processorTime(%)) - 不知道语法是否正确,但有一种方法可以附加PID)

因此 AzureStorage 表 WADPerformanceCounters 中的最终结果只有以下条目:

WebRoleInstance_n_0 | process(w3wp_1033)\processorTime (%) |  12.4
WebRoleInstance_n_1 | process(w3wp_1055)\processorTime (%) |  48.4

自动取款机

WebRoleInstance_n_0 | process(w3wp)\processorTime (%) |  12.4
WebRoleInstance_n_1 | process(w3wp)\processorTime (%) |  12.4

我想:如果我为每个角色启动一个 DiagnosticsMonitor,那么监视器将使用正确的进程 - 属于启动监视器的角色实例。但实际上这不起作用 - 或者我认为它不起作用 - 至少在查看结果值之后。

//更新:在 manage.windowsazure 门户上,您可以为性能监控定义自定义指标。此处可以选择要独占监控的 webrole 实例。 这也是我想做的。了解此页面的实际作用也可能有所帮助。

比较: http://puu.sh/1xp7q

我能想到的获取此信息的唯一愚蠢方法是: 在每个 w3wp 启动之前和之后获取所有进程的列表 - 确定添加了哪个进程,然后根据代码库上下文决定哪个角色实例刚刚启动。

【问题讨论】:

    标签: azure azure-web-roles multiple-instances w3wp performance-monitor


    【解决方案1】:

    我得到了它的工作 - 尽管它不是很直接。

    首先我必须对我之前的陈述进行一些更正 - 只是为了保持在同一水平上。

    在云服务中有多个虚拟机,每个虚拟机托管一个 WebRole 实例或一个 WorkerRole 实例。 因此,在单个 VM 上,只有一个 w3wp 运行,或者根本没有 w3wp,只有一个 waworkerhost 进程。

    在我的特殊情况下,可以在单个 VM 上运行两个 w3wp。所以我需要区分这两者 - 因此要求我进行某种流程-实例关联。

    我想记录的是:单个 VM 的总 CPU 负载,VM 上运行的实例进程的 CPU 负载(w3wp,waworkerhost)。

    对于每个 VM,总 CPU 负载的 PerformanceCounter 简单且相等:\Processor(_Total)\% Processortime 对于 webrole 虚拟机,我不能只使用 \process(w3wp)\% 处理器时间计数器,因为我不能确定它是否正确 w3wp(见上文)

    现在这是我所做的: 由于您必须为 WebRole.cs 或 WorkerRole.cs 中的每个角色实例 OnStart() 启动性能计数器监视器,我认为这是我可以以某种方式收集所需信息的唯一地方。

    在 WorkerRole.cs 中我做了:

    int pc = Environment.ProcessorCount;
            string instance = RoleEnvironment.CurrentRoleInstance.Id;
    
            SomeOtherManagementClass.StartDiagnosticMonitorService(pc, instance, Process.GetCurrentProcess());
    

    在 WebRole.cs 中 CurrentProcess 也返回 WaWorkerHost,所以我不得不将上面的代码行移动到 WebRole 的 global.asax 中。此处提供了正确的流程。

    在 SomeOtherManagementClass 我放了 StartDiagnosticsMonitorService ,它现在接收调用 StartDiagnosticsMonitorService 的 CurrentProcess。 (从 workerrole.cs 它将接收 WaWorkerHost 进程并从 WebRoles 接收 w3wp 进程 - 包括 PID)

    public static void StartDiagnosticMonitorService(int coreCount, string currentRole, Process process)
        {
            string processName = GetProcessInstanceName(process.Id);
            SetCPUCoreData(coreCount, currentRole, processName, process.Id);
             ...
        instanceProcessLoadCounterName = String.Format(@"\Process({0})\% Processor Time", processName);
        }
    

    现在在每个 VM 上调用 GetProcessInstanceName(process.Id) 并将 processName 获取到提供的 process.Id - 这允许您区分单个 VM 上的多个 w3wps,因为返回的 instanceNames 是 w3wp、w3wp#1 , w3wp#2 等与GetCurrentProcess提供的processName相反,它总是w3wp。为此,我修改了我在 stackoverflow 上找到的代码示例 - 你可以在下面找到它:

    private static string GetProcessInstanceName(int pid)
        {
            PerformanceCounterCategory cat = new PerformanceCounterCategory("Process");
    
            string[] instances = cat.GetInstanceNames();
            foreach (string instance in instances)
            {
                try
                {
                    using (PerformanceCounter cnt = new PerformanceCounter("Process",
                     "ID Process", instance, true))
                    {
                        int val = (int)cnt.RawValue;
                        if (val == pid)
                        {
                            return instance;
                        }
                    }
                }
                catch (InvalidOperationException)
                {
                    //this point is reached when a process terminates while iterating the processlist- this it cannot be found
                }
            }
            return "";
        }
    

    最后但同样重要的是:SetCPUCoreData(coreCount, currentRole, processName, process.Id) 将进程的所有相关数据保存到 azure 存储中,以便在应用程序的任何地方都可以使用:

    private static void SetCPUCoreData(int count, string roleinstance, string processName, int processID)
        {
            string[] instances = roleinstance.Split('.');
            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(GetSettingValue("LoadMonitor.Connection.String"));
            CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient();
            const string tableName = "PerformanceMonitorCoreCount";
            cloudTableClient.CreateTableIfNotExist(tableName);
            TableServiceContext serviceContext = cloudTableClient.GetDataServiceContext();
    
    
            PerformanceCounterCPUCoreEntity ent = new PerformanceCounterCPUCoreEntity(count, instances[instances.Count() - 1],processName, processID);
            serviceContext.AttachTo(tableName, ent);
            serviceContext.UpdateObject(ent);
            serviceContext.SaveChangesWithRetries(SaveChangesOptions.ReplaceOnUpdate);
        }
    

    PerformanceCounterCPUCoreEntity 是 StorageTable 的模板 - 如果您对此部分有任何疑问或直接提问,请查看 azure Storage API。

    【讨论】:

      猜你喜欢
      • 2019-10-14
      • 2016-09-30
      • 1970-01-01
      • 2011-01-10
      • 1970-01-01
      • 2013-12-18
      • 2016-04-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多