使用Jexus實現ASP.NET在Linux平台下的部署
來自專欄 Payne的專欄
Hello,大家好,我是Payne,歡迎大家關注我的博客,我的博客地址是https://qinyuanpei.github.io。今天想寫一點關於Linux部署ASP.NET相關的話題,為什麼突然想寫這個話題呢?因為就在幾天前,我被我所認識的一位前輩深深地鄙視了一番,原因是我依然在使用一個落後的IoC框架——Unity,在如今已然是公元2018年的今天。我突然想到,距離.NET Core 2.0發布已經有一段時間,而.NET Core 3.0的roadmap已經開始提上日程,可我好像還沒來得及認真地去對待這個現狀。我一直在關注跨平台和跨語言的技術,就像我在大學裡的時候就開始接觸Linux一樣,未來我們要面對的是種類繁多的終端平台,從PC時代到移動互聯網,再到VR、AR、IoT和AI,有太多太多的事情在悄然發生著變化。偶爾我的內心會泛起焦慮和迷茫,可在時光蹉跎直至褪色以前,我或許只是變回了曾經的自己。既然要如同涅槃一般重新開始,為什麼不首先重新拾起曾經關注的領域呢?所以,在這今天這篇文章里,你將看到:如何使用Jexus實現http://ASP.NET在Linux平台下的部署。
故事背景
我們項目組在開發這樣一種服務,它可以通過收集招聘網站的簡歷來提取相關信息,而這些信息將作為訓練集供AI演算法使用。考慮到Python在AI領域的優勢,我們決定採用Python來開發自然語言處理相關的業務,而簡歷的收集則是通過.NET中的Web Service暴露給前端。整個開發相對順利,可是在部署環節出現了問題。因為項目組以往的的項目都是部署在Linux Server上,所以在部署Web Service的問題上產生了分歧,負責運維的同事不願意為這一個項目而單獨配置一台Windows Server。這裡需要說明的是,採用.NET來開發Web Service的一個重要原因是,這些簡歷中存在大量Word文檔(.doc/.docx),因此不得不採用Office提供的COM組件來支持文檔的解析,雖然後來證明的確是這些COM組件拖了跨平台的後腿。所以,在這個時候,我們面臨著兩種選擇,第一種方案是採用Windows Server來部署,我們的運維同事表示不開心;第二種方案是採用Linux Server來部署。我們知道.NET跨平台的一個關鍵技術是Mono,可Mono的問題是它的基礎類庫不大健全,相信微軟收購Mono以後這個問題能夠得到解決。目前官方主推的跨平台技術是.NET Core,考慮到遷移到.NET Core版本的成本,我們最終沒有選擇這個方案。事實上,即使採用.NET Core進行開發,最終我們的部署依然需要依賴Jexus。綜合考慮這些因素,我們決定採用Jexus來將ASP.NET項目部署到Linux平台。
關於Jexus
Jexus是由宇內流雲開發的一款Linux平台上的高性能Web伺服器,它是一個可以免費使用、不開源的項目,最大的特色是可以支持ASP.NET、ASP.NET Core、PHP。通俗地來講,我們可以認為它是Linux平台上的IIS,這並不為過,因為你可以注意到Jexus Manager這個項目,它可以同時支持Jexus,IIS 和 IIS Express三種伺服器的管理,並提供了各個平台下一致的使用體驗,而Linux平台則主要是針對Jexus。Jexus提供了不亞於商用伺服器的眾多特性,比如多站點支持、使用應用程序池來調度管理工作進程、具有良好的穩定性和容錯能力、支持 HTTPS 和 WebSockets、支持 FastCGI 協議和 OWIN 標準。除此以外,它同時支持 URL 重寫、反向代理、壓縮傳輸、入侵檢測等重要功能。Jexus底層採用Linux中的epoll機制來處理網站請求,所以會比通常使用libuv實現的技術擁有更高的性能。作為一款跨平台軟體,Jexus支持主流的Linux發行版本。目前,國內外已經有大量的網站採用Jexus作為它的伺服器,我們可以在Jexus的官網上找到這些案例。雖然微軟官方正在全力推廣.NET Core,但對於那些需要維護的舊項目而言,遷移到全新的.NET Core平台著實是個不小的挑戰,而且目前支持.NET Core版本的類庫並不豐富,雖然最終的趨勢一定是.NET Core替代Mono,但對於Mono而言,在.NET宣布開源以後,從.NET Framework中吸收的基礎類庫,極大的改善了Mono基礎類庫不完善的狀況,而Mono針對CLR的實現、C#編譯器的實現、AOT環境等等特性,或許可以為.NET跨平台提供借鑒,這是一個相互促進的過程。在新時代到來以前,我們暫時需要使用Jexus來過渡。
Hello Linux
OK,下面我們來體驗一下Jexus在Linux平台上的效果,這裡我們以http://ASP.NET MVC4為例,我們直接通過Visual Studio創建一個項目即可,這裡我們需要的是這個項目發布以後的所有文件。總之,這些文件需要通過某種方式放到Linux平台上,大家自己去想辦法就好啦,這個不再說多餘的話。
安裝Jexus
Jexus安裝起來是非常簡單的,這裡博主使用的是Elementary OS,基於Ubuntu14.0的衍生版本。在終端下執行如下命令:
curl https://jexus.org/release/x64/install.sh|sudo sh
你沒有看錯,真的只需要一行命令。事實上,Jexus分為兩個版本,即通用版和獨立版。其差別是通用版不含Mono運行時,獨立版含有Mono運行時。官方建議使用獨立版,如果有朋友想嘗試安裝通用版,請在終端下執行如下命令:
curl https://jexus.org/release/install|sudo sh
無論採用哪一種方式安裝,當你看到終端中顯示:Jexus已經被成功安裝到系統,就表示Jexus安裝成功了。
配置Jexus
Jexus部署到網站,需要兩個東西,一個是網站內容(廢話),一個是網站配置。假定我們這裡將這兩個東西打包在一起,壓縮包的名字為app.tar。為什麼這裡選擇了.tar格式的壓縮文件呢?因為在Linux平台下這個格式更好用些,我們熟悉的.zip格式,可能會需要我們安裝相應的擴展。此時,我們可以使用如下腳本來部署網站:
tar -xf app.tarsudo mv -f .aspnetconf usr/jexus/siteconf/aspnetconfsudo mv ./aspnet /var/www
OK,現在來解釋下這個腳本,這裡我們需要部署一個名為「aspnet」的網站,所以,網站的內容被放置在「aspnet」這個目錄里。該網站對應一個作用於Jexus的配置文件,配置文件的名字為aspnetconf。首先,我們將「aspnetconf」這個配置文件移動到了「usr/jexus/siteconf/」目錄下,這是Jexus指定的配置路徑,即每一個站點都有一個配置文件,且該配置文件被放置在「usr/jexus/siteconf/」目錄下。然後,我們將「aspnet」這個文件夾移動到了「/var/www」目錄下,這是Jexus指定的網站目錄,即每一個站點都有一個文件夾,文件夾的名字可以理解為網站的名字。默認情況下,Jexus會在www目錄里創建一個名為default的文件夾,即默認有一個名為default的站點,不過經過博主核實,最新版(v5.8.3)中是沒有default站點。同理,Jexus會siteconf目錄里創建一個名為default的配置文件。我們通常以這個配置文件為參照來編寫我們自己的配置文件,例如下面是aspnetconf中的內容:
port=4000 root=/ /var/www/aspnet hosts= indexs= aspnet_exts=
其中,
1.port表示Jexus Web伺服器監聽的埠(必填) 2.root表示網站虛擬目錄與其對應的物理目錄,中間使用空格分開(必填)3.hosts表示網站域名(建議填寫),可以使用泛域名如.http://yourdomain.com或者填寫表示默認網站,一個埠有且只有一個默認網站,選填
4.indexs表示網站首頁文件名,如index.html、index.aspx等,多個文件名使用英文逗號分開,選填5.aspnet_exts表示http://ASP.NET擴展名,不建議填寫。如要填寫,多個擴展名(不含.)使用英文逗號分開。最簡單的配置只需要port和root即可,更多的配置項可以參考官方文檔。
基本使用
Jexus的常用命令簡單到只有3個,start、restart、stop。命令的基本格式為:
sudo /usr/jexus/jws start [站點名(可選,不指定時表示所有)]sudo /usr/jexus/jws restart [站點名(可選,不指定時表示所有)]sudo /usr/jexus/jws stop [站點名(可選,不指定時表示所有)]
在這個例子里,我們執行如下命令來啟動aspnet這個站點:
sudo /usr/jexus/jws start aspnet
當終端中返回OK時,就表示啟動成功啦,此時,我們打開瀏覽器,輸入http://localhost:4000就可以看到如下畫面(這裡的埠號為4000):
你就說,這算不算驚喜。我們還可以輸入http://localhost:4000/info來驗證Jexus是否配置正確,當Jexus被正確配置以後,你就會看到一個顯示著「Welcome to Jexus」的頁面。嗯嗯,好像是和Nginx挺像的哈!
Docker+
接下來,讓我們考慮將這些Linux上的工作轉移到Docker中來做,因為藉助Docker的容器技術,它可以為我們提供一個足以自給自足的環境。通過這個環境編譯測試通過的鏡像可以批量地部署到生產環境中。如果你不想在每一台Linux Server上都覆蓋本文的流程,那麼Docker將是提高你部署效率的不二選擇,而且從認知完整性的角度來看待Docker,你就會發現它和Jekins、TravisCI、VSTS工具一樣,都可以非常完美地被接入到持續集成(CI)的流程里去,譬如我們項目組採用的是Jekins + Gitlib + Docker的方案,所以,如果你想要選擇一個最適合你的持續集成(CI)方案,無論如何,Docker都是需要去了解的一個知識。關於Docker的背景知識大家可以自己去了解,這裡我們通過編寫Dockerfile來完成網站鏡像的構建:
FROM ubuntu:14.04LABEL vendor="qinyuanpei@163.com"# Prepare EnvironmentRUN sudo apt-get update RUN sudo apt-get install -yRUN sudo apt-get install -y curlRUN sudo apt-get install -y wgetRUN sudo curl -sSL https://jexus.org/release/x64/install.sh|sudo sh# Deploy WebsiteADD dest/ /RUN sudo mv -f aspnetconf /usr/jexus/siteconf/aspnetconfRUN sudo mkdir -p /var/wwwRUN sudo mv ./aspnet /var/www# Start JexusEXPOSE 4000WORKDIR /usr/jexusCMD sudo ./jws start aspnet
如果你熟悉Linux下的命令的話,你就會知道apt-get、curl、wget這些命令的含義,真正需要的解釋的是ADD,它表示的是,將Dockerfile同級目錄下的dest目錄添加到Docker環境中,接下來的命令我們同樣非常熟悉,因為這和Linux下操作是完全一樣的。不過,這裡的確有些坑需要踩,在博主構建鏡像的過程中,發現容器環境和虛擬機環境還是有本質不同的,這裡的mv命令在Docker下有時候會引發「hard link」的問題,從Stackoverflow上好像並沒有找到太有價值的答案,總之,這個問題非常的玄學。接下來,我們會將Docker容器的4000埠暴露出來,為什麼是4000埠呢?因為這個網站的配置中指向了4000埠,這一點在上文中我們已經提及。而入口處的命令,顯然是啟動Jexus服務,這個不再解釋。
這裡,我們通過如下命令來構建一個鏡像版本:
docker build -t jexus-aspnet:v1.0 .
假如這個鏡像被成功構建出來,我們就可以使用這個鏡像來啟動網站啦。如下圖所示:
具體地,我們可以使用docke image命令來管理所有的docker鏡像。這裡我們啟動網站:
docker run -p 4050:4000 -t jexus-aspnet:v1.0
這裡,我們將Docker容器的4000埠映射到主機的4050埠,當我們在瀏覽器中輸入:http://localhost:4050,就可以得到和Linux下一樣的結果。不過,在寫作這篇博客時,博主使用的是Windows下的Docker,如果大家遇到相關問題,歡迎在博客評論區留言。
本文小結
本文從一個實際工作的場景切入,分析和闡述了如何使用Jexus實現http://ASP.NET項目在Linux下的部署。為了簡化這篇文章的寫作,我們使用了一個http://ASP.NET MVC4的示例項目,真實的項目通常會有資料庫,所以情況會比本文所介紹的流程更為複雜,可這讓我們看到了一種可能性不是嗎?通過查閱相關資料,博主發現http://ASP.NET Core的部署不需要Jexus,它只需要一個dotnet run命令即可。然後,作為一次體驗Docker的過程,我們通過編寫Dockerfile的方式讓Jexus和Docker發生了某種奇妙的關聯。作為本文的一個延伸,我們需要考慮網站服務停止後可以自動重啟,這就是所謂的守護進程機制啦,感興趣的朋友可以繼續深入研究,Jexus提供了大量的優秀特性,這篇文章中所看到的不過是冰山一角。最終,我們的項目還是沒有使用Jexus,這其中有對Jexus性能的不信任,有因為COM組件而做出的妥協,有對Mono非官方方案的鄙夷......可以說,技術選型是一個受到多種因素制約的問題,誰擁有了話語權,就可以左右技術選型的走向,這是否又印證了,人類並非如自己所標榜的那般理性和正義?好了,以上就是這篇文章的全部內容啦,今天是5月20日,如果沒有人對你說「我愛你」,請記得對自己說「我愛你」,謝謝大家!
推薦閱讀:
※微軟宣布 .NET 開源了,如何學好.NET?
※WPF繪製圖表時,1ms更新一次數據,界面變得特別卡?
※c#中委託和事件?
※誰能介紹學習.net core的書籍或者大神寫的blog?
※微軟的.NET戰略是不是已經失敗了?