只有累積,沒有奇蹟

顯示具有 讀書心得 標籤的文章。 顯示所有文章
顯示具有 讀書心得 標籤的文章。 顯示所有文章

2022年5月1日 星期日

[Architecture] 架構設計 - 限流策略 Rate Limiting Strategies

前言
這一篇是紀錄閱讀 超大流量分佈式系統架構解決方案:人人都是架構師2.0 的讀書筆記,筆者在書中有介紹在面對大流量的請求洗禮時,常見的手段有以下幾種方式
  • 擴充
  • 靜態化
  • 限流
  • 緩存
  • 隊列
這篇文章是介紹上述方案中的限流方案章節筆記,在整理時內容加上自己理解的說明與圖片,其中若是自己有理解不正確的地方是錯誤的部分歡迎各位高手一同討論或給予指導


為什麼需要限流
大型電商網站主要技術挑戰可能來自短時間內客戶忽然的大流量與短時間內的高併發請求,像是之前大家在搶購的 Switch 動物之森主機(搶三次都沒搶到 怒),或是最近吵得很紅的 PS4 造型悠遊卡(搶不到again,怒怒),如果系統不對流量進行合理的管制,任意地讓所有的請求流量在短時間內衝擊系統,可能會導致一連串的問題發生,像是原本設定的 cache 機制因為超過負荷被撐爆、主機連線資源被耗盡,資料庫要處理大量的請求而造成回應時間變長,最後系統很有可能發生雪崩效應(Avalanche effect),造成服務的中斷。任何一個系統的容量都存在著上限,一旦用戶請求量過載超過上限,系統的吞吐量便會逐漸開始下降,流量管制的目的是保護系統,讓系統的負載壓力處於一個比較均衡的水位,有效的管理峰值的請求量。 從上圖可以得知,當處理大量的請求時前面可以使用 CDN (靜態資源),FrondEnd 或是 Backend 可以使用擴充的方式來承接更大的流量請求,但資料的異動最後還是會交由資料庫來進行處理,Database 數據庫的連線是一個非常昂貴且數量有限的底層資源,為了避免開發環境下連接數超過數據庫所能乘載的最大上限,合理的運用資料庫的連線池技術,確保系統在高併發時連接數不會超過資源的水位值(資源閥值)。

常見限流演算法
書中介紹常見的限流演算有令牌桶算法、漏桶算法以及計數器算法三種,以下就針對這三種作簡單介紹

令牌桶算法
令牌桶(Token Bucket)算法在 wiki 說明敘述如下
每 1/r 秒會新增一個令牌(Token)到桶(bucket)中
桶(bucket)中最多可容納 b 令牌。如果桶已滿時則丟棄該令牌(Token)
當傳送 n bytes 封包時,桶(bucket)中如果有 n 個令牌(token >= n),封包將會送至網路
當可用的 token < n 時,不會從桶(bucket)刪除任何 token,該封包會被視為不合格的

圖片來源 https://gateoverflow.in/39720/gate2016-1-54

令牌桶算法的原理是會以固定的速度將令牌(token)放入桶(bucket)中,當要處理請求時首先會先到桶(bucket)中取得是否有足夠的令牌(token),當桶(bucket)中的令牌(token)用完時則拒絕服務。

從上述原理可以得知桶(bucket)的容量大小就是系統的最大併發數;可能的瓶頸是令牌桶算法中會有一個執行緒專門在產生/更新令牌(token)數,如果要在很短的時間內要產生大量的令牌數量的話會消耗系統 CPU 資源,舉例來說如果需求是每 1ms 就產生一次 Token 數量,該執行緒就會頻繁的佔用系統 CPU 資源來產生需要的 Token 數量,關於更多令牌桶算法的討論可以參考此討論串 GATE2016-1-54,裡面有更多詳細關於該算法的速率解說與範例算式說明。


漏桶算法
漏桶(Leaky bucket)算法在 wiki 說明敘述如下
請求進入漏桶(bucket)裡,桶(bucket)容量是固定的
當桶(bucket)中的水量(請求)為空時,則不在流出水滴
流出水滴的速率為固定的,桶(bucket)滿了則會溢出


圖片來源 https://developpaper.com/rate-limit-scheme-of-gateway/

