好久沒寫文章了,有些同學問我公眾號是不是廢了?其實並沒有。其實想寫的東西很多很多,主要是最近公司比較忙,以及一些其他個人原因沒有時間來更新文章。這幾天抽空寫了一點點東西,證明公眾號還活著。 長久以來的認知,對於托管代碼 .NET / JAVA ,都是需要在伺服器上安裝 SDK 或者運行時的。比如 . ...
好久沒寫文章了,有些同學問我公眾號是不是廢了?其實並沒有。其實想寫的東西很多很多,主要是最近公司比較忙,以及一些其他個人原因沒有時間來更新文章。這幾天抽空寫了一點點東西,證明公眾號還活著。
長久以來的認知,對於托管代碼 .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 發佈,這個我們下次再講。
關註我的公眾號一起玩轉技術
QQ群:1022985150 VX:kklldog 一起探討學習.NET技術
作者:Agile.Zhou(kklldog)
出處:http://www.cnblogs.com/kklldog/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。