Dot-Net

性能計數器已創建,但在 Windows 重新啟動之前不工作

  • July 14, 2014

我在現有組中創建新計數器時遇到一個奇怪的問題。我有一個 Windows 服務,它可以做一些工作,並允許我通過性能計數器監控它的狀態。我有性能計數器組和一些性能計數器。在服務安裝階段創建組(具有管理員權限),並在服務啟動時初始化計數器(作為 LocalSystem 使用者)。一切正常,組存在,計數器也存在,我可以監視它們並寫入性能計數器日誌。服務不斷執行。

然後我想添加更多的性能計數器。我將它們添加到服務程式碼中,通過解除安裝以前的服務實例(性能計數器組被解除安裝程式碼刪除)來重建和部署到伺服器,然後再次安裝服務(在安裝階段使用所有新計數器創建性能計數器組)。然後我開始服務。

故事中常見的、無趣的部分就這樣結束了。奇怪的事情從這裡開始。

我去 PerMon,將所有計數器添加到系統監視器視圖。我可以看到我的性能計數器組,我看到了所有性能計數器,包括我剛剛添加的新性能計數器。我可以將它們添加到系統監視器視圖中。我可以看到,舊計數器正在工作。但是新的計數器不起作用,它們不收集任何數據。好吧,好吧,也許是我的錯誤,我切換到日誌視圖並嘗試記錄性能計數器數據。舊計數器的記錄與以前記錄的一樣。但是當我嘗試添加新計數器時,我在事件查看器中發現以下警告:

該服務無法將計數器“\AGENT\MyCountersGroupName\MyNewCounter”添加到 NewCountersLog 日誌或警報。此日誌或警報將繼續,但不會收集該計數器的數據。返回的錯誤是:找不到指定的計數器。

我嘗試重新安裝服務,刪除舊計數器,再次添加它們,但沒有任何改變。舊計數器正常工作,新計數器不工作。然後我重新啟動 Windows,新的計數器開始工作!服務沒有任何變化,我剛剛重新啟動了伺服器。我在 2 台伺服器上遇到了這個問題,它們都在 Windows Server 2003 SP1 下執行。所有性能計數器的程式碼都是相同的,因為我使用帶有泛型的程式碼來創建它們。

您可以說“嘿,別打擾,每次需要添加新的性能計數器時都重新啟動 Windows”,但我不能。我的服務與其他服務一起在伺服器上執行,我們需要這些服務不斷工作,每次更改一項服務時我們都無法重新啟動伺服器。

有人可以幫忙解決這個問題嗎?

更新: 看起來有類似的問題:https ://stackoverflow.com/questions/2180005/adding-performance-counters-to-existing-category

更新 我不認為問題出在我的程式碼中,但如果有幫助,我將其發佈在這裡。

安裝和解除安裝程式碼(在安裝階段呼叫): PerformanceCountersManagerBase.GetCreationData() 是一個通用包裝器,用於獲取數據集合以創建性能計數器。

public static void Install()
{
   CounterCreationDataCollection counters = new CounterCreationDataCollection(
   PerformanceCountersManagerBase.GetCreationData<TManager>().ToArray());

   if (PerformanceCounterCategory.Exists(PerformanceCountersManagerBase.GroupName))
       PerformanceCounterCategory.Delete(PerformanceCountersManagerBase.

   PerformanceCounterCategory.Create(PerformanceCountersManagerBase.GroupName, 
       "Group description",
       PerformanceCounterCategoryType.SingleInstance, counters);
}

public static void Uninstall()
{
   if (!PerformanceCounterCategory.Exists(PerformanceCountersManagerBase.GroupName))
       return;

   PerformanceCounterCategory.Delete(PerformanceCountersManagerBase.GroupName);
}

初始化服務中的計數器並更新的程式碼:

internal void Initialize(string name, string groupName)
{
   _counter = new PerformanceCounter(groupName, name, false);
   _counter.RawValue = 0;
}

internal void Increment()
{
   if ((_counter == null) || _counter.ReadOnly)
       return;

   lock (_counter)
   {
       _counter.Increment();
   }
}

更新 3 我更改了程式碼以通過 .NET 組件 PerformanceCounterInstaller 安裝計數器,但沒有任何改變。舊計數器按原樣工作,而新創建的計數器不工作並嘗試記錄它們會導致事件日誌中出現確切的錯誤(警告)消息。安裝程序創建程式碼如下:

public static PerformanceCounterInstaller GetInstaller()
{
   PerformanceCounterGroupAttribute group
       = PerformanceCountersManagerBase.ExtractGroupSettings(typeof(TManager));

   PerformanceCounterInstaller installer = new PerformanceCounterInstaller();
   installer.CategoryName = group.Name;
   installer.CategoryHelp = group.Description;
   installer.CategoryType = PerformanceCounterCategoryType.SingleInstance;
   installer.UninstallAction = UninstallAction.Remove;
   installer.Counters.AddRange(PerformanceCountersManagerBase.GetCreationData<TManager>().ToArray());

   return installer;
}

性能計數器基於共享記憶體段。當有人仍然擁有共享記憶體段的句柄時,我已經看到了類似的問題。這可以包括 perfmon 工具本身。您可以使用句柄實用程序來查看誰在使用共享記憶體。您不需要重新啟動,因此請嘗試查看此問題是否會消失,您首先關閉 perfmon,然後重新創建計數器。還要確保您的服務沒有執行。

在邁克回答之前,我自己處理了這個問題。但我沒有時間找出問題的原因。我通過執行以下步驟解決了這個問題:

  1. 停止 perfmon 日誌記錄(我通過 perfmon logger 記錄了所有計數器)
  2. 關閉性能
  3. 解除安裝服務(服務解除安裝程序解除安裝性能計數器整個組)
  4. 安裝帶有附加性能計數器的服務

在這些步驟之後,新的性能計數器出現了。也許沒有必要停止記錄,但我現在沒有時間檢查它。我稍後會嘗試。我接受邁克的回答是正確的,因為它指出了問題的原因。

引用自:https://stackoverflow.com/questions/3734277