漏桶算法的原理較為簡單,水滴(請求)進入漏水桶(bucker),漏水桶流出水滴的速度為固定的,當水滴進入水桶的速度太快時就直接溢出。漏桶算法提供的機制是限制流量數據的流出速度,且流出速度是持續保持固定的。

上述是介紹 Leaky bucket 中的 meter 版本,在 wiki 中還有另外一種是 queue 版本
水滴(請求)進入漏桶(bucket)裡,桶(bucket)容量是固定的
當超過桶(bucket)容量限制時,排隊或者被丟棄
桶(bucket)流出水滴的速率為固定的



計數器算法
計數器算法算式最單純的限流算法,應用層面相當的廣泛,原理如下
在單位時間之內由一個計數器專門負責計算,當新的請求來的時候會與閥值(水位)進行比較,當請求數達到閥值或水位時,便會觸發限流機制的邏輯。
舉例來說,假設限流策略為每分鐘為 5 個請求數,每請求一次計數器便會遞增加一,單位時間內計數器與限流閥值相等時,後續的請求將會被執行限流處理,當單位時間過後計數器便會進行重置的動作,新的請求才可以繼續訪問,示意圖如下



漏桶算法 v.s 令牌算法
從本質上來看兩者算法都可以用於高併發與大流量的場景下進行流量管制,不會因為瞬間的大流量而讓系統被打爆。但需要注意這兩者的現流方向是相反的,令牌桶(Token Bucket)算法限制的是流量的平均流入速率,並允許一定程度上的突發狀況(大流量);而漏桶(Leaky bucket)算法限制的是流量的流出速率,而非流入速度,這種流出速度還是保持固定不變的;令牌桶算法的極限可能會是桶的容量加上生成令牌處理程式的最大併發能力。

HTTP Status
上面提到了一些常用的限流算法,接著來看 HTTP 協定中有提到定義當達到限流機制的 Status Code 代碼,在達到閥值(水位)值時,開發者可以使用 429 Too Many Request 告訴呼叫端(用戶)特定時間內發送太多的請求,並在 Response 中說明觸發條件的詳細訊息,以及多久後可以再進行重試(Retry-After),範例如下
HTTP/1.1 429 Too Many Requests
   Content-Type: text/html
   Retry-After: 3600
   
   Too Many Requests
   I only allow 50 requests per hour to this Web site per
   logged in user.  Try again soon.     
   

ASP.NET Core 實現限流策略
身為一位不專業的工程師,上面介紹這麼多之後當然也要介紹在 ASP.NET 好用的限速策略 Library 其中比較推薦的是 AspNetCoreRateLimit 套件,使用與設定上相當簡單,也可以根據不同情境像是 Request IP 或是 Client ID 進行限流的策略,Github wiki 介紹頁面如下

以上若有問題歡迎一起討論,或是有錯誤的地方也請高手大大們給予指導予糾正,謝謝


參考
Rate limiting
Scaling your API with rate limiters
High-performance rate limiting
An alternative approach to rate limiting
Leaky bucket
Rate limit scheme of gateway
流量调整和限流技术
rate limiting 之 leaky bucket
想通关「限流」?只要这一篇

2020年10月3日 星期六

[筆記] 《知行》: 技術人的管理之路

前言
這一篇是紀錄閱讀 《知行》: 技術人的管理之路 的讀書筆記,這本書是參加 TGONetwork 所舉辦的 TGONext - TGONetworks 導師計畫 成果發表會導師 Taien 所贈送的,能夠拿到導師所贈送的書自己也有點意外(當天上台分享時蠻掉漆 XD)。這半年來工作上寫 Code 的時間越來越少花很多時間都在與團隊同仁溝通,在規劃新項目或是簡報時不是那麼的流暢(得心應手)似乎總覺得少了什麼,因此決定靜下心來好好的把導師所贈送的書了解一番,才不會枉對導師對我的期待(自以為?)。這篇文章僅介紹第一章節 : 管理路口的徬徨,整理可能當開發者要轉換成技術管理職可能會遇到的一些問題,其中若是自己有理解不正確的地方是錯誤的部分歡迎各位管理大神一同討論或給予指導

