當前位置:
首頁 > 最新 > 老衣的微服務實踐簡要指引2017版

老衣的微服務實踐簡要指引2017版

這是老衣在2017年5月份總結的,適用於中小團隊跨平台微服務開發的實踐指引(簡化版)。若有有不當之處,歡迎指點更正

因本文涉及到大量第三方庫或工具,詳細學習和了解需要參考相關官方文檔。若您在使用Mac電腦,建議安裝使用Dash軟體下載查閱;其他操作系統上則考慮使用Chrome瀏覽器在http://devdocs.io/offline 上查閱文檔,值得一提的是該網頁的文檔支持離線模式。


node.js 可根據實際情況選擇安裝當前版或是長期支持版

docker最新版 根據實際需要決定使用免費的Docker CE版或是收費的Docker EE版。注意Windows 10 64位專業版和64位企業版可以直接安裝(依賴hyper-v),其他舊版Windows,需要使用docker toolbox。

根據自己的喜好選擇安裝下列Git客戶端:

git scm

Source Tree

TortoiseGit 僅支持Windows

SmartGit


lua 最新版

python最新版

.NET Core 1.1或以上


Visual Studio 2017:僅支持Windows系統

Visual Studio for MAC:故名思議,僅支持Mac系統

Visual Studio Code,跨平台代碼編輯器。建議至少安裝以下擴展,其他擴展由團隊根據使用的開發語言和相關工具鏈自行決定是否安裝:

Docker :支持DockerFile的加亮和智能提示

Angular 1 JavaScript and TypeScript Snippets for VS Code :支持angular1.x的一些代碼片段和智能提示

Azure Extension Pack :微軟官方出品的在VSCode中處理Azure相關功能的一些擴展

Azure Tools for Visual Studio Code :一些方便在VSCode使用的Azure工具

Beautify :代碼格式整理插件

Bootstrap 3 Snippets :bootstrap框架的代碼片段

Bower :Bower的VSCode擴展

C# Extensions :增加一些C#開發時的功能

C# XML Documentation Comments :支持C#的注釋

Can I Use :檢查當前行的CSS屬性兼容的瀏覽器版本

HTML CSS Support :支持各種Web語言(html、Razor、Vue、pug、php等)

Icon Fonts :字體圖標(例如Font Awesome)的樣式支持

Lua linter :支持Lua語言智能提示和語法檢查等

mssql :可在VSCode中方便使用微軟SQL Server資料庫

nginx.conf :支持nginx配置文件的代碼加亮

Python :支持Python的智能提示和代碼格式化等功能

yo :將前端項目模板工具Yo的相關命令內置到VSCode

Web前端開發相關工具:

Yeoman,簡稱Yo - 前端項目模板工具,可以快速搭建前端項目模板

Bower - 前端包管理工具,類似於Visual Studio種的Nuget

用於打包發布的工具: Grunt、Gulp、webpack 中的至少一種,看個人喜歡或團隊熟悉度

動態CSS語言: LESS、SASS 根據團隊需要選擇其一

Angular 1.x 適用於企業管理等相關用戶場景的開發,因為其對IE瀏覽器支持的版本相對較低,適用面較廣

後端資料庫,建議向跨平台的資料庫種類傾斜,比如MySQL、PostgreSQL,甚至是一些NOSQL資料庫:MongoDB。微軟的SQL Server 2017支持Linux和Docker,目前尚處於預覽版狀態,不建議在生產環境使用,等官方正式版發布後再嘗試使用。PostgreSQL資料庫對SQL標準的語法支持非常完整,建議更多考慮。


為了最大限度提功開發部署靈活性,建議使用Git方式託管。所以可根據實際情況選擇下列之一:

支持Git庫的TFS

GitHub 私有庫或企業版

Coding.net 私有庫或企業版

開源免費,私有部署的Gogs,具有豐富的認證方式選擇,並支持Slack平台的WebHook

GitLab 可託管部署或私有部署

建議在以上任何一種git服務中,建立或使用一個支持證書登錄的用戶,該證書用於構建環境自動拉取代碼時使用,不建議使用賬號密碼方式,因為安全性較差。該證書對應的用戶應該有所有需要自動構建的代碼庫讀許可權。不建議給該用戶開放寫許可權,避免一些潛在安全問題和代碼衝突問題


