2018年10月29日 星期一

讓 Windows Azure Web Server 擁有自動修復/重啟機制

這篇文章的內容其實應該半年前就打算要筆記下來了,無奈那陣子在忙 PMP 證照的考試以至於沒有特別撥出時間來寫,起因在於某個案子是用 .Net Core 開發出來的應用放在 Azure Web Server 上,但由於內部 Client 端對 Server API 的 Request 沒有良好的規劃,導致有一些多餘(數量還不少...)的 Request 已經開始造成 Server 的負擔,加上 Server 選用的等級也不高...所以那陣子 Server 的狀態一直處於不穩定的狀態,常常假日都要有人待命去對 Server 做重啟的動作,慶幸在網路上有看到針對此問題相關的文章,二話不說馬上拿來用看看(應該沒人想在假日一直 On Call 吧...)


首先打開專案根目錄下的 Web.config (沒有自己新增),然後先看一下該檔案內容有沒有包含以下結構碼(沒有再自己新增)

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <monitoring>
      <triggers></triggers>
      <actions value=""/>
    </monitoring>
  </system.webServer>
</configuration>

接著 Azure 提供了四種狀況/場景來讓 Server 可以自動修復/重啟,以下將會介紹每種方式()

1. 在一定時間內達到指定的 Request 數

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <monitoring>
      <triggers>
 <requests count="2000" timeInterval="00:15:00"/>
      </triggers>
      <actions value="Recycle"/>
    </monitoring>
  </system.webServer>
</configuration>

當 Server 在15分鐘內被 Request 達到2000次時,Server 馬上執行回收/重啟作業


2. 單筆 Request 的回應超過預設的時間,且達到指定的數量

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <monitoring>
      <triggers>
 <slowRequests timeTaken="00:00:30" count="10" timeInterval="00:02:00" />
      </triggers>
      <actions value="Recycle"/>
    </monitoring>
  </system.webServer>
</configuration>

當 Server 在30秒內有10筆耗時超過2分鐘的 Request 時,Server 馬上執行回收/重啟作業


3. Server 在指定時間內回應特定的 HTTP 狀態碼達指定數量


<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <monitoring>
      <triggers>
 <statusCode>
          <add statusCode="500" subStatusCode="100" win32StatusCode="0" count="20" timeInterval="00:01:00"/>
        </statusCode>
      </triggers>
      <actions value="LogEvent"/>
    </monitoring>
  </system.webServer>
</configuration>

當 Server 在1分鐘內有20筆 HTTP 回應碼為500的 Request 時(或 SubStatusCode 為100或 win32StatusCode 為0),Server 將執行寫入 Log 到 eventlog.xml (在網站根目錄的 Logfiles 資料夾下),你也可以將 <actions value="LogEvent"/> 替換成 <actions value="Recycle"/>


4. 限制 Server 記憶體使用量上限


<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <monitoring>
      <triggers>
 <memory privateBytesInKB="500000"/>
      </triggers>
      <actions value="CustomAction">
        <customAction exe="d:\home\procdump.exe" parameters="-accepteula w3wp d:\home\w3wp_PID_%1%_" />
      </actions>
    </monitoring>
  </system.webServer>
</configuration>

當 Server 該應用程式的記憶體使用量超過在 500 MB Request 時,執行指定目標程式(d:\home\procdump.exe)


5. 測試結果

經設定後,當 Server 有達到設定的條件時,確實有執行相對應的動作,觀察一陣子後也都沒異常發生當然罪魁禍首內部 Client 端的問題也是要解決,畢竟這也只是算一種讓 Server 有自我保護的機制,預防 Server 無預警的癱瘓,至此問題也算是圓滿告一段落了


P.S. 由於區段 <monitoring> </monitoring> 屬於 Azure 特有的設定,故如果在一般測試環境 IIS 上執行時是會報錯的,可以把它放在要部屬的 Web.config 裡,如放在 Web.Release.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <monitoring xdt:Transform="Insert">
      <triggers>
        <!-- Scenario #1: Recycling based on Request Count -->
        <!-- <requests count="2000" timeInterval="00:15:00"/> -->
        <!-- Scenario #2: Recycling based on slow requests -->
        <slowRequests timeTaken="00:00:30" count="10" timeInterval="00:02:00" />
        <!-- Scenario #3: Logging an event (or recycling) based on HTTP status code(s) -->
        <!-- <statusCode>
          <add statusCode="500" subStatusCode="100" win32StatusCode="0" count="20" timeInterval="00:00:30"/>
        </statusCode> -->
        <!-- Scenario #4: Taking custom actions (or recycling/logging) based on memory limit(500MB) -->
        <!-- <memory privateBytesInKB="500000"/> -->
      </triggers>
      <!-- Scenario #1 & #2 Action -->
      <actions value="Recycle"/>
      <!-- Scenario #3 Action -->
      <!-- <actions value="LogEvent"/> -->
      <!-- Scenario #4 Action -->
      <!-- <actions value="CustomAction">
        <customAction exe="d:\home\procdump.exe" parameters="-accepteula w3wp d:\home\w3wp_PID_%1%_" />
      </actions> -->
    </monitoring>
  </system.webServer>
</configuration>




參考資料:

[Microsoft Azure] Auto-Healing Windows Azure Web Sites

[Stackoverflow] System.webServer has invalid child element "monitoring"