工程師發展路徑
在書的一開始,作者提到過去有一群從 2005 年開始工作的工程師好友們,在某次聚會中整理這些好友目前的職務可以分為幾大類 (作者為大陸人,書中內容可能會因為場景或是地區不同有所差異)
技術類 : 架構師、技術專家
管理類 : 技術管理者、職業經理人
創業類 : 創辦人、技術合作者
顧問類 : 投資顧問、管理顧問
可能隨著能力的提升可以做的事情越來越多,提升架構能力後轉為架構師;或是專案管理及帶團隊能力越來越強,逐漸轉為技術管理者;有很好的想法想要做自己的一番事業,成為創業公司的技術合夥人;書中提到特點之一是 10 年後堅持做技術比例的只剩 20% 左右 (沒有一定,最自己而言做自己最喜歡與認同的角色即可)。不管是走上述哪一條路,有些基本能力可能會是通用的,像是規劃、帶人、管理、溝通及執行能力,也可以說是環繞著技術與管理這兩條路在走,只是不同職務所面臨與擔負的責任不同。

我到底要不要做管理
作者常常被工程師問到我適不適合做管理?您對我有甚麼建議,作者則會反問工程師幾個問題
做管理對您來說意味什麼? 您覺得它能給您帶來什麼
希望可以透過此問題來讓提問者去了解到做管理的初衷,而非直接透過回答的方式取得答案;如何審視管理對您來說是不是真愛呢,可以透過三個問題幫自己做判斷
您是否認同做管理的價值 ? 
您是否對管理充滿熱情 ? 並享受這些工作呢 
您是否看中在管理方面的成長呢 ?
管理與技術的挑戰不一樣,常常會需要接觸很多雜事像是面試、團隊溝通、規劃流程、與主管匯報、資源協調與績效評估等各式各樣的管理工作,與開發工作相較之下項目較多且較為雜亂,可能也很難從中獲得成就感與價值,如果不認為管理是有價值的可能較難持久下去,可能會有覺得寫代碼較為單純的念頭出現。但從另一個角度來思考,過去在開發可能只要做好主管交辦的項目即可,但轉做管理為了要帶領整個團隊前進,就須思考上級、同一層單位、下級各方面的期待與訴求,要求自己用更全面的角度來思考問題的解決方式,這些挑戰也會替您帶來成長,成就感與影響力。

我要不要轉回去做技術
俗語說《人窮則反本》,當人們遇到挫折就會想回到老路上。作者提到在訪談的 2/3 的新技術經理,都有類似的擔心跟問題,問題像是做了管理之後沒時間寫Code,覺得離本行越來越遠;不知道在管理與技術中如何取得平衡,兩者兼顧;管理工作瑣碎,技術越來越少接觸覺得心虛;因為技術人員常常會專心在代碼或是某些技術上,但對於職業生涯思考方向算是被動,可能不是主動的或是被動推到經理的位置上,過去沒有經驗且可能對管理沒有深入的了解,初期在不熟悉的情況下可能感到慌張或焦慮;或是覺得 技術才是自己的根本,在面對上述問題,作者提到親自寫代碼是很好的實現方式,但作為管理者必須要掌握更多的技術,快速判斷該如何搭配使用,所以必須有更高效的學習方式,建議如下
建立你的學習機制 : 思考團隊內可以建立甚麼樣的學習機制,可以借助團隊的力量提升技術判斷力,也讓團隊能力提升。
請教專家 : 借助平台找到該領域專家大神進行請教,能成為某領域高手都有深厚的知識累積,且能用簡單精準的說明讓人容易明白與了解。
共創 : 對於知識型工作者來說,和大家共創所收穫的成功,比自己埋頭思考高效許多。
如果您對技術充滿著熱情,目標是成為一位優秀的架構師的話,做管理所累積的能力是完全可以遷移到架構師上,在管理上所具備的全局視野、規劃能力、結果導向、專案規畫及溝通與協調能力,這些都是優秀的架構師必須具備的條件之一。其次,不管是做技術管理或是架構師角色,看事情的角度都必須從 High Level 的角度來思考,建議如下
從目標出發看待技術 : 目標明確,才可以選擇最佳的技術方案,做出最合理的技術決策。
從評估角度看待技術 : 必須清楚了解技術方案是透過哪一些維度來評估好壞優劣,當技術問題暴露出來時會造成甚麼影響,損失的邊界為何 ? 
從依靠自己技術到借助大家的技術 : 要熟悉團隊每位成員的技術情況,知道誰可以勝任做什麼事,適合做什麼,借助大家的技術去做事
即便做不好也不是沒有回頭路,在轉作技術管理者時離技術很近,如果嘗試下來認為管理工作確實不是自己想要的(天命),那麼回頭繼續做工程師是幾乎沒有門檻的,但前提是自己必須先全力以赴的去嘗試一段時間,盡全力的去做一件事之後才不會有遺憾,才可以知道自己到底適不適合做技術管理的工作。