構建環境是專門用來自動化、編譯、集成、測試、打包、發布的環境,建議使用獨立的計算機和伺服器做為構建環境。因為該環境對代碼和測試、生產環境都有較高的許可權,也會涉及到大量的安全證書或密鑰等極敏感信息,所以強烈建議該環境所在設備僅限極少數高度可信賴的人訪問管理,並有嚴格的安全規定,不允許隨便安裝軟體或向外複製數據

建議使用linux作為構建環境的操作系統,因為windows的命令行工具能力有限。並確保安裝如下工具:

Node.js 我們需要依賴很多nodejs工具鏈,所以這是必須安裝的。通過下列命令確認是否安裝,以及什麼版本

還需要確認是否安裝:

安裝新版,可以通過自更新實現

ShellJS 是在Node.js API之上的攜帶型(Windows/Linux/OS X)Unix Shell命令實現,可以消除或減少您的Shell腳本對特定操作系統的依賴。通過下面的命令全局安裝

老衣的實踐是利用shelljs的腳本能力以及js語言的豐富特性和靈活度,通過編寫腳本的方式結合其他工具或平台實現編譯、測試、打包、發布、通知等的自動化處理

Docker 幾乎是微服務架構的必需品,我們通過Docker隔離和構建相關的服務,通過下列命令確認是否安裝,以及什麼版本

git 確保安裝使用了最新的git命令行客戶端,可通過下列命令確認是否安裝,以及什麼版本

Python 很多輔助工具是用python開發的,所以有備無患,通過下列命令確認是否安裝,以及什麼版本

Mono 是跨平台的.NET框架實現,目前5.0以上版本已經完整匹配.NET 4.6.2的API集,幾乎除了Windows平台特有的API外,Mono和.NET框架幾乎是完全兼容的。所以如果你的微服務是用的.NET開發的,這是必須安裝的——當然如果你只打算在Windows上用,可以不安裝這個。通過下列命令確認是否安裝,以及什麼版本

.NET Core 如果你的微服務有用的開發的,這是必須安裝的。通過下列命令確認是否安裝,以及什麼版本

Cake 是C# Make的縮寫,是一個基於C# DSL的跨平台自動化構建系統。它可以用來編譯代碼,複製文件以及文件夾,運行單元測試,壓縮文件以及構建Nuget包等等。

TeamCity、Jenkins 這兩個是獨立的自動構建伺服器軟體,如果不願意使用shelljs之類的腳本自行編寫構建任務,可以通過他們在管理界面上設置,不過學習成本和複雜度蠻高的,如果團隊內沒有人熟悉這兩個工具,早期不建議使用。

其他語言的基礎框架根據實際的每個微服務所使用的語言環境決定安裝哪些基礎支持工具、框架、模塊等

自動構建服務,在拉取代碼、獲取依賴包、編譯、測試、打包、發布等各個環節都可能會發生錯誤或異常,而編譯不通過或測試不通過等情況也應該第一時間跟團隊或項目管理者報告,我們在實踐中更推薦使用Slack來實現,實現方式請參考官方文檔 https://api.slack.com/incoming-webhooks,絕大部分情況下1-3行代碼即可實現,非常方便,當然了這裡有個小問題Slack的所有客戶端(web、手機App、桌面應用等)都沒有中文版。當然了你願意使用電子郵件或企業微信或微信服務號來實現也可以,只是實現成本和效果跟Slack比完全不在一個級別上。注意:Slack的webhook地址通常類似於 這屬於保密的地址,不應該在公開的文檔或代碼中體現,否則容易在Slack的相關頻道中產生虛假的信息,切記!!!

當然了上述構建所需到基礎依賴,也可以在準備好到Docker容器中做,可減少不同服務對基礎依賴(比如php、java、nodejs等)版本不同而帶來的構建衝突。早期團隊可通過技術選型很大程度上避免基礎依賴衝突,所以可先不考慮使用大量Docker容器隔離不同到構建環境,待團隊逐漸成熟壯大後,可根據需要慢慢向這個方式靠攏。

我們在實踐中更傾向於使用Docker構建相應的鏡像來部署最終的微服務,所以需要一些必要的基礎鏡像提前做準備。推薦安裝如下鏡像:

以上鏡像,如果需要安裝特定版本,可通過加tag參數來獲取對應版本的鏡像。特別一提的是其中和都是使用廣泛的超小型基礎鏡像,大小僅有幾M而已,對最終鏡像大小很敏感的可考慮使用這些鏡像作為基礎。

