不安裝運行時運行.NET程序

好久沒寫文章了,有些同學問我公衆號是不是廢了?其實並沒有。其實想寫的東西很多很多,主要是最近公司比較忙,以及一些其他個人原因沒有時間來更新文章。這幾天抽空寫了一點點東西,證明公衆號還活着。
長久以來的認知,對於託管代碼 .NET / JAVA ,都是需要在服務器上安裝 SDK 或者運行時的。比如 .NET Framework 4.XX ,JDK/JRE.XX 等。其實從 .NET Core 2.1 開始我們的 .NET 程序可以獨立打包成可以執行文件,在服務器上根本不需要安裝任何運行時相關的東西就可以運行。這個發佈模式在某些情況下可以大大提高部署的效率。以下簡單介紹一下。

“獨立”部署模式

在發佈界面部署模式選擇“獨立”,點擊保存之後然後正常發佈。等到發佈完成之後,查看 publish 目錄,可以發現裏面生成了一大堆文件,數量有上百個。這裏其實就包含了 runtime 相關的文件。

我們把這堆文件全部複製到某個未安裝過 .NET SDK 或者 runtime 的 windows 服務器上,找到 SelfContainedTest.exe 文件,雙擊運行。如果一切順利,會啓動一個控制檯。


訪問一下服務器的 5000 口,看到測試數據被成功的輸出了,證明我們的 .NET 程序可以正常運行了 。

單文件

上面的操作我們已經可以不安裝運行時在服務器上運行 .NET 程序了。但是那麼多文件看着不太優雅,下面讓我們的 .NET 程序打包成一個文件。
打開發佈設置界面,勾上“生成單個文件”

點擊保存,發佈之後,在 publish 目錄可以看到只剩下 6 個文件了。排除配置文件,pdb 文件等,其實真正的程序只是 SelfContainedTest.exe 文件,所以稱之爲單文件。雙擊這個文件我們的程序就可以正常的運行了。

裁剪

以上我們已經把程序從多個文件打包成一個文件了。這個文件我們可以看到有 70 M ,對於我們一個簡單的演示程序來說 70M 也挺大了。那麼有什麼辦法來縮小我們的可以執行文件嗎?
其實我們只要在發佈配置上打開裁剪功能,就可以縮小我們的程序。

在發佈配置界面勾上“裁剪未使用的代碼”,點擊保存,發佈之後,在 publish 文件夾下面生成的 SelfContainedTest.exe 文件縮小到了 30M 左右。

裁剪的注意點

這裏大概說一下裁剪的原理。當我們使用裁剪功能的時候,發佈程序會開始分析我們的代碼,哪些類被使用,哪些類沒有使用,沒有使用的類就會被刪除掉,使用這樣的原理來減小發布後程序集的大小。
但是以上方法顯然會有一個問題,那就是無法識別動態性很強的代碼,比如反射實現的某些功能。比如以下代碼:

string s = Console.ReadLine();
Type type = Type.GetType(s);
foreach (var m in type.GetMethods())
{
    Console.WriteLine(m.Name);
}

顯然以上代碼靜態分析沒辦法知道程序最終需要使用那些類,因爲目標類是通過 Console.ReadLine 方法輸入進去的。在程序沒有執行的時候誰也不知道哪些類會被使用。

在 IIS 上運行

上面我們演示程序運行的時候是寄宿在控制檯上的,這樣的話很容易被人誤關閉。其實單文件發佈的程序照樣可以使用 IIS 來託管。
按照正常的 IIS 發佈網站的流程配置之後,把應用程序池設置爲 “無託管代碼” 訪問對應的端口程序就可以正常運行了。

在 linux 上運行

以上我們都是在 windows 上測試,現在讓我們試一下在 linux 上運行它。
在 linux 上運行的話,需要在發佈配置界面修改“目標運行時”爲 linux-64 。

發佈成功後把生成的文件複製到 linux 服務器上。cd 到目錄,運行以下代碼。

chmod +x SelfContainedTest
./SelfContainedTest

很不幸,我們的程序沒有按計劃運行起來。

通過搜索後發現,需要設置一個環境變量。修改運行的代碼:

export DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1
./SelfContainedTest

運行完之後我們的程序應該會順利的啓動。訪問一下對應的 http 接口,可以看到正確的輸出了。

總結

通過以上演示,我們根本沒必要在服務器(windows/linux)上安裝任何 SDK 或者運行時就可以完整的運行我們的 .NET 程序。而且通過裁剪之後我們的程序的大小也縮小到了一個很小的範圍。以上功能對於互聯網行業來說可能沒什麼必要,畢竟大家走的都是容器化部署,服務器上本來就不需要安裝運行時。但是對於一些傳統行業,比如醫院這樣的環境,還有很多需要在服務器上人肉部署的場景。在這些場景之下就非常有意義了,可以大大的體高部署的效率。畢竟不是誰都可以很快的在服務器上安裝好運行時,特別是 linux 服務器。
其實不安裝運行時來運行程序還有一個辦法,那就是使用 AOT 發佈,這個我們下次再講。

關注我的公衆號一起玩轉技術

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章