如何保持技術競爭力
如何保持技術競爭力是自己最感興趣的議題,在轉型技術管理者之後,自己可以支配與寫代碼的時間會越來越少(最近感觸很深阿),書中提到當你的角色從《技術實現者》轉變為《技術管理者》時,與技術的關係就發生了變化,過去開發者對技術的追求可能是以《技術實現者》的角度出發,但現在是轉變為技術管理者的角色,對於技術能力這詞也就悄悄的開始轉變,應該以技術應用者的角度出發,技術評估能力變得為其重要,要關心與思考的是 why & what,也就是要不要做這件事以及這是件什麼事情?並在綜合評估之後做出決策與判斷。
那麼如何精進技術判斷力就會是一個重要議題,作者提到技術評估有以下三個維度

維度一 : 技術項目結果評估
在決策要不要做一個事情時,需要回答三個問題
這究竟是件什麼事情
希望得到的結果是什麼
要用什麼角度/維度衡量結果,從那些技術指標去驗收結果
有個目標與希望預期得到的結果,才可以有始有終的做出準確的判斷與正確的決策,舉例來說
  • 可能為了要提升服務穩定性,去調整服務架構
  • 可能為了提升數據的準確性,去改寫技術數據的收集流程
  • 可能為了提升系統效能指標,去調整數據庫效能讀寫模組
像是希望提升系統性能,如何衡量結果是否有提升? 要用甚麼技術指標來進行衡量? 如果結果無法衡量的話,我們如何判斷這件事是做得好或是不好,因此,技術管理對於技術項目結果的評估能力最為重要。

維度二 : 技術可行性評估
可行性有兩層涵義,分別是 能不能做值不值得
  • 能不能做 : 是指有沒有能力做到,這是能力問題
  • 值不值得 : 是指能力允許,全力投入之後的結果是否是值得的(效益),這是選擇問題
在不懂技術管理的管理者一般提問的是 能不能做,有經驗的技術管理者與資深工程師則考慮的是值不值得,另外還需要考慮成本與收益部分。 那麼通常的技術項目,都有哪些成本需要考慮的呢
投入的資源成本
技術維護的成本
- 技術選型成本
- 技術升級成本
- 問題盤查成本
- 代碼維護成本
機會成本
協作成本

維度三 : 技術風險評估
技術風險評估也叫技術風險判斷,也就是有哪些技術風險需要未雨綢繆,該技術方案帶來最大的損失的可能性是什麼,以及在甚麼情況下會發生。舉例來說,為了降低 DB Loading 可能會加上像是 Redis 的 cache 機制,在使用時可能要思考當快取發生異常時,快取 Server 重啟因為沒有對應的快取資料,這時請求全部都跑去訪問資料庫,可能會造成快取雪崩或是快取穿透的狀況發生,這時候的解決方案或是甚麼 ? 要如何防範以及團隊同仁要如何解決,這些都可能是上線後可能會遇到的問題。風險評估考驗技術管理者的技術經驗與風險意識,經驗越豐富則對風險的判斷也就越敏銳。去拓展技術視野與技術判斷力常見方式如下
建立技術學習機制
專項技術調研項目化
與技術專家交流
聽取工作匯報
另外,你不是一個人在戰鬥,因此風險評估上也需要借助團隊的技術力量做出準確判斷,並非只靠技術管理者的技術判斷力,能從周圍人群學到多少訊息與資訊,而不是在靠自學。
核心是在如何提升技術實現的能力,轉變為提升技術判斷力與技術評估能力,有些管理者擔心自己一旦不是團隊技術能力最強的人,會因此有團隊成員不服氣,但從另外一個角度來看,管理者的職責是帶領團隊高效的交付高質量的產品與系統上,隨著年紀的增長,團隊中比你優秀的人才會越來越多,是一種好的現象,如果多年之後你依然是團隊裡技術最強的一員,可能不是一個好的現象。

