Asp.Net Core 輕鬆學-在.Net Core 中使用鉤子

来源:https://www.cnblogs.com/viter/archive/2018/12/19/10140697.html
-Advertisement-
Play Games

Host startup hook,是2.2中提供的一項新的功能,通過使用主機啟動鉤子,允許開發人員在不修改代碼的情況下,在服務啟動之前註入代碼;通過使用鉤子,可以對已部署好的服務在服務啟動期間自定義托管程式的行為;通過使用鉤子,可以對服務進行跟蹤或者遙測,也可以在服務啟動前對托管環境進行健康檢查;... ...


前言

    Host startup hook,是2.2中提供的一項新的功能,通過使用主機啟動鉤子,允許開發人員在不修改代碼的情況下,在服務啟動之前註入代碼;通過使用鉤子,可以對已部署好的服務在服務啟動期間自定義托管程式的行為;通過使用鉤子,可以對服務進行跟蹤或者遙測,也可以在服務啟動前對托管環境進行健康檢查;還可以通過鉤子動態載入程式集進行依賴註入等功能。

什麼是鉤子

鉤子的作用原理是通過設置環境變數 DOTNET_STARTUP_HOOKS 的值將鉤子程式掛載到托管程式之中,在托管程式啟動的時候,CoreCLR 將按照鉤子列表順序進行檢查,初始化後執行每個鉤子程式,當鉤子列表中的鉤子程式被逐一執行完成後,托管程式將返回到程式主入口 Main 方法,進入一系列的啟動,鉤子程式可以是任何 .Net Core 版本的類庫項目,在項目內必須包含類 StartupHook 這是固定命名,且 StartupHook 必須是一個沒有命名空間的內部類,包含預設的靜態方法 Initialize(),符合此規範即可作為鉤子程式進行托管掛載

使用鉤子

1.首先創建一個控制台項目 Ron.HooksDemo ,作為托管主機,用於掛載鉤子程式 Ron.Init

Ron.HooksDemo 的代碼非常簡單,僅僅輸出一句話

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("\n程式已啟動");
            Console.ReadKey();
        }
    }
2. 創建鉤子程式,Ron.Init

2.1 按照鉤子程式的規範,創建一個無命名空間的內部類 StartupHook ,且包含預設靜態方法 Initialize()

internal class StartupHook
{
    public static void Initialize()
    {
        Console.WriteLine("程式集:Ron.Init.dll");
        Console.WriteLine("正在獲取伺服器信息.....");
        string[] drives = Environment.GetLogicalDrives();
        Console.WriteLine("machineName:{0},\nOSVersion:{1},\nversion:{2},\nuserName:{3},\nCurrentDirectory:{4}\nCore Count:{5}\nWorkSet:{6}\nDrives:{7}",
            Environment.MachineName,
            Environment.OSVersion,
            Environment.Version,
            Environment.UserName,
            Environment.CurrentDirectory,
            Environment.ProcessorCount,
            Environment.WorkingSet,
            string.Join(",", drives));

        Console.WriteLine("\n\n正在獲取網路配置.....");
        var hostName = Dns.GetHostName();
        Console.WriteLine("HostName:{0}", hostName);
        var addresses = Dns.GetHostAddresses(hostName);
        foreach (var item in addresses)
        {
            IPAddress ip = item.MapToIPv4();
            Console.WriteLine("AddressFamily:{0} \tAddress:{1}", ip.AddressFamily, ip);
        }

        Console.WriteLine("\n\n正在上報啟動信息.....");
        Console.WriteLine("=========== Ron.Init.dll 結束 ===========");
    }
}

上面的代碼即表示一個標準的鉤子程式,在 Initialize() 內部,進行托管主機檢查,獲取網路配置等行為,最好,還列印一條上報到遙測伺服器的信息,這裡是模擬上報檢查報告,最後輸出結束信息
代碼非常檢查,現在打開 Ron.HooksDemo 項目屬性頁進行鉤子掛載

上圖添加環境變數 DOTNET_STARTUP_HOOKS ,並設置其值為 C:\Users\Administrator\Source\Repos\Ron.HooksDemo\Ron.Init\bin\Debug\netcoreapp2.2\Ron.Init.dll,這是本次示例的鉤子程式絕對路徑
註意:該環境變數的值不支持相對路徑,如果嘗試使用相對路徑,托管主機將拋出 ArgumentException 異常