通過下列命令可在部署環境中確認上述鏡像是否已經到:


Docker Store上已經有大量官方鏡像和公開鏡像,可供參考使用,但通常我們自己到私有服務的鏡像是不希望公開讓別人下載使用的。所以需要搭建自己的鏡像庫,所以我們需要使用Docker Registry來搭建自己的私有鏡像庫。

注意:新版到registry要求必須使用https協議,所以搭建時需要考慮購買或使用免費的SSL證書。目前國內的騰訊雲和阿里雲貌似都有免費一年到二級域名證書,可考慮使用。

使用私有的Docker Registry服務後,每次構建好的服務鏡像都是先到私有服務上,然後再在生產環境中最新版,並部署使用。


測試或生產環境,基本上僅需要安裝Docker,通過相關的命令來拉取相關鏡像,並部署或維護所需服務的容器即可。單伺服器上多個微服務如果有依賴關係或啟動先後順序等要求時,建議使用Docker Compose對微服務的相關容器進行編排。是否使用Docker Swarm來做集群化編排更新則由實際業務要求和團隊對Docker的熟練度來決定。

需要特別指出的是關於資料庫的處理,微服務架構通常強調服務的無狀態化,其中原因主要是為了服務的可複製性和可遷移性,所以目前的主流實踐是,資料庫在正式生產環境時,使用公有雲的獨立資料庫服務或自己機房的獨立資料庫伺服器的資料庫,不建議使用容器作為資料庫的宿主——但測試環境可以根據情況考慮使用,以方便模擬和測試各種情況。

生產環境的服務發現,考慮使用分散式服務發現和配置工具Consul。但如果微服務整體全部都是基於Docker的,而且集群使用等Docker Swarm實現的,那麼就不必使用其他工具來做服務發現了,因為docker swarm內置了服務發現機制。


根據業務和系統架構,拆分微服務

為每個微服務設計 RESTful Web API的文檔,建議使用API Designer工具,藉助於RAML語言設計API

根據API設計文檔,使用json-server來編寫API的Mockup

Web前端或App通過調用mock出來的api開發相關功能頁面,同時後端人員根據API設計文檔開發後端API,測試人員則根據設計文檔和mockup版的API表現編寫自動化測試腳本

構建服務定期從git伺服器上拉取最新代碼,根據項目的定義自動編譯、測試相關微服務,並通過Slack通知團隊或項目負責人;

構建服務在編譯和測試都通過後,通過腳本自動構建Docker鏡像,然後push到私有的docker鏡像庫中,並通過Slack通知團隊或項目負責人;

測試&&生產環境根據提前編寫好的腳本,自動從私有鏡像庫中拉取最新版的服務鏡像,部署運行對應的新服務


期間測試人員通過編寫的自動化API測試腳本不斷驗證服務的最終表現是否正確,不正確的不應該進入生產環境

單元測試是開發人員自行編寫的,但是需要明確測試的命令行調用方式,以便構建伺服器能夠不停的測試驗證代碼

每個用到資料庫的微服務都應該具備資料庫的自動化遷移能力,比如新增的表在服務啟動時應該會自動創建,而如果服務回滾到舊版本時必須能夠將資料庫對應回滾到原來的結構,比如刪除增加的表或欄位等。

前後端應該完全隔離在不同的鏡像中,在服務的總出口處(通常是nginx之類帶有反向代理的伺服器)將api和頁面集成到同一域名下

生產環境儘可能利用nginx伺服器的熱部署和熱更新能力

API的自動化測試,可通過如下nodejs工具開發測試腳本:

chakram

mock

mochajs


微服務有幾個要點:

功能獨立

獨立部署

獨立進程

可替換性

功能獨立容易理解,而難度是整體服務如何合理拆分,其基本原則就是看該服務的數據是否需要關聯另外一個服務的數據表才能查出,如果是則應該合併到一個服務中,否則可獨立拆分;獨立部署獨立進程告訴我們,每個服務運行在獨立的進程或伺服器中,每個服務都應該可以獨立部署,且不應該影響其他服務的運行;可替換性,則是說每個服務都應該可以隨時用任何編程語言重新實現並替換掉舊有的服務而不會影響其他服務和整體系統的正常運行。

鑒於每個微服務都可能隨時更新,為了保證整體系統運行的穩定性,我們需要至少做到如下幾點:

每個微服務的更新過程都要足夠的快,要儘可能在1秒內完成,以便減少服務更新時出現的各種異常

