天天看點

使用.NET Core搭建分布式音頻效果處理服務(七)使用Docker壓榨性能極限

使用.NET Core搭建分布式音頻效果處理服務(七)使用Docker壓榨性能極限

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鏡像

上面噼裡啪啦的說了一大堆,其實就是一張圖檔就解釋的事情:

使用.NET Core搭建分布式音頻效果處理服務(七)使用Docker壓榨性能極限

筆者用了三台伺服器做處理服務,每台上面運作相同的docker執行個體32個,總共3*32=96個執行個體(全傻瓜式的水準擴充),通過用戶端模拟100個請求,得到結論如下:

反而比單機模拟6台伺服器性能降低了3%-6%,但是:

1:單機一次請求是8個,而在該系統測試中,一次請求是100個。

2:單次時間變長,是因為伺服器的U比本地測試的U的主頻低,但是核心卻是本地U的4倍。

這樣一來,其實整體性能會随着伺服器的數量的添加而增加,根據業務需求而定吧,就說目前某度雲的視訊轉換最高請求也就是幾千左右,如果真有那個量級,傻瓜式的增加伺服器就行了。

本系列完,感謝閱讀