如何快速釋放Windows Server Core記憶體!

如何快速釋放Windows Server Core記憶體!

一個有趣的Case。我們需要收集與分析機台日誌,一天資料量(Size)不大,約200 ~ 300MB,但資料量(Folders/Files)很多,目前觀測到每日約有60 ~ 70萬筆,而且還會不斷成長。資料夾與檔案數約1:2,也就是,如果當天資料夾10萬個那就有20萬筆檔案。我們需要定時去主機A把日誌同步至主機B去進行程式分析與處理,因為不是所有檔案都是我們需要的,在複製的過程會進行一些過濾動作,所以選擇下面三套來測試,但發現一個好玩的現像,主機B常常沒有多久就記憶體滿載(Memory 99%~)的情況,目前測試過:

  1. xcopy.exe
  2. robocopy.exe
  3. freefilesync.exe

1,2 是 Windows 內建,freefilesync 是第三方軟體,都會造成記憶體不斷拉高的現像。記憶體一直長大的可能原因,我猜和黑大這篇Windows記憶體都用到哪裡去了?有關。(其中還是有大量 Part 1 的 Nonpaged Pool ... 頭痛呀! >__< )

Full Usage Memory

就算複製(同步)工作結束後,主機B要放著沒做事過一陣子(目前觀測要超過1hr)才會把記憶體還你,也就說憶體體並不是不會釋放。不過我們同步作業是1小時一次,等於是等不到系統把記憶體還給你就又開始工作了。所以憶記體不斷拉高,也是合情合理。

Memory reduce

當然,我們可以一直放著 99% Usage Memory 不管,到沒有因為 99% Usage Memory 而造成當機或藍白畫面或應用程式不會跑等。不過有觀察到一些副作用,例如,遠端桌面登入時,明顯反應變慢了,或是要多登入幾次才會登入成功,其他的操作也有變慢現象。

試了好多辦法都沒有好效果,最後想法放在:是否能在 Windows Server 上更快速釋放記憶體?

以下設定有一定風險,快速釋放記憶體有賺有賠,設定前自行評估與負責。

Mem Reduct

本想 .NET Framework 是否能處理這方面的問題,但查詢之後才了解,記憶體管理大多要從 Win32 API 下手,雖然可以在 .NET / C# 去呼叫 Win32 API 來處理,但想想有沒有人家造好的輪子。

Mem Reduct 是個 Open Source 的軟體,以 C++ 撰寫,目前測試在 Windows Server 也有不錯的效果。不過在測試時發現二個問題:

  1. Mem Reduct 只能在登入狀態下執行,一但登出應用式程會關閉。
  2. Mem Reduct 在 Server Core 連最小化都有問題,因為 Server Core 根本沒有工作列。

hwnd

透過 Dino Wang 的支援,得知有個 hWnd 的方法,可以把前景應用程隱藏起來。在網路上找到一篇 PowerShell 的做法:

$definition = @"    
      [DllImport("user32.dll")]
      static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

      [DllImport("user32.dll")]
      [return: MarshalAs(UnmanagedType.Bool)]
      static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

      public static void Show(string wClass, string wName)
      {
         IntPtr hwnd = FindWindow(wClass, wName);
         if ((int)hwnd > 0)
            ShowWindow(hwnd, 1);
      }

      public static void Hide(string wClass, string wName)
      {
         IntPtr hwnd = FindWindow(wClass, wName);
         if ((int)hwnd > 0)
            ShowWindow(hwnd, 0);
      }
"@

add-type -MemberDefinition $definition -Namespace my -Name WinApi

[my.WinApi]::Hide('memreduct.exe', 'Mem Reduct')

此法可行,這算是解了第二個 Server Core 無工作列造成自動關閉的問題。

NSSM

要在登出後處於執行的狀態,除了請原作者支援外,是否還有其他方法?是否可能把這種前景應用程式包裝成背景應用程式來執行呢?看到許多國外許多網友介紹用 NSSM 來解決類似問題。試過之後,一次解決上述的二個問題。

下載後必須透過 Command Line 方式來設定,文件寫的很清楚:

nssm install memreduct
nssm service installer
nssm cli message

這樣就能在把前景應用程式包裝成背景應用程式來執行。目前以記憶體 80% 的使用率當為條件來觸發清除系統快取。

副作用

這樣等於是手動介入了的系統的運作,在持繼觀察這樣的行為是否有副作用時,是的,這樣會造成應用程式不正常,雖然不是立即產生副作用,但造成應用程式不正常是事實,最後只好又把此路封了。

沒有留言:

張貼留言

感謝您的留言,如果我的文章你喜歡或對你有幫助,按個「讚」或「分享」它,我會很高興的。