緊接上篇 TFS在項目中Devops落地進程(上)html
再接着說TFS相關以前先插入一個番外篇,雖然跟TFS關係不大但跟DevOps關係很大,以爲有必要在此亂入一下。前端
咱們以前並無任何監控類產品(我指的是應用程序級別的),發生任何異常都是往數據庫的表裏insert個錯誤日誌,all系統共用同一張錯誤表。git
這其實意味着咱們當時的系統是:系統異常基本不關注(線上數據庫開發確定無法查對吧),關注的時候確定都出事了,對本身負責的系統的運行狀態基本不瞭解,什麼性能之類東西純粹靠猜。程序員
而後我就但願咱們能有辦法獲取到咱們系統的各類狀態,而此時在VS2015的時候整合在VS裏的application insights引發了個人關注。github
簡要介紹下application insights,是微軟基於azure所推出的一款SAAS性質的APM(Application Performance Management,應用程序性能管理)服務,本人不會詳細介紹這個,詳情可參閱官方文檔。shell
而後也感謝我大學年代曾經當過MSP(微軟校園菁英)並透過這個拿到過Visual Studio Enterprise的訂閱,而後裏面附贈的每月150美圓額度的Azure費用,讓我有條件能夠先試用Application Insights。數據庫
而後本身將本身負責的站點搭上Insights作了個小Demo展現了給老大看,而後老大也對此表示滿意。緩存
(Application Insights的概覽圖)服務器
在後續的一次PMO會上我將此拿出來進行了演示,也得到了CTO的承認和支持,而後終於能夠將Application Insights投入到線上使用(固然此時用的是公司正式的帳號而不是我那個150刀每個月的測試號了)。網絡
可是有Insights投入初期其餘小夥伴熱情度並不高,你們仍是以爲記數據庫挺好的,直到後面發生了一件事…
事情是這樣的,那是一個要常規發佈的夜晚,由於並無數據庫相關的修改,因此DBA已經下班了(要加班到夜裏發佈,DBA只是正常下班),而後某站點發布上去的時候報錯了,而後對應的開發小夥伴不知道爲何,就知道出異常了。
而後此時DBA不在,沒法查線上數據庫,而後就乾着急,最後經過在代碼裏讓異常本地寫txt臨時解決了發佈上的問題,但這個問題完整暴露出記錄數據庫的不靠譜:萬一DBA不在呢?畢竟若是沒數據庫內容的話總把DBA留下來的話其實也不合理,咱們應該要從更長遠和更科學的方案解決這個問題。
至此後續咱們全部項目加入Insights的進程就加快了,由於Insights裏咱們能夠自主的查看到性能/請求/異常等各類數據了。
另外有了Insights後咱們開發本身第一次有了本身的程序運行數據,有時候咱們也會針對Insights裏的數據作一些對應的優化。
如上圖,這是一個經過城市Id獲取城市名稱的接口,原先調用量巨大(當時設置了50%採樣率,因此實際調用量要比圖中翻一倍)可是其實這個接口返回的內容可變性不高,而後讓前端加了緩存後從原來至少10K以上每小時調用量降低到如今100多的調用量,而這些都是由於咱們有了Insights以後才能進行的。
因此說:優化不能靠猜,咱們要用數聽說話。
而Insights的Analysis功能/智能預警功能等特性也在實際中幫咱們解決了很多問題。
而後Insights也是能夠跟TFS進行必定程度的整合的,其中主要包括自動發佈的時候打上註解和在TFS的面板裏查看Insights的信息
版本註解,有了這個咱們能夠從監控系統裏知道何時上了預發佈環境
可添加在TFS上的widget(新版本的,詳情可參看Application Insights: VSTS dashboard chart widget now available)
而後最近Insights裏還有各類Preview的功能,好比新的Preview性能面板裏能查看到95線/99線等,新的異常面板裏還能給你分析出你異常的共同點之類的,Insights也一直在進步着。
在定型監控系統的時候咱們曾經議論過聽雲和是否自建服務端(當時肯定了監控的SDK都是用Insights的,可是糾結因而否基於ELK自建服務端)
聽雲:
老實說從默認的圖表來講,聽雲比Insights的圖表更全面,但聽雲缺少一個Insights裏有的一個很重要功能,查詢分析Analysis:
在Insights的Analysis裏,能夠經過一個長的很像Sql的一種語句,能夠快速查詢你想要的任何原始數據(精確到每一條),此語句也能繪製圖表,這個絕對是對程序員Friendly的一個功能
比方說出了異常,可能從運維層面更關注異常的趨勢,而開發層面更關注的是具體的每個異常,和每個異常對應的每個請求等,另外聽雲由於是服務器層面的監控沒法在代碼層面埋點,咱們Insights裏則埋了若是異常的話將錯誤請求的Body記錄到Insights的Traces裏,這樣就算是Post/Put之類的請求報錯咱們也能拿到原始請求報文。
自建服務端:
關於這個我以爲在咱們如今連Redis啊隊列啊這些更緊急的東西都沒有落實的狀況下在分出人力去搞這個,就擔憂作出來後就是個永恆的1.0版本,以爲相似這種東西除非說有專職負責這個的人/團隊否則不該該自建,再說那個時候咱們組已經用Insights好一段時間了(有接近1年了吧)習慣了上面各類高級特性,而原始版的ELK則呵呵噠(一個自個買的原始毛胚房VS一個租來的豪華精裝房),固然若是有專職人員專門投入到上面基於ELK作定製開發我相信也確定能作的跟Insights那樣或者比Insights更好,可是,咱們有更多更緊急的事不是麼?
不過卻是有一點是由於費用問題咱們的Insights是使用了採樣率的(就是說並非收集所有而是部分收集),可是咱們但願異常不要被採樣,因此後面可能要基於ELK搞個Exceptionless來專門記錄異常。
另外Insights跟VS的整合也是棒棒噠,好比下面這樣,直接告訴我哪一個方法發生了異常,直接反映在CodeLens裏
原先整個TFS服務器的搭建和維護都在運維那邊,那爲何要拿出這個來講呢?
首先咱們如今正處於一個快速發展的年代,什麼框架啊每個月總能冒出幾個,技術各類突飛猛進,雖然絕大多數企業本着穩定至上的原則不會說老是用最新,但這不是固步自封,不思進取的藉口,在一個「最新」變爲」穩定「以後總要試着跳出溫馨區步入現代化進程吧?
而後咱們遇到的第一件事就是.Net版本升級,咱們計劃升級到.Net 4.6.2(原來是4.0到4.5.1不等),而後由於自動打包的緣由因此要求Build Agent也要升級,而後原先運維部署配置的TFS是服務器+Build Agent放在同一個機器上的,搭載的是VS2015.
而後除了4.6.2以外的話咱們有個別類庫項目使用上了.Net Core裏全新的xproj格式來進行多target framework的開發,這也要求服務器上要有.Net Core的Sdk。
在另外此時在討論到代碼質量審覈,而後咱們初定使用Sonarqube,而這個也要求Build Agent服務器要有Java的功能。
基於上述緣由外加後面咱們技術部某神祕人物毛哥批了一批(2臺)服務器(也就通常工做電腦)資源給我,後面還有CTO批了一臺大服務器(真·服務器,當時但是嘻嘻噠的心裏),而後我開始本身搭建Build Agent。
當前咱們組自行維護的4臺Build Agent,承載了包括持續集成,自動打包,代碼分析,自動測試等一系列任務
裝上了一堆如今要用或未來但願想用的功能,知足當前及其可預見的一段時間內的需求
其實關於Build Agent主要以爲這個必需要能適應開發組的步伐,首先咱們.Net 4.5->.Net 4.6.2的時候,要求Build Agent要支持.Net 4.6.2或以上,以後咱們有計劃要上.Net Core(此時已經有基於.Net Core項目的Dll包了),並且以後.Net Core還有2.0版本(主要是NetStandard 2.0),因此我以爲這個Build Agent在咱們組內的話咱們能更好適配咱們的前進步伐。
如今咱們的Build Agent裏裝的是Vs2017 17.3 + .Net 4.7 + .Net Core 2.0 + Docker 17.03.2-ee + CMake 3.9.1 + Python 3.6.2(x64) + JMeter 3.0 + F# 4.1 + Node.js 8.4(x64) + Java 1.8
估計小半年內基本都能知足需求。
接着上篇說,咱們有了本身的Build Agent,而後自動發佈之類的基礎功能也有了,因而咱們就有更高層次的自動化追求了。
首先就是自動化代碼質量檢查,在此先聲明一點:任何自動化代碼質量檢查工具都不能代替人肉的Code Review,但能減小人肉Code Review的工做量。
而後在選型上咱們選了Sonarqube,固然大家會問爲何選Sonarqube,說來慚愧其實我以前並不瞭解相關產品,而後在TFS商店裏看到了這貨而後才知道還能自動化代碼檢查…而後就去研究這貨,發覺整體還能夠(規則之類的啊,還有跨平臺等),在跟咱們技術部神祕人物毛哥上報下技術選型得到認證後就拍板開始幹。
經過本身手頭有的服務器資源,搭建了個Sonarqube服務器,而後經過TFS的任務加上去
一個帶Sonarqube分析的編譯過程,做爲C#程序員看上去好像一個using的結構(開始->釋放)
某項目分析結果
好,而後代碼分析質量有了,你們就能照着上面去「優化」代碼了。
慢着,我寫了一段代碼,由於水平問題我也不知道有沒有咖喱,而後一提交,而後上面就留下了一個永恆的污點(有歷史記錄的),這樣確定很不爽,因此後面咱們就糾結有沒辦法可以讓代碼在進入到Sonarqube系統以前先有個反饋。
而後此時微軟就發佈了TFS2017,具體參考 TFS2017RTM Release Note
其中它引入了這麼一個功能
在拉取請求的時候顯示Sonarqube的分析結果(直接定位到你代碼上),且該分析結果不記錄到Sonarqube服務器裏
接着慫恿下老大出面讓運維那邊幫忙升個級。
而後爲了配合Sonarqube,那麼每一個項目在Pull Request的時候都要進行編譯的過程(編譯了Sonarqube才能分析),所以也順帶加上了阻止合併不能編譯的代碼這個額外附加項。
贊成一次Pull Request須要一個非本人外的其餘人贊成且要編譯成功
而後審覈人也能看到Sonarqube分析的結果就不用每行仔細看也能大概知道個因此然。
固然實踐過程當中,看別人的代碼發現很多什麼超過3重if嵌套啊,類超過1000行啊這些,他們總說因爲某些緣由實在很差改的,那就只能忍了(你能怎麼辦呢,特別是多重if的每每都是各類業務條件判斷複雜,而後本身也沒空深刻去看他們的業務),但本身項目要求要嚴格點,要嚴格控制不能出現任何形式的咖喱。
另外在此吐槽一點:TFS不能直接在Dashboard裏瀏覽Sonarqube的結果,要看Sonarqube結果還要跳到Soanrqube裏去,這不符合All in one的TFS理念啊,就沒人想過弄個Widget什麼的來解決解決這個問題?
自動測試在這裏想主要分2塊來講,單元測試和集成測試。
首先我以爲對於這2個概念儘管有很官方的說明但實踐中不少人都有本身的理解,我簡單說下我本身對上述2個詞的理解和定義
單元測試:在代碼內部進行的不依賴外部環境(網絡/數據庫等)進行的對某個方法級的測試,特色是隻能測試一小塊邏輯,能模擬數據且運行較快(毫秒級),代碼執行結果可預測。
集成測試:多是代碼也多是腳本依賴外部環境(網絡/數據庫等)進行的針對某個流程上的測試,特色是要造數據且運行較慢(至少是秒級),代碼執行結果絕大多數狀況下可預測(受外部因素影響不能100%可控)。
單元測試:
要讓代碼能夠被單元測試,首先代碼先要是可測試的,要如何作到代碼可測試呢?答案很簡單,隨便街上抓一個僞計算機專業的都能給出你正確答案:解耦。
可是你要真的落實「解耦」到你的代碼裏,又每每是一個異常艱鉅的任務(Talk is cheat, show me the code)。
首先在我本身負責的項目裏,徹底使用依賴注入的形式重構了,另外抽象出了各類各樣的接口,理論上要作到全部的」Service「都是能夠」被替換」的。
嚴格限制對static和new這2個關鍵字的使用(絕大多數狀況下static或者new都意味着不可測試,固然static一個數據無關的方法好比Math.Min之類的或者new一個純數據類這些例外)
在本身一番折騰下,如今本身負責的項目單元測試覆蓋率70%+,也算是一個本身比較滿意的數字了(這個是Resharper收集的,它將單元測試項目自己也包含進去了的)
在單元測試的加持下,本身想重構代碼什麼的都能放開手去重構,有沒有影響老邏輯?測試跑一下就知道了。
而加新邏輯的時候也能知道會對原有流程形成怎麼樣的影響。
總之有單元測試後,你會對你的代碼更加倍有信心。關於單元測試看看往後是否專門開一篇文章來講說,裏面也有大學問。
上面說了那麼多單元測試,那麼它跟TFS有啥關係呢?測試寫完了是吧?你怎麼能確保它必定是有在跑呢?這時就能夠將單元測試的運行整合在自動編譯的流程裏
整合到編譯流程裏的單元測試,每次跑完後會報告結果,若是單元測試失敗那麼會阻止pull request
在TFS主頁的Dashboard裏展現單元測試結果
集成測試
咱們的集成測試如今主要是QA那邊負責,QA那邊有基於Jmeter來進行的測試,具體細節由於不是我負責因此我不是特別清楚,可是在Build Agent裏裝好Jmeter後(QA配置好了各類他們要的插件的版本)而後在自動發佈的時候運行下就行了
運行QA他們指定的Jmeter,先從一個位置拷貝配置文件過來而後運行命令行,沒錯,從TFS角度去理解的話它只是去執行個命令行而已
不過當前QA他們弄的Jmeter是運行後發一個結果郵件,若是可以將Jmeter的測試結果轉變爲TFS可接收的某種測試結果格式(什麼JUnit或者Xunit之類的測試結果)展現到TFS上那就更好了(若是有會的人請賜教)
在集成測試方面我本身也有一套基於代碼的(固然如今主流都是基於腳本了)
基於Specflow+xunit的方式我本身作了幾個我旗下項目主流程的測試用例(就是那種一出問題QA就郵件出來:」測試環境掛拉「的那種)
基於Specflow的BDD形式的描述文檔,儘量弄的貼近業務層面
描述文檔背後對應的是若干代碼
目前我本身這套集成測試僅放在Demo環境(第一個測試環境)使用,主要是一旦發覺個風吹草動,立馬還原代碼…(逃…
關於集成測試按道理此處應有以Selenium爲表明的UI自動化測試,不過我本身主要負責的是接口,而後讓折騰UI的那位同事目前也只是處於演示級階段還沒正式投入使用,此處就不獻醜了。
固然TFS上還有管理手工測試等各類功能,不過因爲QA組是基於Jira來管理任務因此並沒使用。
儘管咱們當前在通過一番折騰後全組項目目前已經統一到.Net 4.6.2,但短期內也不會用上NetCore,但背後一直爲了NetCore的遷移在默默準備着。
主要是考慮到在NetCore 2.0後出了個NetStandard2.0,它跟NetCore 2.0以及.Net Framework 4.6.1是兼容的。
那麼咱們如今項目代碼的目標都是兼容Netstandard2.0(底層類庫),但以後真要遷移的時候就改個TargetFramework以及表現層稍微改下就行了(嗯,很豐滿的理想)。
說這篇呢主要是分享一個,咱們如今TFS是2017Update2,在這個版本下你用常規方法是沒法引用任何Netstandard2.0的包的(不信大家試試)
其本質是由於TFS2017Update2自帶的Nuget還原工具是4.0版,而4.0是不支持NetStandard2.0,要4.3才能夠,那難道咱們在現有的TFS下(2018又沒Release)就拿NetStandard沒轍了?
而後就找到了這篇文章Using the latest NuGet in your build
在這篇文章指引下,將它 那堆Powershell腳本 粘貼上去執行,下面參數寫個4.3.0
而後使用自定義的nuget
而後就迎來了勝利的曙光
任務管理
雖然我司一直是基於Jira作任務管理的,不過由於Jira並不能直接跟TFS上的代碼進行關聯,因此我私自上是喜歡在TFS裏建對應任務而後關聯上去
還能跟代碼裏結合起來
在TFS裏也能作可視化的關聯查詢
自動備份分支
這是最近折騰出來的小玩意
在Release里加上這個步驟(這是個插件提供的,插件詳情請點此處)
而後在執行到對應發佈步驟的時候就會自動將當前發佈的代碼拉一個分支出來,全自動的喲。
上面的大概就是咱們如今折騰TFS的成果,但咱們的道路遠沒結束,或者說,如今又處在某種程度上的開始。
首先,Docker這個大趨勢確定以後或多或少都要涉足進去的(不過以爲先將諸如服務發現之類的前置條件先搞定在作這個)
還有撇了下隔壁TFS2018的Release Note,這回引入了Wiki功能,回頭可能能夠直接在TFS上直接寫上各類知識庫文章了
還有想整個OWASP ZAP而後跟TFS流程整合下來個自動滲透測試分析什麼的,讓咱們自動化更上一層樓(if有空弄的話)。
大概就是扯那麼多了。
The End。