每個微服務調用其他服務時最後都具備retry機制,以便在調用到的另外一個微服務出現短期故障(比如更新服務)時,能夠具備過一點時間後再訪問的能力,這樣最前端的用戶或者服務調用者會認為當前的服務調用速度只是比原來慢了而已

集中的日誌收集服務,可以通過該服務的界面上查看到各個微服務的日誌,以便團隊或項目領導者能夠及時了解和分析系統的運行狀態,及時發現和修復各種問題異常

微服務架構的複雜性決定了微服務總體出現異常的幾率比單體系統要多,所以單元測試和集成測試變得極其重要,甚至可以說是必須的

每個微服務對外的服務介面(如WebAPI),應該都是具備普適性、自釋性、可預見性、明確性的。也就是:

每個微服務的對外介面實現可以不依賴於任何特定的語言

每個微服務調用另外一個服務時,都應該是儘可能使用通用的通信協議,而不是私有的,避免跨語言實現的難度,即通暢是使用HTTP協議

每個服務的最終路由地址是不可隨意變更的

每個服務的路徑自身就是其功能的最簡說明

通過一個api地址就能較為準確的猜出另外一個服務的地址和訪問方式

基於以上觀點,並假定我們大部分的微服務都使用、或編寫,那麼如下相關的庫和組件則應該是必須的或優先考量的:

NancyFx 這是一個非常優秀的Web框架,獨立於ASP.NET以外,也就是說他自身不依賴命名空間下的任何東西。具有極好的跨平台支持能力和極佳的可測試性、組件可替換性、路由可視性。用它編寫微服務,會讓開發過程變得很簡單。當然如果你實在不喜歡這套框架的風格,依然可以選用、、等相對傳統的技術,畢竟這並不影響微服務實現的本身。

Flurl 這是一個新出現的優雅的的Http客戶端庫,它依然基於,但是提供了風格的編程模型,所以寫代碼時會比傳統方式要爽快和高效的多。雖然RestSharp也是一個很優秀的訪問庫,但是它目前不支持等框架,所以跨平台能力欠佳。

xUnit.net 這是NUnit.net原作者幾年前重新打造的一個平台的單元測試框架,具有豐富的工具鏈。微軟官方的等框架也都使用的該框架編寫的所有單元測試,而沒有採用微軟自家的單元測試框架。

KestrelHttpServer 這是微軟官方實現的的Host伺服器框架,可以實現極高性能的服務,而不必依賴IIS。

TinyMapper 比老牌的AutoMapper具有更佳的性能(大概快60倍),而且老衣也曾貢獻了部分代碼增加了一些特性。不過目前對支持方面還有點瑕疵,但可以在項目中大規模使用。

Mapster 它跟TinyMapper一樣是新型的Mapper庫,號稱快速、有趣且激動人心的Mapper,老衣目前在項目中主要採用這個作為主要的Mapper庫。

Json.NET 平台下最流行的高性能(但不是最快的)庫。

Polly 是平台下,讓開發者可以輕鬆實現線程安全的、、代碼,大幅提升應用穩定性的絕對利器

C-Sharp-Promise Promise在js開發領域大行其道,深得開發者們的喜愛。C#程序員們可以用C-Sharp-Promise,使用Promise的方式編程。一些時候你會發現它比的方式更好

Topshelf 當你需要將一個.NET的Console或者桌面應用,作為Windows服務運行時,它會很好的幫到你。它還支持Mono,也就是說可以在Linux上玩

Dapper 輕量級的通用ORM,支持市面上大多數關係型資料庫。兼容、和


先確保和已安裝

如果上述命令顯示未安裝node.js,請到Node.js官網下載對應操作系統的版本,並安裝好。

確保已經安裝

如果上述命令未輸出版本號,提示命令不存在則,應該使用下面到命令安裝它

確保已經安裝

如果上述命令提示未安裝一個名叫的,則需要使用下面到命令安裝

上一步命令正常會輸出如下結果

按鍵盤的?鍵,直到出現在這一行後,按回車鍵

在後面輸入你的服務的名字(比如:)後回車。

提示: 由於這個名字會出現在代碼中,所以請使用類似的命名規範輸入,不要使用任何中文字元或,也不要是純數字。

假設上一步輸入的名字是,使用下列命令進入目錄,並使用打開該目錄