2.2 運行程式,看看是否正確掛載了鉤子程式 Ron.Init

上圖紅色部分輸出信息表示鉤子程式掛載成功,藍色部分表示托管主機已啟動,可以看到,托管主機啟動是在掛載鉤子之後運行的
一定要註意,鉤子是在托管程式的 Main 方法之前運行的

3. 掛載多個鉤子

3.1 一個托管程式可以掛載多個鉤子

掛載多個鉤子的方法是設置環境變數 DOTNET_STARTUP_HOOKS 的值,多個鉤子按順序執行,其中 Windows 和 Unix 掛載多個鉤子的方式基本相同,這其中,有一點微小的區別

  • Windows 平臺掛載方式
DOTNET_STARTUP_HOOKS = C:\Hooks_1.dll;C:\Hooks_2.dll
  • Unix 平臺掛載方式
DOTNET_STARTUP_HOOKS =/data/Hooks_1.dll:/data/Hooks_2.dll

以上 DOTNET_STARTUP_HOOKS 變數的值包含兩個鉤子程式,其中 Windows 平臺的值為使用分號(;)進行分隔,Unix 平臺使用冒號(:)進行分隔,這於傳統使用方式一致

3.2 運行掛載了多個鉤子的托管程式
  • 下麵把兩個鉤子掛載到 Ron.HooksDemo 項目後,他們分別是:Ron.Init 和 Ron.License

    Ron.Init 鉤子輸出的是檢查伺服器信息,這個信息在之前已經演示,這裡不再重覆,下麵看 Ron.License 代碼

    public static void Initialize()
    {
        Console.WriteLine("\n\n程式集:Ron.License.dll");
        Console.WriteLine("作者:Ron.liang");
        Console.WriteLine("博客地址:https://www.cnblogs.com/viter/\n\n");
        Console.WriteLine("=========== Ron.License.dll 結束 ===========");
    }
  • 鉤子程式的 Ron.License 代碼也非常簡單,結構和 Ron.Init 鉤子程式一致,只是簡單的輸出版權信息
3.3 運行 Ron.HooksDemo 程式,看下圖輸出結果

紅色部分是 Ron.Init 鉤子輸出信息,黃色部分是 Ron.License 輸出信息,藍色部分是托管主機 Ron.HooksDemo 輸出信息
可以看到,鉤子上安裝掛載的順序執行的

4. 在鉤子中載入額外的程式集

我們應該這麼理解,鉤子程式也是一個普通的應用程式集;所以一個普通的程式集能做到事情,鉤子也一樣可以

4.1 在 Ron.License 載入一個程式集 Ron.Service,Ron.Service 中定義了一個類 UserService,繼承自並實現 IDisposable 介面
    public class UserService : IDisposable
    {
        public void Dispose()
        {
            Console.WriteLine("程式集:Ron.Service.dll");
            Console.WriteLine("動態載入程式集,執行清理任務已完成\n\n");
            Console.WriteLine("=========== Ron.Service.dll 結束 ===========");
        }
    }
4.2 在 Ron.License 的鉤子方法中載入 Ron.Service 程式集,創建 IDisposable 的實現,並調用 Dispose() 方法
internal class StartupHook
{
    public static void Initialize()
    {
        Console.WriteLine("\n\n程式集:Ron.License.dll");
        Console.WriteLine("作者:Ron.liang");
        Console.WriteLine("博客地址:https://www.cnblogs.com/viter/\n\n");

        string path = @"C:\Users\Administrator\Source\Repos\Ron.HooksDemo\Ron.Service\bin\Debug\netcoreapp2.2\Ron.Service.dll";
        var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(path);
        dynamic obj = assembly.CreateInstance("Ron.Service.UserService");
        obj.Dispose();

        Console.WriteLine("=========== Ron.License.dll 結束 ===========");
    }
}
4.3 運行程式 Ron.HooksDemo

從輸出結果看到,Ron.Service 程式集已被成功載入並調用,控制台紅色輸出信息部分表示載入成功

