TFS在项目中DevOps落地进程(下)
緊接上篇?TFS在項目中Devops落地進程(上)
再接著說TFS相關之前先插入一個番外篇,雖然跟TFS關系不大但跟DevOps關系很大,覺得有必要在此亂入一下。
番外篇--監控之Application Insights
我們之前并沒有任何監控類產品(我指的是應用程序級別的),發生任何異常都是往數據庫的表里insert個錯誤日志,all系統共用同一張錯誤表。
這其實意味著我們當時的系統是:系統異常基本不關注(線上數據庫開發肯定沒法查對吧),關注的時候肯定都出事了,對自己負責的系統的運行狀態基本不了解,什么性能之類東西純粹靠猜。
然后我就希望我們能有辦法獲取到我們系統的各種狀態,而此時在VS2015的時候整合在VS里的application insights引起了我的關注。
簡要介紹下application insights,是微軟基于azure所推出的一款SAAS性質的APM(Application Performance Management,應用程序性能管理)服務,本人不會詳細介紹這個,詳情可參閱官方文檔。
然后也感謝我大學年代曾經當過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里
?
第4篇--自行管理BuildAgent
原先整個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
估計小半年內基本都能滿足需求。
?
第5篇--自動代碼質量檢查
接著上篇說,我們有了自己的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什么的來解決解決這個問題?
?
第6章--自動測試
自動測試在這里想主要分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來管理任務所以并沒使用。
?
第7章--引入NetCore的打包
盡管我們當前在經過一番折騰后全組項目目前已經統一到.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
然后就迎來了勝利的曙光
?
第8章--我們基于TFS的小折騰
任務管理
雖然我司一直是基于Jira做任務管理的,不過因為Jira并不能直接跟TFS上的代碼進行關聯,所以我私自上是喜歡在TFS里建對應任務然后關聯上去
還能跟代碼里結合起來
在TFS里也能做可視化的關聯查詢
自動備份分支
這是最近折騰出來的小玩意
在Release里加上這個步驟(這是個插件提供的,插件詳情請點此處)
然后在執行到對應發布步驟的時候就會自動將當前發布的代碼拉一個分支出來,全自動的喲。
?
第9章—VNext
上面的大概就是我們現在折騰TFS的成果,但我們的道路遠沒結束,或者說,現在又處在某種程度上的開始。
首先,Docker這個大趨勢肯定之后或多或少都要涉足進去的(不過覺得先將諸如服務發現之類的前置條件先搞定在做這個)
還有撇了下隔壁TFS2018的Release Note,這回引入了Wiki功能,回頭可能可以直接在TFS上直接寫上各種知識庫文章了
還有想整個OWASP ZAP然后跟TFS流程整合下來個自動滲透測試分析什么的,讓我們自動化更上一層樓(if有空弄的話)。
大概就是扯那么多了。
原文地址:http://www.cnblogs.com/leolaw/p/7847062.html
.NET社區新聞,深度好文,歡迎訪問公眾號文章匯總 http://www.csharpkit.com
總結
以上是生活随笔為你收集整理的TFS在项目中DevOps落地进程(下)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 处理ASP.NET Core中的HTML
- 下一篇: 大叔公开课~微服务与持久集成