用打開後,查看修改文件中的為最新安裝的的版本。如果不知道當前安裝的是什麼版本,可通過執行下列命令查看

如果你安裝的是版,則此時應該會看到結果是。

此時把文件中version後面的版本號,改為剛才命令中輸出的版本號(例如)。

查看文件中的節點的值,如果你打算使用則應該是,如果打算使用則應該是。你還需要根據自己選擇版本修改引用的相關庫的版本。還要修改的值為你期望的程序集名,通常我們跟服務名一致,本例中應該是

這裡我們使用版來開發,那麼此時應該將文件的內容調整為如下:

注意:的版本號應該使用最新支持的版本。是編寫此文時的NancyFx最新版。實際操練時需要根據新的情況對應修改。

執行下列命令,載入依賴包、編譯並運行這個服務

會看到如下結果

在瀏覽器中訪問地址,可以看到。

這樣一個最簡單的級的微服務已經開發完成。其中文件就是這個服務的核心邏輯代碼:

是不是非常簡單呢_

目前這個服務看起來很美,但是存在如下問題:

因此我們需要藉助Docker這個容器工具來解決它,如果你不確定是否安裝了,請運行下面的命令確認

當然你也可以通過

查看docker的一些信息,還可以通過

查看已經到本地的鏡像列表,需要確認的運行時(編寫此文時的最新版本)鏡像是否存在,如果不存在請使用下列命令拉取鏡像:

拉取完畢後我們就可以準備構建服務的docker鏡像了

需要運行主機上安裝的sdk或者運行時

如果多個服務用的不同版本的則可能會出現版本衝突等問題

部署起來比較麻煩,需要用、、或等工具部署大量文件

基本不具備規模化橫向部署能力,比如一次性部署100個節點

一旦服務崩潰或其他異常退出時,無法自動重啟

在目錄下創建一個名字為的文件——注意:這個文件名是區分大小寫並沒有任何擴展名的

用或打開剛才創建的文件,並將以下內容寫入並保存:

提示:

表示該鏡像的容器默認的運行時時區為上海時區,這對於大陸的服務來說至關重要,不加這行默認情況一般都是時間,切記 表示該鏡像的容器默認向外暴露埠,這裡就是服務的默認埠 中的,為服務的主運行程序,不同服務這個地方會有所不同

之所以使用runtime版的基礎鏡像而不是sdk版,是因為sdk版的鏡像太大(大了幾百兆),對後的應用也是沒有必要的。

在目錄下運行下面的一組命令構建正式發布版的服務鏡像

使用命令查看是否有名為的鏡像出現在列表中。如果沒有,請檢查上面的這組命令是否輸出了什麼錯誤信息,修改代碼並重新執行上面這組命令,直到docker鏡像列表中有名為的鏡像出現為止。

提示

上面這組命令中hi服務被發布在dist目錄中,因此需要在中將目錄設置為忽略項,不做版本控制。

通過下面的命令執行鏡像:

此時會收到如下結果:

第1行告訴你運行環境是產品環境還是開發環境;第3行意思是你可以通過訪問本機的看到結果。但是這時候我們在瀏覽器中訪問,會提示你:。

在另外一個控制台窗口(Windows下叫命令行窗口)中運行下面的命令進入容器:

運行命令:

此時會看到輸出結果為,這說明hi服務可從內容內訪問,是容器外無法訪問。

輸入命令退出容器

打開文件,在下插入一行新代碼,即的代碼變為:

再次運行下面這組命令,重新構建hi服務的鏡像:

運行下面的命令臨時將鏡像以名為的容器運行:

打開瀏覽器,訪問,看到了。

這樣我們的服務容器鏡像就算成功了。

提示

中的是為容器起一個特定名字; 是讓這個容器在退出時立即刪除; 是為了將容器的埠映射到當前主機的埠上,以便在真機中可以測試訪問這個服務。 最終生產環境中不會以當前用戶的前置進程方式運行,否則用戶退出時容器就會結束運行。所以我們通常會額外附加參數讓服務在後台執行,詳情請參考Docker CLI的官方文檔。


前面,我們演示了如何使用docker將一個跑起來。下面為hi服務增加幾個複雜的API

增加一個服務狀態的api

在hi這個項目中增加一個新文件,內容如下

用下面的一組命令運行起hi服務:

用postman或非windows系統的命令行工具,訪問,會收到一個json數據,類似於:

