網頁

2016年6月1日 星期三

使用 NanoProfiler 對 ASP.NET Web API 進行性能監控

在開發 ASP.NET MVC 網站的時候,我會使用 MiniProfiler 或 Glimpse 來監控每一個頁裡各種功能的執行性能,這在之前有寫了多篇文章作介紹,然後也在 twMVC#15 以「開發的效能與效率」這個 Session 裡也做了介紹和說明。但是到了開發 ASP.NET Web API 服務的時候,因為沒有頁面,所以也就無法使用 MiniProfiler 或 Glimpse 等工具去對每次的 API 執行去做監控,以致於就會相當仰賴 Log 記錄,在想要監控的程式片段去計算執行時間與寫入 Log,但是這樣的方式相當沒有效率,而且事後去查看 Log 也要當浪費很多時間才能把相關數據給整理出來。

在 2014 年底,我在 Nuget 的 Release 訊息裡發現了一個名為「NanoPrifiler」的套件,當時的介紹文章相當少,大概只有作者部落格裡的兩篇文章(第三篇文章還是到了 2015 年八月才發佈),而且我在 2014 年看到的時候還沒有放在 Github 分享出來(原本一開始有放在 Github 上,但是後來又關閉,現在已經重新公開),一開始我是被他的介紹與文章說明給吸引,直覺這個套件就是我所想要的,所以花了一點時間去研究,接著在 2015 年初就全面導入到專案開發裡,甚至於之後公司裡幾個後續所開發的 ASP.NET Web API 專案也都導入使用 NanoProfiler。

在 2015 年 12 月裡所舉行的 twMVC#21,我在主講的「以實例說明 ASP.NET Web API 服務的開發與測試過程」裡就有將 NanoProfiler 介紹給大家,而到了現在才有時間將使用、安裝的說明給整理出來,所以將會有一系列的文章說明如何使用 NanoProfiler。

 


如何偵測監控一個 Request 進來 API 然後一直到最後輸出所經過的每個程式的執行時間呢?

用 Stopwatch 在每個所執行的程式前後去做計算?…… 別鬧了,一開始就講過,這麼做真的很累。

用 NLog 去記錄?…… 你是認真的嗎?

一開始有講過,在 ASP.NET MVC 可以使用 MiniProfiler 或 Glimpse,但是 ASP.NET Web API 並沒有所謂的頁面可以顯示,使用情境上是不同的,所以就 ASP.NET Web API 服務就無法對執行性能作監測了嗎?

以下是 twMVC#15「開發的效能與效率」的相關連結:
https://mvc.tw/event/2014/6/14
https://docs.com/is-twMVC/2591/twmvc-15

image

 

NanoProfiler

NanoProfiler 是一個由 EF Learning Labs 所發佈的一個免費性能監控類別庫。

作者為 Teddy,對於 NanoProfiler 的詳細描述,可以參閱 Teddy 的部落格:

http://www.cnblogs.com/teddyma/

Teddy's Knowledge Base - NanoProfiler 相關文章

NanoProfiler - 适合生产环境的性能监控类库 之 基本功能篇

NanoProfiler - 适合生产环境的性能监控类库 之 大数据篇

NanoProfiler - 适合生产环境的性能监控类库 之 实践ELK篇

以上三篇文章裡是以 2014 年時的版本(1.x)所做的介紹與說明,所以如果是用目前的最新版本(2.x)去對照及跟著做,那麼一定會遇到很多的問題,所以請各位務必要看 NanoProfiler 在 Github Repository 上的 Wiki 內容,而且如果有遇到任何問題的話,也可以發 Issuse 給作者,作者都會給予協助。

NanoProfiler - Github Repository
https://github.com/englishtown/nanoprofiler
https://github.com/englishtown/nanoprofiler/wiki

我所提出的 issuse
https://github.com/englishtown/nanoprofiler/issues/2

NuGet Gallery
https://www.nuget.org/packages/NanoProfiler/

image

作者在他的部落格與 Github Wiki 裡都明白表示,NanoProfiler 是從 MiniProfiler 得到啟發,對高效能與大數據分析的需求所設計,而且不管是在同步或是非同步的程式模型裡都可以容易被使用,另外除了提供程式的執行性能監控外,也能夠監控資料存取的操作過程,例如透過 ADO.NET 或是 Entity Framework 對資料庫進行存取操作,都可以監控性能以及記錄所執行的 T-SQL 內容,而基礎是使用 ADO.NET 的 Dapper 也當然可以使用(我就是親身實例)。

