微軟開發部門 DevOps 經驗談 (四) - 從使用者經驗中學習

本文接續:

微軟開發部⾨ DevOps 經驗談 (一) - 從 Agile 邁向 DevOps

微軟開發部門 DevOps 經驗談 (二) - 從經驗中學習

微軟開發部門 DevOps 經驗談 (三) - 為 DevOps 量身打造的系統

今天要來談的是如何從使用者經驗中學習。


從使用者經驗中學習

我們盡可能讓所有開發的功能,都能提供良好的使用者體驗,就算這是件相當困難的事。舉例來說,我們花了很多功夫讓服務達到 99.9% 的服務可靠度 (SLA, Service-level agreement),但我們並不因此而滿足。

我們的目標並不僅僅只是 SLA,而是希望提供 100% 完全沒有缺點的服務。這也代表著我們必須要對發生機率是 0.001% 的例外狀況斤斤計較。由於異常狀況經常會隱藏在監控的數據之中,我們甚至為此改寫了三次計算 SLA 的演算法,來讓我們的監控標準更加的嚴謹。參考下圖一,在一開始,我們使用外部進入測試,來判斷服務是否正常運行,如圖表中的虛線所示,我們的第二個演算法是觀察所有使用者進行的操作指令中,失敗和執行緩慢的數量比例,來判斷是否有功能發生異常,你可以參考圖表中的失敗和緩慢指令數量。在服務成長之後,由於使用者數量過多,也可能會讓問題被隱藏在相對大的系統數字之中,目前我們的作法是計算每分鐘遇到問題的使用者數量相對於每分鐘所有使用者數量,作為判斷系統是否有異常的指標,如圖中黑色現所示。

圖一、呈現了計算SLA的三種演算法,外部進入測試沒有找到任何的異常,追蹤指令執行狀況呈現了有一小時發生執行緩慢的狀況,而在使用者異常相對比例中更反映了有三小時的執行緩慢情形發生。

如同你所看見的,在四個小時的週期中,第一條虛線顯示沒有異常,第二條線顯示大約有一小時的異常,而第三條線卻顯示了有三個小時服務的效能是十分糟糕的。其實我們沒有必要這麼嚴格的設定線上數據觀察的機制,但我們為了提供給使用者更好的服務品質,對每一個數據都會更嚴格的要求自己。

注重安全性

在我們服務的其中一個安全標準中,要求了我們必須確保服務能夠保護使用者隱私,確保資料安全,在提供穩定服務的同時維持安全品質。以前我們開發地端版本的軟體提供給客戶使用時,就曾經在軟體的安全性上下了不少苦工,甚至會假設如果服務被入侵時,要怎麼自動偵測或判斷服務的安全受到了威脅。

除此之外,我們使用擴展單元來部署服務的方式帶來了一些額外好處,SU0 除了作為我們服務的第一個部署單元之外,還可以透過它來進行安全演習,強化驗證並我們服務的安全性。我們會使用這個擴展單元來舉辦一些類似“遊戲日”的活動,例如在內部舉辦安全性比賽,看看服務是否能夠抵禦入侵,而使用 SU0 更大的好處是不會影響正在使用我們服務的使用者們!

不同的部署方式

在我們開發地端版本提供給客戶使用的軟體時,我們花了十分多的精力調整開發系統和流程,想辦法讓客戶使用軟體遇到異常的時間降低,換句話說,由於產品提供給客戶之後,萬一客戶在使用時發生任何的異常或問題,要處理的成本都會變得十分的高,所以我們必須要在提供給客戶前就盡可能的降低問題發生的機率,避免我們常常要發行修正更新給客戶來解決異常,也避免造成客戶對我們的軟體有不好的印象。

DevOps 以及服務的雲端化改變了我們的思維,我們要考慮如何盡可能降低修復問題和重新部署到線上服務的時間,這也讓我們有了不一樣的目標,同時必須還要考慮修復問題、發現問題、找到原因以及學習改善根本原因的時間