但是,如果你用瀏覽器訪問你會收到一個錯誤頁,標題是,不過你看不到錯誤內容——讓你改一下代碼才能看到錯誤。

在hi目錄中新建一個文件,內容如下:

再次編譯運行,

用瀏覽器訪問,會看到一個很詳細的異常報告,意思是找不到名為的任何視圖文件。

這其實是Nancy框架的一個特性,他可以實現一個地址即是webapi又是網頁,其具體的原理就是判斷當前請求的中是否以開頭,如果是說明當前請求是一個瀏覽器,那麼Nancy就會使用當前地址返回的model類型名作為視圖名查找視圖文件,找到了就用類似於mvc的方式顯示視圖頁面,如果找不到就報錯。

如果我們不希望用這個特性,就是期望該地址永遠返回一個json數據,則需要使用方法。應該修改為:

再次編譯運行,

用瀏覽器訪問,我們會看到與在postman看到的一樣漂亮的json數據。Great!

準備一個資料庫,為了跨平台我們選擇PostgreSQL資料庫。當然了在計算機上安裝一個資料庫是很麻煩的事情,這裡我們用Docker直接用官方的鏡像運行起一個容器即可。執行下列命令:

此時我們就準備好了一個postgres資料庫,賬號是,密碼是,並可以通過本機的埠訪問到它。你可以使用pgAdmin鏈接並管理這個資料庫,老衣假定你已經學會使用pgAdmin的基本功能,才繼續下面的演練的。

使用pgAdmin在pgdb這個資料庫容器中創建一個新的資料庫

在hi項目上,從Nuget引用最新版的,先在中通過Nancy自帶的容器註冊一個資料庫連接:

然後增加一個文件,代碼:

之後在中增加資料庫可連接性的狀態檢測,代碼如下:

再次調試運行hi項目,然後訪問會收到類似於下面這樣的json數據:

其中表示資料庫可連接性狀態。如果你把資料庫容器停止:

再次調試運行,並訪問,會發現的值變為了。 嗯,腦袋聰明的你一定會想: 這個資料庫檢測的代碼應該封裝成一個方法,這樣就可以多個服務中都能方便做這個檢查了; 而資料庫連接字元串,也應該用配置文件。老衣在這裡先提示你這未必是好的,至於原因嗎,後面會有討論。

當然了,你也可以在這個api中增加CPU、內存等實時環境狀態數據,用於監控服務通過這個api定時獲取到該服務的相關狀態數據

增加一組簡單的新聞相關API

先確保資料庫容器處於啟動狀態:

在資料庫上建一張表:

在hi項目上,從Nuget引用最新版的和

在hi項目中,新建一個文件:

為了簡單期間,我把的定義放在了同一個文件中,實際項目中不應該這樣寫

即增加了3個API:

用postman向 POST 一條json數據:

收到說明添加成功,接著GET請求會獲取含有剛添加的新聞的數組json:

GET 請求 會獲取id為1的新聞數據json:

GET 請求 會獲取一個狀態碼為的json數據:

很棒啊, 3個API都表現正常了。是不是感覺用替代,用替代 寫代碼變得更暢快淋漓呢?嗯,不過也不是說這些替代就任何場合都會更好,這完全可以由開發者或團隊根據實際情況自由控制。 但老衣在這裡主要是想說,一些其他選擇也許可以讓你的開發變得輕鬆有趣一些了,甚至更多好處。

總之,以後我們也就可以使用以上類似的方式,很快速的創建其他微服務了。

所有新聞的列表

添加一個新聞

獲取指定id的新聞

嗯,到這裡不知道你是否想起了前面的資料庫連接字元串中,包含了 也就是說資料庫伺服器的所在地是本機。而我們的資料庫實際上是在另外一個容器中,只是因為我們運行容器時把本機埠和容器做了個映射,所以造成了資料庫在本機的假象。我們到底應該如何處理呢?一台生產環境的機器上可能會有多個資料庫容器,或者其他服務的容器,我們不能也不應該把所有服務的埠都在真實生產環境中上進行映射暴露。生產環境中資料庫容器或類似的涉及信息安全的容器,都應該儘可能不允許外部直接訪問,而是使用容器的相關通信手段。這樣一來,我們的hi服務訪問的資料庫應該是這個容器。所以在部署(非開發階段)應該將的值改為,並使用方式將hi服務的容器與進行連接,直接通過容器通信。改完資料庫連接字元串後,重新製作hi服務的容器鏡像

