Определение связанного процесса w3wp для экземпляра веб-роли

Я работаю над мониторингом производительности службы Azure.

в настоящее время запущено два экземпляра веб - роли (для одного и того же веб-сайта) - каждый со своим W3WP.exe (w3wp и w3wp#1)

Как я могу узнать, какой процесс w3wp принадлежит экземпляру роли?

С этой информацией я хочу кормить azure.диагностика.монитор с некоторыми счетчиками производительности, а именно Process (w3wp)ProcessorTime ( % ) и Thread Count. Но для того, чтобы получить любые значимые данные я должен добавить идентификатор процесса процесса w3wp к счетчику производительности (e.G 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

atm его как

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

Я подумал: если я запустил DiagnosticsMonitor для каждой роли, что монитор будет использовать corrrect process-принадлежность к Roleinstance, который запустил монитор . но на самом деле это не работает - или я думаю, что это не работает - по крайней мере, посмотрев на полученные значения.

/ / update: на управление.портал windowsazure можно определить пользовательские метрики для мониторинга производительности. Здесь можно выбрать экземпляр webrole для мониторинга исключительно. Это то, что я тоже хочу сделать. Понимание того, что на самом деле делает эта страница, также может помочь.

для сравнение: http://puu.sh/1xp7q

Они только глупый способ, который я могу придумать, чтобы получить эту информацию : чтобы получить список всех процессов до и после каждого запуска w3wp-определите, какой из них был добавлен, а затем решите контекст базы кода, какой экземпляр роли только что был запущен.

1 ответов


Я заставил его работать-хотя это было не совсем прямо.

прежде всего, я должен внести некоторые исправления в мои предыдущие заявления - просто быть на том же уровне.

в облачной службе есть несколько виртуальных машин, каждая из которых содержит либо экземпляр WebRole, либо экземпляр WorkerRole. Таким образом, на одной виртуальной машине работает только один w3wp или вообще нет w3wp, но процесс waworkerhost.

в моем частном случае есть возможность иметь два процесса w3wp на одном ВМ. поэтому мне нужно было различаться между этими двумя - таким образом, я должен был сделать какую-то ассоциацию процесса-экземпляра.

то, что я хотел зарегистрировать, было: общая загрузка ЦП одной виртуальной машины, загрузка ЦП процесса экземпляра, запущенного на виртуальной машине ( w3wp, waworkerhost).

PerformanceCounter для общей загрузки процессора легко и одинаково для каждой виртуальной машины: \Processor (_Total)\% Processortime для виртуальной машины webrole я не мог просто использовать \process(w3wp)\% счетчик processortime, потому что я не могу быть уверен, что это правильный w3wp (см. выше)

теперь вот что я сделал: Поскольку вам нужно запустить монитор счетчика производительности для каждого экземпляра роли OnStart () в WebRole.cs или WorkerRole.cs я понял, что это единственное место, где я могу каким-то образом собрать необходимую информацию.

в файла workerrole.CS я сделал:

int pc = Environment.ProcessorCount;
        string instance = RoleEnvironment.CurrentRoleInstance.Id;

        SomeOtherManagementClass.StartDiagnosticMonitorService(pc, instance, Process.GetCurrentProcess());

в WebRole.cs CurrentProcess также возвращает WaWorkerHost, поэтому мне пришлось переместить выше codelines в глобальную.эйсакс в webrole . Здесь доступен правильный процесс.

в SomeOtherManagementClass я помещаю StartDiagnosticsMonitorService, который теперь получает CurrentProcess, из которого был вызван StartDiagnosticsMonitorService. (из файла 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);
    }

GetProcessInstanceName(process.Id) теперь вызывается на каждой виртуальной машине и получает processName для предусмотренный процесс.Id-это позволяет провести различие между несколькими w3wps на одной виртуальной машине, потому что возвращаемые имена экземпляров-w3wp, w3wp#1, w3wp#2 и т. д. в отличие от имени процесса, предоставленного GetCurrentProcess, который всегда 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-посмотрите в API хранилища azure, если у вас есть какие-либо вопросы относительно этой части, или просто спросите.