...To Be Contined

心得
這篇文章僅介紹第一章節 : 管理路口的徬徨的部分,擔任開發人員也有10年的時間,其實在最近幾份工作主管都有建議可以嘗試往技術管理的路前進,但由於自己認為技術能力還尚未到一定的水準所以都不小心選擇逃避帶過,趁這個中秋連假期把該有的基本知識給惡補一下,光閱讀第一個章節就感觸蠻深的,提到過去自己很多深藏在心中已久的問題,其中也提到在不懂的知識下要找專業人員求助,這也讓我想到與前主管常提到的人脈的重要性,平常就需要累積人脈與研討會會認識一些技術愛好者,當你工作遇到問題時就會透過這種方式向大神們請教相關問題,當然態度方面是很重要的(別人也不是一定要回答你,回答問題也是需要時間成本),因此這點也是需要格外注意,雖然書還沒完全看完但已經有不少幫助,希望日後還有時間可以繼續下去。

參考
《知行》: 技術人的管理之路

2020年9月9日 星期三

[Architecture] The 12 factor App 筆記

前言
最近在與同事一起規劃新系統的架構,在整理相關文件時想起參加前公司 Techday 由新加坡同事提起的 The Twelve-Factor App 方法論,提出此方法論的作者參與了超過一百個專案開發與部署,並透過 Heroku 平台見證了數十萬個應用程式的開發運作以及擴展的過程,整理了在 SaaS (Software as a Service) 開發時需要理想的實踐標準,方法論主要內容如下

Use declarative formats for setup automation, to minimize time and cost for new developers joining the project;
Have a clean contract with the underlying operating system, offering maximum portability between execution environments;
Are suitable for deployment on modern cloud platforms, obviating the need for servers and systems administration;
Minimize divergence between development and production, enabling continuous deployment for maximum agility;
And can scale up without significant changes to tooling, architecture, or development practices.
其中提到此方法論是不限定語言與後端服務開發的應用程式,因此這篇文章就來介紹關於 12 個方法論的一些重點項目,若有理解錯誤或是異常的地方歡迎隨時提出討論。

介紹
【文不如圖,圖不如表】再多的文字都比不上一張清晰的圖讓人容易了解,因此在一開始先 PO 出在網路上找到有關 12 factors 的小抄表,讓有興趣的朋友對於整個方法論有更清楚的 overview
接著,再來逐一介紹每個方法論的內容 備註 : Puppeteer 是 Playwright 的前身,其 API 與核心概念都很相似。

Codebase
一份基准代码(Codebase),多份部署(Deploy)
  • 使用版本控制系統來控管代碼,像是 Git、Subversion 等常見的版本控管工具
  • 一份用來追蹤代碼所有異動版本的數據庫被稱為 代碼庫 (code repository, code repo, repo)
  • 基準代碼指的就是這一份代碼庫,如果是 Git 分布式版本控制系統,基準代碼就是最上游的代碼庫。
  • 基準代碼與應用(Aplication) 是保持一對一的關係。
  • 在不同的環境會對應到同一份代碼庫,每個部署可能會使用到不同的版本

Dependencies
清楚的定義依賴關係(Dependency)
  • 應用程序不會隱式依賴系統級的類別庫,透過依賴清單清楚定義所有依賴項目
  • 透過依賴隔離工具來確保不會調用不存在的項目,此做法在 Production 與測試環境皆是如此
  • 為新的開發者簡化環境配置的流程,只需要透過建構指令 (build command) 即可安裝其依賴項目,即可開始工作
  • 舉例來說,在 Ruby/Bundler 就是透過 bundle install

Config
將 Config 定義在環境變數中
  • 代碼(Code)與配置(Config)嚴格分離
  • Config 在不同環境分別各自定義,代碼是一致的
  • 推薦將應用程式的配置定義在環境變數中 (Env vars, env)
  • 環境變數可以很方便的在不同環境修改,不用異動到代碼 (Code)與語言也無關
  • 舉例來說,與第三方介接時所需要的 Token,在與 DB 建立連線時需要的連線字串 Connection string