構建完成後,以容器方式連接並運行

訪問,收到

可以看出資料庫連接是成功的,很棒。即使你把pgdb容器的埠映射移除,也會發現hi服務仍可以訪問容器的資料庫,但是你的pgadmin就訪問不了,挺安全吧 :D 至於如何跨伺服器連接容器通信,這屬於高級話題,有機會再細聊或者直接查相關文檔和書籍研究一下。

看起來這時候我們用一個資料庫容器和一個hi服務容器實現了期望的功能,是不是完美了呢?當然不完美,因為不完美的人類永遠造不出完美的事物來,只能儘力無限趨向完美!(來自老衣語錄^_^)把資料庫容器也作為一個微服務,我們都知道:是個服務就有升級、更新、重啟或宕機的時候。我們希望資料庫容器中的資料庫因某原因出現崩潰退出時能夠自動重啟資料庫服務,以便達到整體系統的高可用度。docker運行容器時指定參數就可以非常簡單做到這一點,Great!看起來很美是不是,但請想一下如果用戶剛好在資料庫崩潰時訪問了hi服務,是不是就會收到伺服器端異常呢?就前面實現的代碼來說,答案是肯定的。那麼怎麼能夠讓用戶感受不到這中間的短時間資料庫失聯呢?前文中我們提到過領域有個很好的庫Polly,可以再遇到一些異常時實現。現在用它改造一下hi服務的代碼,讓新聞有關的幾個api實現資料庫鏈接異常時自動Retry:

先在hi項目上用Nuget引用,然後修改的代碼為:

編譯運行hi服務後,不要著急訪問news相關api,先模擬資料庫失聯:

等資料庫停止後,用瀏覽器訪問,你會發現瀏覽器一直在等待伺服器響應…… 立即再切換到剛才的命令行窗口,啟動資料庫容器:

再次切換到剛才訪問那個瀏覽器窗口,你會驚奇的發現有數據了,而不是返回資料庫異常!這就是的強大之處。當然了這個庫還有很多強大功能,請移步到官方網站查看文檔學習一下吧。

到這裡,聰明的你是否已經聯想到,其他情況一個微服務請求另外一個微服務的時候也可以用實現高可用呢?

用用OpenResty吧

OpenResty 是一款基於 NGINX 和 LuaJIT 的 動態Web 平台。你可以根據自己的需求設定啟用的模塊,並編譯生成自己定製的OpenResty。官方的Docker鏡像默認包含了一些模塊:

file-aio

http_addition_module

http_auth_request_module

http_dav_module

http_flv_module

http_geoip_module=dynamic

http_gunzip_module

http_gzip_static_module

http_image_filter_module=dynamic

http_mp4_module

http_random_index_module

http_realip_module

http_secure_link_module

http_slice_module

http_ssl_module

http_stub_status_module

http_sub_module

http_v2_module

http_xslt_module=dynamic

ipv6

mail

mail_ssl_module

md5-asm

pcre-jit

sha1-asm

stream

stream_ssl_module

threads

其中可以實現簡單的登錄後訪問某資源的功能,並且身份驗證和資源是分開的,具體介紹可參考http://ohmycat.me/nginx/2016/06/28/nginx-ldap.html;模塊則可以輕鬆實現實時縮略圖、圖片旋轉等,可參考 https://ruby-china.org/topics/31498 了解。其他模塊功能請自行Google吧。

OpenResty繼承了Nginx的高性能、反向代理等優點外,還支持使用Lua腳本編寫動態邏輯代碼,甚至是伺服器端視圖。這裡我們說一下如何用openresty簡單實現前面的新聞列表api的功能。

先在一個新建的目錄中創建一個Dockerfile用來創建帶有postgres訪問能力的openresty鏡像:

用這個文件構建一個鏡像(建議翻牆狀態構建,你懂的):

在另外一個新建的目錄(假設名字叫)中,新建一個文件:

在目錄中,創建一個文件:

在上一步創建的目錄中,創建一個文件:

構建這個鏡像:

連接容器運行上一步構建的鏡像:

用瀏覽器訪問你會看到跟之前我們訪問hi服務的新聞列表api獲得一樣的json數據。但這裡我們實際上只是在中加了幾行配置就實現了。更加簡單快速(雖然第一次準備支持postgres的openresty鏡像有點慢,但是這個鏡像是可以復用的,不必每次都重新構建)!訪問可以看到通過這個api獲取數據後綁定到前端頁面列表