5. 在 Asp.Net Web Api 項目中使用鉤子

Web Api 項目掛載鉤子的方式和控制台方式相同,首先我們還是創建一個 Web Api 項目 Ron.HooksDemo.Web
接著掛載鉤子

  "DOTNET_STARTUP_HOOKS": "C:\\Users\\Administrator\\Source\\Repos\\Ron.HooksDemo\\Ron.Init\\bin\\Debug\\netcoreapp2.2\\Ron.Init.dll;C:\\Users\\Administrator\\Source\\Repos\\Ron.HooksDemo\\Ron.License\\bin\\Debug\\netcoreapp2.2\\Ron.License.dll"
5.1 運行 Web Api 項目 Ron.HooksDemo.Web

紅色輸出部分表示 Web Api 程式的 Main 方法在鉤子列表執行完成之後成功啟動,這表示在 .Net Core 中,掛載鉤子的方式是一致的,其行為也相同

結束語

使用鉤子程式註意事項

  1. 鉤子程式不能依賴於托管主機的TPA列表之外的任何程式集,否則會拋出 FileNotFoundException 的異常
  2. 不要掛載過多的鉤子程式,這可能會出現相容性問題,如果要使用多個鉤子,必須確保每個鉤子程式的行為都是獨立的,互不幹擾的,如果一定要使用,建議修改托管主機的代碼,使用依賴註入的方式而不是鉤子
  3. StartupHook 類應該是 internal 類型的,如果是使用 public 進行修飾,還是可以正常載入鉤子程式

演示代碼下載

https://files.cnblogs.com/files/viter/Ron.HooksDemo.zip


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1. 成員 在類中你能寫的所有內容都是類的成員 2. 變數 1. 實例變數: 由對象去訪問的變數. 2. 類變數. 此時. 這個變數屬於類. 但是對象也可以訪問. 3. 方法 1. 實例方法: 使用 對象.方法() 特點: 在聲明的時候. 需要給出self, self必須放在第一個位置 在調用的時候 ...
  • 將兩個有序鏈表合併為一個新的有序鏈表並返回。新鏈表是通過拼接給定的兩個鏈表的所有節點組成的。 註意: 兩個鏈表都是有序的 如果某個鏈表為空,那就直接返回另外一個有序鏈表 然後我們就要比較兩個鏈表的節點的順序了 首先,我們定義一個result指針 比較兩個鏈表的第一個元素哪個比較小 result指向小 ...
  • php+ajax實現登錄按鈕載入loading效果,一個提高用戶體驗,二個避免重覆提交表單,ajax判斷載入是否完成。 ...
  • 這篇文章為spring回顧總結的第二篇,本篇主要分為兩個部分,分別是spring的bean工廠的實現.spring的aop實現原理,這兩部分也是面試當中問的比較多的. spring的bean工廠的實現 spring的bean工廠的實現可以有以下三種方式 1. 靜態工廠實現 配置文件: 2. 實例工廠 ...
  • 1.初識面向對象 面向過程: 一切以事物的發展流程為中心 面向對象: 一切以對象為中心.一切皆為對象.具體的某一個事務就是對象 打比方: 大象進冰箱 步驟:第一步:開門, 第二步:裝大象,第三:關門 面向對象: 大象,進冰箱 , 此時主語是大象,我操縱的是大象,此時的大象就是對象 2.類,對象 類: ...
  • javaSE(java standard Edition):標準版,定位在個人電腦上的應用。 javaEE(java Enterprise Edition):企業版,定位在伺服器端的應用。*********************************** javaME(java Micro E ...
  • flash的一般分區: print(可縮寫為:pri):列印查看uboot這個軟體中集成的環境變數setenv、saveenv:設置、保存環境變數 如:設置環境變數: setenv abc 100刪除環境變數: setenv abc保存環境變數到存儲器:saveenv abc 100網路層的設置: ...
  • 前言: 環境:centos7.5 64 位 正文: 拉取 microsoft/dotnet, 安裝完畢後執行 docker images 可以看到本地已經包含 microsoft/dotnet 使用 docker run 鏡像名 可以啟動鏡像,通過指定參數 it 以交互模式(進入容器內部)啟動。依次 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...