我們還想到在設計時必須多為了彈性做考量。線上服務可能會因為周邊相關的系統中斷而導致異常,尤其是在使用量尖峰時段很容易發生,但既然是線上服務,就必須將使用上的影響降到最低,並搭配對應的重試機制,例如使用 Circuit Breaker 模式。我們也要盡量避免使用者在重試期間可能造成的不當操作,這點可以透過類似 Chaos Monkeys 模擬使用者亂點的行為來進行測試,這套軟體是由 Netflix 所開發。

另外,災難復原機制也是相當重要的,像是在內部舉辦 “遊戲日” 活動時,侵入的行為可能會把服務打掛,因此我們必須要事先準備好相對應的機制來應付突然的異常或是任何意外造成服務中斷。

開放程式碼

我們提高了參與 Open Source Software 社群的比例,OSS 鼓勵人們建立可分享、可重複使用及容易搭配的服務或產品,並且盡可能的讓產品低耦合,鼓勵跨服務結合使用,但保持服務各自獨立發行。

如果有 OSS 的解決方案可以滿足我們的需求,我們會希望可以直接使用它,而不是再發明一套新的。如果我們開發了一些用途比較廣的軟體,我們也希望能夠分享

它。我們會獎勵開發出好用元件的工程師,鼓勵公司所有人使用那些好用的元件。任何公司內的工程師都可以對所有公司的產品提出改善的意見,同時,在公司內部我們提供所有公司產品的程式碼,以及完整的產品支援。

學習的好時機

只有在徹底了解問題發生原因並解決之後,才能夠視為處理完成。我們同時還會使用 “5 Whys” 方法,試圖從各種不同的面向了解下次如何做得更好。每當發生問題且影響客戶使用時,我們的管理負責人 Brian Harry 就會發佈一篇部落格文章詳細解釋問題發生的原因,以及我們學習到的教訓,這也替我們的線上異常提供了一份公開的紀錄,驅使我們持續改善。

我們也會透過客戶對於這篇部落格文章的反應,當作我們改進的參考,在文章中描述了服務的不足之處,客戶也感謝我們願意分享這些異常的處理及說明。透過透明化的方式,讓我們與客戶之間並不只是商人與顧客的關係,而擁有更深層更良好的互動。

經營與開發緊密結合

在過去,我們不容易統整經營和開發這兩者的考量,這也是因為我們所做的決定通常必須經過很久才能看到成效,但 DevOps 改變了這一切,我們希望能夠持續的讓使用者體驗更好,我們會從使用者一開始使用我們服務就開始了解使用者使用的狀況,不管是透過網路調查,或是其他試驗的方式,也會透過遙測技術觀察所有的數據,甚至是透過和使用率高的使用者進行 1 對 1 訪談來了解使用者的想法。

由於我們的服務提供了許多的功能,為了提供使用者更好的使用體驗,我們會假設使用者實際使用這些功能的動作,例如開啟網頁、註冊帳號,或是部署程式到 Azure 上,還是進行其他的動作。如果我們對於使用者進行操作步驟的轉換率不滿意時,我們會透過假設的方式來思考如何改善,調整功能進行實驗並收集數據分析結果,並且會只專注在有調整功能部分的數據,盡可能不讓它被服務的其他面向調整所影響,我們對於數據的有效性非常的謹慎,設法不要讓自己淪為追求成長的假象。

在分析數據時,如果可以和使用者的反饋一起分析會更加有效。我們使用了很多種方式來收集使用者的反饋,其中一種最有效的是“高用量使用者計畫”,我們鼓勵自願的工程師每個月和一位高使用量的使用者進行訪談,了解使用者的意見,這也幫助我們了解使用者喜歡和討厭什麼,希望的功能或是感到困惑的地方,這些都是靠數字無法告訴我們的。同時在我們內部有一個“嘗鮮”小圈圈,其中大部分是 MVP 或和我們比較熟的客戶,我們幾乎每個禮拜都會透過網路開會來分享對於服務的新想法。他們會通過 StoryBoards 的方式,提供對於流程的想法和意見,並且在開始實作之前提供對於項目優先程度的想法。另外,我們也有使用類似 uservoice.visualstudio.com 的方式,讓所有人都可以提供意見和對想要的功能進行投票。

