6

Sto lavorando al monitoraggio delle prestazioni di un servizio di Azure.Identificare il processo w3wp associato per un'istanza di ruolo Web

momento non ci sono due istanze di ruolo web (per lo stesso sito) di gestione - ognuna con il proprio W3WP.exe (w3wp e w3wp # 1)

Come faccio a sapere quale processo w3wp appartiene a quale istanza di ruolo ?

Con queste informazioni voglio alimentare il server azure.diagnostics.monitor con alcuni contatori delle prestazioni, ovvero Process (w3wp) \ ProcessorTime (%) e Thread Count. Ma per ottenere dati significativi devo aggiungere l'ID di processo del processo w3wp al contatore delle prestazioni (es. Process (w3wp_PID) \ processorTime (%)) - non so se la sintassi è corretta, ma c'è un modo per aggiungere il PID)

quindi il risultato finale nelle WADPerformanceCounters tabella AzureStorage deve solo voci come:

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

atm suo come

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

ho pensato: se ho iniziato un DiagnosticsMonitor per ciascun Ruolo, che il il monitor userebbe il processo corrretto - appartenente al Roleinstance che ha avviato il monitor. ma in realtà non funziona - o penso che non funzioni - almeno dopo aver visto i valori risultanti.

// aggiornamento: sul portale manage.windowsazure è possibile definire le metriche personalizzate per il monitoraggio delle prestazioni. È possibile qui scegliere l'istanza di webrole da monitorare esclusivamente. Questo è quello che voglio fare anche io. Approfondimenti su ciò che effettivamente fa questa pagina potrebbe essere d'aiuto.

per il confronto: http://puu.sh/1xp7q

Essi unico modo stupido mi viene in mente per ottenere queste informazioni è il seguente: per ottenere un elenco di tutti i processi prima e dopo l'avvio di ogni w3wp - identificare quale è stata aggiunta e poi decidere il contesto di base di codice saggio quale istanza di ruolo è stata appena avviata.

risposta

0

ho funzionato, anche se non era davvero semplice.

prima di tutto devo apportare alcune correzioni alle mie dichiarazioni precedenti - solo per essere sullo stesso livello.

Nel Servizio Cloud ci sono diverse macchine virtuali, ognuna delle quali ospita un'istanza WebRole o un'istanza WorkerRole. Quindi su una singola VM viene eseguito solo un singolo w3wp o nessun w3wp, tranne un processo waworkerhost.

Nel mio caso speciale c'è la possibilità di avere due w3wp in esecuzione su una singola VM. quindi avevo bisogno di distinguere tra questi due, quindi mi richiedevano di creare una sorta di associazione di istanza di processo.

Quello che volevo registrare era: Il carico totale della CPU di una singola VM, il carico della CPU del processo istanza in esecuzione sulla VM (w3wp, waworkerhost).

Il PerformanceCounter per Load CPU totale è facile ed uguale per ogni VM: \ Processore (_Total) \% Processortime per la WebRole VM ho potuto basta utilizzare il processo \ (w3wp) \% processortime contatore perché non posso essere sicuro se è il w3wp corretto (vedi sopra)

Ora ecco cosa ho fatto: Dato che devi avviare un contatore di prestazioni contatore per ogni istanza di ruolo OnStart() in WebRole.cs o WorkerRole.cs ho capito questo è l'unico posto dove posso in qualche modo raccogliere le informazioni richieste.

Negli WorkerRole.cs ho fatto:

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

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

Negli WebRole.cs il CurrentProcess restituisce anche WaWorkerHost, così ho dovuto spostare le codeline sopra nella global.asax del WebRole. Qui è disponibile il Processo corretto.

In SomeOtherManagementClass ho inserito StartDiagnosticsMonitorService, che ora riceve il CurrentProcess da cui è stato chiamato StartDiagnosticsMonitorService. (da workerrole.cs riceverebbe WaWorkerHost processo e dal WebRoles processo w3wp - compreso 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) viene ora chiamato ogni VM e ottiene il processName alla condizione process.Id - questo consente di effettuare una differenziazione tra più w3wps su una singola VM poiché i nomi di istanza restituiti sono w3wp, w3wp # 1, w3wp # 2 ecc., contrariamente al processName fornito da GetCurrentProcess, che è sempre w3wp. per questo ho modificato un codeSample ho trovato qui su StackOverflow - si può trovare qui di seguito:

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 ""; 
    } 

Ultimo ma non meno importante: SetCPUCoreData (coreCount, currentRole, processName, process.Id) salva tutti i dati rilevanti dei processi allo stoccaggio azzurro quindi è disponibile da ovunque nell'applicazione:

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); 
    } 

il PerformanceCounterCPUCoreEntity è un modello per lo StorageTable - esaminare l'API bagagli azzurro se avete domande riguardo a questa parte, o semplicemente chiedere.

Problemi correlati