如果我們先把之前的hi服務容器運行起來,並把前面步驟中的中到的配置改為:

然後再次構建鏡像,並重新運行這個鏡像的容器,你會發現效果跟第步一樣。只是原來上是通過反向代理訪問了上的新聞api而已。

至於如何使用openresty設置更複雜的反向代理、運行腳本等細節,請移步到http://agentzh.org/misc/slides/ngx-openresty-ecosystem/#1 了解一些相關特性,也到https://moonbingbing.gitbooks.io/openresty-best-practices/content/查看相關最佳實踐,一次學習終生受用。

用shelljs自動拉取代碼構建鏡像並推送Slack通知

你可能已經發現了,我們前面的內容中幾乎所有的編譯、發布、打包、容器的運行停止等都是用命令行來做的。原因就是命令行指令可以寫成批處理腳本,腳本並不涉及滑鼠點擊等人工干預,所以就可以讓機器自按照一些計劃安排自動反覆執行。我們在前面提到過的、等測試框架甚至、、等web前端打包工具也都有對應的命令行(CLI)支持,所以也都可以很方便的自動化執行。

我們選擇作為批處理工具的原因是使用熟悉的javascript語言寫比其他有很多額外的好處,比如更豐富的基礎類庫、工具鏈、依賴包等。

至於Slack的介紹前面已經講過,我們主要用它把機器和人之間的交互打通,讓機器積極主動的告訴人或團隊,一些代碼發生了什麼事情。

提示:

下面的例子代碼可能僅兼容MacOS或Linux,不支持Windows

準備 Slack 集成的WebHook:

假設你已經在Slack上註冊並創建了自己的團隊url是。那麼請登錄後訪問,在中添加真對您某個頻道(假設是)的配置,此時會獲得一個WebHook的Url,我們假設這個Url是。的使用方式可以查看 https://api.slack.com/incoming-webhooks

切換到hi服務所在目錄的父級目錄中

新建一個用於推送Slack通知的文件:

新建一個:

運行命令:

這個構建程序會每個一段時間(上面代碼中為60秒)拉取最新代碼,然後編譯、發布、打包docker鏡像、推送docker鏡像等一系列動作。

如果代碼沒有編譯通過,你會在Slack中收到一個來自機器人的消息推送;如果編譯通過、打包好新的Docker鏡像,推送至私有Docker Registry上後,你又會在Slack中收到一個來自機器人的消息推送。是不是很酷呢?團隊或項目主管可以第一時間通過Slack了解構建程序執行的情況。

生產環境中則可以用類似的方式定期從私有Docker Registry上使用的命令拉取最新hi服務的Docker鏡像,並用新的鏡像替換舊的。甚至可以使用或等做docker的編排和集群更新。這裡因為各自情況不同,老衣就不給例子代碼了,你發揮一下自己的想像力和編程能力吧。


有基於的國產API網關:Orange, 可以參考學習一下,因為中文文檔的產品對國人來說太好了

領域的很多優秀庫和項目可以參考https://github.com/thangchung/awesome-dotnet-core

(Actor模型)也可以實現一些場景的微服務,建議學習和了解一些成熟的框架(例如 Akka、Akka.NET、Orleans等);目前我比較喜歡的是Proto.Actor

zeit 是一家微服務領域很神奇的公司,開源了不少不錯的庫,比如pkg可以把nodejs項目直接打包成可執行程序,而不必依賴環境;micro 輕鬆實現基於的非同步HTTP微服務;hyper 構建在Web技術上的終端控制台;next.js 是在伺服器端渲染React應用的框架。仔細學習研究一下會有很多收穫的

Jint 是一個版的解釋器,它提供了對ECMA5.1的完整兼容,並且可以運行在任何平台上。由於它不會動態生成代碼,也不使用DLR,所以它可以很快的運行相對較小的js腳本。

NLua 是綁定世界和世界的項目。它可以讓你在Windows, Linux, Mac, iOS , Android, Windows Phone 7 and 8等幾乎任何C#應用中實現與的相互調用。

原文:http://yimingzhi.net/2018/03/lao-yi-de-wei-fu-wu-shi-jian-jian-yao-zhi-yin-2017-ban


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 dotNET跨平台 的精彩文章:

EF Core:一統SQL和NoSQL資料庫
Blazor正式成為Microsoft官方.NET 和WebAssembly項目

TAG:dotNET跨平台 |