學習: 邁向卓越的實踐計畫

在我們轉換到 DevOps 之後,我們將成長歸納到七個面向,我們也認為即將迎來使用敏捷開發趨勢的第二個十年。

圖二、圖中的七個區域是我們為了更好的專精於 DevOps 上,所訂定持續改善實行的目標

  • 敏捷的規劃與團隊 - 這其實也是敏捷精神的延伸,但更加的輕量化。我們擁有更多面向的功能開發小隊,保持 Product backlog 的精神,最小化工作內容,並且在每個 Sprint 結束之後,將完成的項目即時部署到線上服務。 
  • 技術債務的管理 - 所有遺留下的技術債務都是風險,可能會產生預期之外的工作項目,例如線上服務的異常必須要及時的被排除,也有可能會影響預期的工作產出。我們非常謹慎的對待技術債務,並且在技術債務影響我們的產出或品質之前,就安排計畫將它排除。(有一次我們誤判了情況,就是在之前所提到的 VS2013 發表事件,但我們盡可能的保持資訊透明) 
  • 執行有價值的項目 - 我們的 backlog 項目會根據使用者所希望的功能,以及項目上線之後帶來的價值,來決定項目對我們的重要程度。從十年前使用敏捷開發時我們就很重視這些,但今天透過 DevOps 的遙測技術,可以透過實際測量項目所帶來的成效,以及需要進行的改進方向。
  • 基於假設的 backlog - 在導入 DevOps 之前,我們的 Product Owner 會根據使用者的反饋,挑選出對產品有幫助的項目加入我們的 backlog 之中。而現在,我們的 backlog 是由一系列的假設組合而成,根據所收集到使用者使用的數據,猜測能夠滿足使用者需求的項目進行實驗,再根據上線後所收集到的數據來分析我們的假設是否正確。根據這些結果,可以決定我們是否要繼續朝這個方向開發,或是應該調整我們所假設的方向。 
  • 數據與驗證 - 我們盡可能的讓一切都數據化,不僅僅只是服務是否健康運行、可靠度或是效能,我們還會收集軟體品質的分析,嘗試了解使用者的使用狀況,以及觀察假設性項目的結果是否理想。舉例來說,我們可能會根據使用者體驗做一些實驗性的調整,再測量這些調整對於流程轉換率的影響,我們會一起根據使用者實際使用狀況,來假想如何讓使用者擁有更好的使用體驗。 
  • 重視線上環境 - 只有在服務維持著高品質的時候,我們所收集的資料才有意義。所以我們會不斷的追蹤上線服務的健康狀況,找出每一個問題發生的根本原因,並監測我們的效能是否理想,找出導致功能緩慢的原因。 
  • 雲端化 - 要能夠讓我們的服務 7x24x365 不斷穩定的運行,只有不斷的改善優化服務架構,讓系統之間互相獨立,不要彼此依賴,並且使用更加具有彈性的公有雲服務。當我們的服務需要乘載更多的流量時,我們所使用的雲端服務就會提供延展的彈性 (我們使用的雲端平台是 Azure)。所有的新功能我們都會進行雲端版本的開發,完成之後再進行地端版本的產品化,包含了一些企業應用的處理,但相對來說就比較沒有那麼容易進行延展,我們也會從日常的使用狀況得到持續的反饋,來進行產品的改善。

其實我們可以說 DevOps 是敏捷開發精神進一步的延伸,打破了以往開發與營運難以合作的界線,讓敏捷開發的內容與現實生活更貼近。除了保持著敏捷開發流程之外,現在還會更進一步的讓使用者現場與開發工作更加的緊密,透過收集使用者數據與各種遙測技術,我們能夠更加了解使用者想要的功能,讓產品符合市場需求,而不僅僅只是假設,也會透過持續改善的精神,不斷的推陳出新,讓產品具有更好的競爭力,提供更棒的使用者體驗。