在專案的程式裡要使用 NanoProfiler 是相當簡單的,透過 NuGet 安裝相關套件,然後進行簡單的設定,在程式碼裡只需要幾行程式就可以完成。

這篇雖然會以 ASP.NET Web API 專案來做安裝、設定等介紹說明,除了 Web API 專案外,也可以應用在 ASP.NET MVC 與 WCF 專案裡,至於那個 ASP.NET WebForm 專案的話,我就完全沒有試過(因為已經很久沒有去開發 WebForm 專案了,未來也不太有可能會再開發,所以就連試都不想試),這邊歡迎還有在開發 WebForm 專案的朋友去試試看能不能讓 NanoProfiler 在 WebForm 裡也可以使用。

會讓我要把 NanoProfiler 應用在專案裡,可以讓我們在開發過程馬上就從 view-result UI 裡看到各個過程的性能狀況,甚至於專案發佈到正式環境裡,也一樣可以使用(不過跟 Elmah 一樣,要記得做好防範),透過 view-result UI 就可以看線上即時的性能監控結果。

image
(圖片來源:https://github.com/englishtown/nanoprofiler/wiki/5.-How-to-view-profiling-results%3F

幾項特點:

  • 提供即時的性能監控數據
  • 可對資料庫存取進行監控
  • 提供清楚、方便、簡單操作的數據顯示頁面,方便查看
  •  

    安裝使用

    Step.1 先準備好一個 ASP.NET Web API 專案

    這邊使用的是以前文章的範例程式「ASP.NET MVC WebForm Repository Sample
    https://github.com/kevintsengtw/ASPNET_MVC_WebForm_Repository_Sample

    不過原始範例裡並沒有 ASP.NET Web API 專案,所以就新增一個 Web API 專案,資料存取層就直接使用原有的 Sample.Repository

    image

    EmployeeController

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Web.Http;
    using Sample.Repository.EntLibDAAB;
    using Sample.Repository.Interface;
     
    namespace Sample.Web.WebApi.Controllers
    {
        public class EmployeeController : ApiController
        {
            private IEmployeeRepository employeeRepository;
     
            internal IEmployeeRepository EmployeeRepository
            {
                get
                {
                    if (this.employeeRepository == null)
                    {
                        this.employeeRepository = new EmployeeRepository();
                    }
                    return this.employeeRepository;
                }
     
                set { this.employeeRepository = value; }
            }
     
            public EmployeeController()
            {
            }
     
     
            public IHttpActionResult Get()
            {
                var employees = this.EmployeeRepository.GetEmployees();
                var result = this.Request.CreateResponse(HttpStatusCode.OK, employees);
     
                IHttpActionResult response = ResponseMessage(result);
                return response;
            }
     
            public IHttpActionResult Get(int id)
            {
                var employee = this.EmployeeRepository.GetOne(id);
                var result = this.Request.CreateResponse(HttpStatusCode.OK, employee);
     
                IHttpActionResult response = ResponseMessage(result);
                return response;
            }
        }
    }

    執行結果

    image

    image

     

    Step.2 安裝 NanoProfiler 相關 NuGet Packages

    因為是 ASP.NET Web API 專案裡,所以需要安裝幾個 NanoProfiler 套件:
    NanoProfiler
    NanoProfiler.Web
    NanoPrifiler.Storages.Json

    目前的版本號都是 v2.0.7.3

    image

    另外還會安裝一個相依的套件:slf4net

    image

    image

     

    Step.3 修改 Web.Config

    https://github.com/englishtown/nanoprofiler/wiki/3.-Profiling-Configuration

    根據 Wiki 所提供的資料去修改專案的 Web.Config,不過…… Wiki 上面所給的 Web.Config Section 資料有點問題,如果直接使用 Wiki 的資料,在執行 Api 時就會出現「無法從組件 'NanoProfiler, Version=2.0.7.3, Culture=neutral, PublicKeyToken=132fc11abeaff685' 載入類型 'FileExt'。」錯誤,如下:

    image

    image

     

    所以請各位使用以下的設定內容,

    image

    <configSections>
        <section name="slf4net" type="slf4net.Configuration.SlfConfigurationSection, slf4net" />
        <section name="nanoprofiler" type="EF.Diagnostics.Profiling.Configuration.NanoProfilerConfigurationSection, NanoProfiler" />
        ......
    </configSections>

    image

    <nanoprofiler circularBufferSize="200" storage="EF.Diagnostics.Profiling.Storages.Json.JsonProfilingStorage, NanoProfiler.Storages.Json">
        <filters>
            <add key="_tools" value="_tools/" type="Contain" />
            <add key="exts" value="ico,jpg,js,css" type="EF.Diagnostics.Profiling.Web.ProfilingFilters.FileExtensionProfilingFilter, NanoProfiler.Web" />
            <add key="ViewProfilingLogsHandler" value="ViewProfilingLogsHandler.*" type="regex" />
        </filters>
    </nanoprofiler>

     

    Step.4 將想要監控的程式給包起來

    image

    ProfilingSession.Current.Step() 方法裡 StepName,用來描述這段被包起來的程式內容,能夠讓我們可以在 view result-UI 的 Detail 頁面裡清楚辨識就可以。

     

    Step.5 瀏覽 NanoPrifiler 的 Profiling result

    前面三個步驟都完成之後,就請先執行 Web Api 服務,然後再發出幾個 API Request,再來就是開啟網頁瀏覽器並且在網址列輸入「http:// localhost:xxxx /nanoprofiler/view

    image

    點選其中一項記錄,會以另開新網頁的方式顯示該項記錄的內容

    image

     

    先說到這裡,待續…

     


    其實還有很多可以寫出來的,不過再繼續寫下去就會太長了,所以在之後的文章會再繼續說明。

    這篇文章只有說明如何安裝與使用,比較進階的還沒有講到,例如監控記錄是存放在那裡、監控記錄有什麼樣的限制、能夠存放多少筆的記錄、如何監控資料庫存取的內容…… 需要說明的東西是真的不少,所以就請各位再耐心等候。

     

    相關連結

    http://www.cnblogs.com/teddyma/

    Teddy's Knowledge Base - NanoProfiler 相關文章

    NanoProfiler - 适合生产环境的性能监控类库 之 基本功能篇

    NanoProfiler - 适合生产环境的性能监控类库 之 大数据篇

    NanoProfiler - 适合生产环境的性能监控类库 之 实践ELK篇

    https://github.com/englishtown/nanoprofiler
    https://github.com/englishtown/nanoprofiler/wiki

     

    以上

    5 則留言:

    1. nanoprofiler没有一个完善的服务器端方案(存储+dashboard), 我之前使用mongodb来做存储,自己实现了一套dashboard集浏览、统计、监控于一体,最后发现瓶颈还是在存储上,后续的优化方案里打算采用influxdb,不过没有动手实现。

      回覆刪除
      回覆
      1. 目前 nanoprofiler 的作者是有提出支援 ELK 的方案,如果是真的有需要永續這類的資料,我會選擇購買 APM 產品,
        現在用這個 nanoprifiler 是應用在開發與測試環境的效能檢視,而線上環境的監控僅止於參考,
        log 相關的應用都會面臨到數據儲存的問題,就看對於這些 log 數據是如何做後續的處理,
        所以目前使用 nanoprofiler 對我而言是已經足夠

        刪除
    2. 作者已經移除這則留言。

      回覆刪除
    3. Kevin大大,
      目前我也嘗試要將NanoProfiler導入專案, 不過它不像Elmah可以設定Remote Only 或透過 Web.config 的 authorization 指定權限, 想請問Kevin大大, NanoProfiler 要怎麼做好保護機制呢?再請Kevin給小弟一些方向.

      非常感謝~

      回覆刪除
      回覆
      1. 兩個是不一樣的產品,所以不能拿來相比的,
        作者其實也說過,他是受到了 MiniProfiler 的啟發而寫了 NanoProfiler
        之前我曾經就 MiniProfiler 的安全性與讀取權限有寫一篇文章來說明
        所以在我還沒有針對 NanoProfiler 的讀取權限寫文章說明之前
        你可以先把那邊 MiniProfiler 的文章給翻出來看看,你就知道應該怎麼做了

        刪除