Backing Service
將後端服務(Backing Service)視為附加資源

  • 應用程式(Application)不會區別本地或是第三方服務
  • 對它來說兩者都是附加的資源,透過某個 url 或配置的服務定位 (locator/credentials) 來取得數據
  • 也可以在不用異動代碼的情況下,將本地 MySql 資料庫換成第三方服務(ex:Amaxon RDS)
  • 每個不同的後端服務都是一份資源(resource),這些資源與其附屬的部署保持鬆耦合(loose coupling)的關係

Build, release, run
嚴格分離建構與運行

  • 嚴格區分構建,發布,運行這三個步驟
  • 直接修改運行中的代碼是非常不可取的行為
  • 每次發布都要對應到唯一個發布ID,例如可以使用發布時的時間戳記 2020-09-10 22:33:44
  • 發布的版本一但發布就不能修改,任何代碼的變動都應該產新的版本
  • 備註 : 小弟公司是使用 Git commit 的 hash 值,方便盤查

Processes
使用一個或多個無狀態的 Process 運行
  • Application 的 Process 應該是無狀態且不能共享的(share-nothing),
  • 任何像是需要持久化的數據都要存在後端服務中,像是數據庫
  • 一些互聯網系統過度依賴於 session (sticky sessions),這在 12-Factor 是極力反對的,
  • Session 數據應該保持在像是 Memcached 或是 Redis 有帶過期時間的緩存中

Port binding
通過端口綁定( Port binding )來提供服務
  • 通過端口綁定(Port binding)來提供服務,並監聽發送至該 Port 的請求
  • 不僅限於 HTTP 服務

Concurrency
使用 Process Model 進行 Scale Out

  • Processes are a first class citizen
  • 開發人員可以運用 Unix process model for running servuce daemons,將不同的工作分配給不同的類型 (Process Type)
  • 舉例來說,HTTP 請求可以交給 Web 進城來處理;常駐的後台則交由 worker 來負責
  • Process 應該 stateless 和無分享的,方便進行擴充

Disposability
通過快速啟動和優雅關機,實現穩健性最大化
  • Processes 是可以瞬間開啟或是停止,易處理的 (disposable)
  • 追求最小啟動時間,理想狀態當輸入啟動指令到等待請求應該只需要很短的時間
  • 更快的啟動時間提供敏捷的發布與擴展,容易將 Process 容易的搬移到新的物理機器上
  • 收到終止信號(SIGTERM)就會優雅的終止,也就是停止監聽服務的 Port 拒絕所有的請求然後退出

Dev/prod parity
盡可能保持開發/測試/正式環境相同
  • 想做到持續部署應該縮小本地與線上的差異
  • 縮小時間差異:開發人員可以幾小時,甚至幾分鐘就部署代碼。
  • 縮小人員差異:開發人員不只要編寫代碼,更應該密切參與部署過程以及代碼在線上的表現。
  • 縮小工具差異:盡量保證開發環境以及線上環境的一致性。
  • 開發人員應該反對在不同環境使用不同的後端服務,降低使用上的差異以及突然出現的不相容問題

Logs
把日志當作事件流
  • 應用程式不應該煩惱 logs 存放位置,統一使用 stdout 直接輸出
  • 這些事件流可以輸出至文件,或是在終端實現觀察的
  • 輸出流可以發送到 Splunk 諸如此類的日誌索引及分析系統

Admin processes
後台管理任務當作一次性運行
  • 開發人員有可能會執行一次性的管理或是維護的一次性任務
  • 執行資料轉換
  • 執行控制台(REPL Shell)
  • 一次性管理程序應該使用相同的環境,並使用相同的程式碼跟配置


感想
以上針對 The 12 Factor 做了基本簡單的介紹,但在實務上某些部份可能實現的難度較高,舉例來說像是 Dev/Prod 環境要一致的要求,現實上可能會遇的問題是開發環境的 Server 已經包含 feature A,但在未驗證完全的情況下可能會也不會更新到正式環境;每一個原則都是開發與運維同仁在開發時需要注意的部分,日後有機會設計新架構或是既有系統調整時可以做為參考的準則之一,以上如果有不清楚的地方歡迎一起討論,謝謝 !

參考
12 factor

Copyright © m@rcus 學習筆記 | Powered by Blogger

Design by Anders Noren | Blogger Theme by NewBloggerThemes.com