Docker相信很多朋友都使用過,做微服務比虛擬機還好用。 需要安裝的一些東西 ffmpeg: dotnet: 預設全是latest最新即可,具體怎麼配置網上搜索一下即可。 調用用REST? 還是用RPC? 微服務之間的介面調用通常包含兩個部分,序列化和通信協議。常見的序列化協議包括json、xml ...
Docker相信很多朋友都使用過,做微服務比虛擬機還好用。
需要安裝的一些東西
ffmpeg:
docker pull ffmpeg
dotnet:
docker pull dotnet
預設全是latest最新即可,具體怎麼配置網上搜索一下即可。
調用用REST? 還是用RPC?
微服務之間的介面調用通常包含兩個部分,序列化和通信協議。常見的序列化協議包括json、xml、bytes等;通信比較流行的是http、soap、websockect,RPC通常基於TCP實現,常用框架例如dubbo,netty、thrift。
REST:嚴格意義上說介面很規範,操作對象即為資源,對資源的四種操作(post、get、put、delete),並且參數都放在URL上。
RPC:即我們常說的遠程過程調用,就是像調用本地方法一樣調用遠程方法,通信協議大多採用二進位方式。
一般來說,對內選擇rpc,因為他是直接基於TCP/IP協議通訊,性能要好很多。對外選擇REST,因為他是更規範的、更標準的、更通用的、更簡單的。
但是對於追求較高性能的RPC,會消耗額外很多成本,因此有時候對內一般也採用REST。
因此,筆者為了偷懶o(∩_∩)o ,在這個項目中選擇REST,而拋棄RPC那臃腫的調用方式。
發佈你的應用
dotnet 已經完全可以跨平臺,但是如果直接用bin下麵將文件夾拷貝到指定的地方,那麼你將得到無數抓狂的錯誤,這是因為netcore和 net framewor本身的不同而造成,前者提供的是基礎平臺、讓使用者自行去開發和擴展相應模塊、且開源,而後者是所有東西都已經為你打包到他的集合中去了,你只管調用NET系統根目錄中相應的庫即可。
比如你需要發佈到linux平臺,進入你的項目主目錄。執行:
dotnet publish -r linux-x64
註意:從dotnet core 2.1開始,發佈的時候已經不再需要先還原源碼包(dotnet restore)。
進入到publish文件夾(一般在bin下),你會發現多了一些runtime庫和一些你根本就沒引用的庫,這樣才能有效的在其他操作系統上直接運行。
運行你的應用
你可以通過主機docker命令並附加子命令來運行docker內的dotnet程式,例如這樣:
docker run -dit \ -p 50532:80 \ -v /home/dotnet/Service:/wwwroot \ -w /wwwroot \ --restart always \ --name dotnet_service \ 6d25f57ea9d6 \ dotnet Service.Web.Api.dll
-p:內外埠映射
-v:內外路徑映射
-w:工作目錄
6d25f....:你的dotnet鏡像名稱。
但筆者啟動的程式需要附帶大量的參數,而且不喜歡這樣通過docker宿主進行命令輸入,啟動中有沒有報錯不能及時反饋(docker啟動鏡像返回的是一組hash代碼,不會返回程式的的任何啟動信息,需要通過docker log查閱),這樣就變成如下操作:
進入在docker中的dotnet容器(成功運行鏡像後都會成為一個容器),找到與你項目相關的主程式集文件,例如筆者是Service.Web.Api.dll,執行dotnet Service.Web.Api.dll(當然你也可以附帶一大堆的啟動參數,例如筆者這樣)便可以運行這個項目。
dotnet Service.Web.Api.dll --ASPNETCORE_ENVIRONMENT=Development --ASPNETCORE_URLS=http://localhost:5052 --USE_CONTENTS_DIRECTORY=/home/netcore.MicroService/src/Service.Web.Api
小技巧:linux上面SSH相信大家有耳熟能詳,但是一旦關閉控制台,運行的後臺也將隨之關閉,我們可以通過安裝screen建立一個虛擬子屏幕,以保證shell程式在後臺能一直運行下去。
保存你的netcore容器到鏡像
如果我們需要在一臺伺服器上面建幾十個docker容器,每一個都像上面那樣進行一步一步的手動輸入,那不是要崩潰...
我們保存一個已經在運行的容器,修改他子程式的運行參數,例如修改映射埠號,就可以實現快速的多個相同鏡像的目的。使用命令:
docker commit c16378f943fe service_media
c1637...:這是筆者這邊已經在運行的容器實例。
接下來再執行“運行你的應用”中的命令,將外部映射埠改成你想要的埠號,不斷的重覆這個操作,即可在同一臺伺服器上運行多個實例。
為何要選擇docker進行實例運行
有的朋友也許不明白為何要這樣做重覆的操作,直接用dotnet自帶的宿主,複製多條相同的命令,修改埠號一樣也能達到如上的需求。
是的,這樣的確也可以在同一臺伺服器上運行多個主機宿主實例,但是,他們並沒有隔離。
對,就是這個詞語----隔離:
說到這個詞語可以牽涉一堆專業術語,而筆者又不想太多去複製太官方的東西,喜歡用白話文介紹自己所理解的內容。
當所有的子程式都運行在主機(非docker)下,記憶體分配,IO讀取,系統底層調用等等一些處理,都會交給主機操作系統執行,這樣會存在一定的風險。而docker雖然運行在主機之上,可他卻有一套自己的底層進行處理,這樣帶來第一層隔離,其次,運行在docker容器內的程式,容器本身也是一個操作系統,不外乎是被建立鏡像的時候將操作系統進行了大範圍的瘦身,只保留該TAG需要的LIB就行,這樣又做了一層隔離。
具體詳細的隔離架構,朋友們可網上搜一搜,很多的。
運行多個docker dotnet core鏡像
上面噼里啪啦的說了一大堆,其實就是一張圖片就解釋的事情:
筆者用了三台伺服器做處理服務,每臺上面運行相同的docker實例32個,總共3*32=96個實例(全傻瓜式的水平擴展),通過客戶端模擬100個請求,得到結論如下:
反而比單機模擬6台伺服器性能降低了3%-6%,但是:
1:單機一次請求是8個,而在該系統測試中,一次請求是100個。
2:單次時間變長,是因為伺服器的U比本地測試的U的主頻低,但是核心卻是本地U的4倍。
這樣一來,其實整體性能會隨著伺服器的數量的添加而增加,根據業務需求而定吧,就說目前某度雲的視頻轉換最高請求也就是幾千左右,如果真有那個量級,傻瓜式的增加伺服器就行了。
本系列完,感謝閱讀