前言 : 此篇文章僅記錄筆者在軟體工程相關知識學習上的紀錄,若有任何錯誤還請見諒並且留言告訴我,非常感謝你/妳的閱讀以及幫助。

Helm

Helm 是甚麼?
有使用過 kubernetes 的開發者多少會知道,在部屬一個後端服務時不外乎會定義 deployment, ingress, service 等種類的yaml檔,在部屬SQL服務則可能會定義statefulset, config, secretconfig, volumn等種類在yaml檔。在筆者的公司內這樣子的服務不會僅止於一份,甚至一個後端服務可能就會配上一個redis cluster。若有10個後端服務在專案中可能就會有10*3份(deployment, ingress, service)的yaml檔案,在筆者的經驗中這三份檔案內很大機率會是 name, image, host中的值會不相同,因此下意識地認為若可以將這三份檔案抽成template在部屬時塞入差異值並做版本的控制,這樣就可以減少維護的成本,而helm就是以這樣的概念幫我們管理k8s內的服務。

Helm helps you manage Kubernetes applications — Helm Charts help you define, install, and upgrade even the most complex Kubernetes application.
https://helm.sh/

如何使用Helm?
1.
安裝好helm後,打開command line 並執行 。

helm create {yourChartName}

--

--

在資料庫的交易中,如果交易所操作的是不同資料、不互相依賴,那此交易就可以安全低平行執行。但若兩個交易流程會修改到相同資料,又在高併發的情況下就會造成競爭條件(Race condition)現象(Phenomena)。以下會列出五種交易可能會發生的現象以及四種資料庫所提供的隔離層級。

Race condition Phenomena

Dirty Read

假設一個交易向資料庫寫入資料但還沒有Commit,此時另一個交易如果可以看到尚未提交的資料,那麼這就是dirty read。
如下圖所示,初始在資料庫X=2,當transaction A執行交易,過程中set X=3,在尚未commit前又有另一個transaction B取得X的值,若此時X=3則是為dirty read,因為上筆交易還沒有提交(commit)。

dirty read

Non-repeatable Read (Read Skew)

在同一個交易中重複讀取相同的資料會拿到不一樣的值,就稱為Non-repeatable Read。如下圖所示,當transaction A更新Ben的balance時,在尚未commit前transaction B來讀取,此時會讀到原始的值balance=500(沒有dirty read),在commit後,transaction B又在讀取一次,此時會讀到balance=100,此現象稱為Non-repeatable Read。

--

--

提到in-memory cache就會提到redis,redis的特性諸如 single thread、快速、支援多種語言、cluster、哨兵模式等,本篇文章皆不會概述xD。本篇文章主要想記錄在維護高併發、高流量(電商、券商等)的系統時,在使用in-memory cache不管是VM自己的lcoal cache又或者是redis,可能會遇到的問題以及其解法,其中包含

1. 快取雪崩 (Cache Avalanche, 緩存雪崩)
2. 快取擊穿 (Hotspot Invalid, 緩存擊穿)
3. 快取穿透 (Cache Penetration, 緩存穿透)

話不多說,就開始吧!!~

快取雪崩 (Cache Avalanche, 緩存雪崩)

" 什麼是快取雪崩 ? "
在某個時刻所有的 cache同時發生過期或者redis 服務失效,導致大量的 request 直接打在資料庫上,當流量巨大時資料庫很可能會被打掛,此時DBA若重啟資料庫可能又會被新的一波流量再打掛,這樣的狀況就是快取雪崩。

解決方案 -
因為是同個時間點,所有的cache key大規模失效,因此可以在設定 cache 時,給予每個cache key 隨機的過期時間,或者 不設定過期時間 。每個cache key 過期時間的設定,其核心理念在你想要更新資料的頻率。

快取擊穿 (Hotspot Invalid, 緩存擊穿)

" 什麼是快取擊穿 ? “
快取擊穿和快取雪崩相似,雪崩是大面積cache key時間過期,而快取擊穿則是某個熱門的 cache key過期。所以,當高併發集中在此熱門的key又快取失效過期時,流量就會直接打在資料庫上,這樣子的狀況就叫快取擊穿。

解決方案 -
要避免快取擊穿其中一個方法是將熱點key設為不過期,另一個方法則是在application寫lock(互斥鎖)以確保共用資源在多執行緒下可以排隊拿取資源,不過此作法會造成系統吞吐量下降,並阻礙其他線程。

快取穿透 (Cache Penetration, 緩存穿透)

" 什麼是快取穿透 ? “
快取穿透是指client request 的資料並不存在於 cache 中並且也不存在於資料庫中,因此每次的請求就會直接穿過cache並打在資料庫中。同樣,若這樣類行的請求量一多,也是會將資料庫打掛。
舉個簡單的例子,若 client 請求 id=-1的資料,但是在我們的資料庫中是從id =1開始的流水號,那麼-1則永遠不會拿到資料,並且請求會直接打在資料庫上。

解決方案 -
因為是查找不存在的資料,因此可以在application中過濾非法請求,也就是當client 請求id = -1時,直接將請求做例外處理,不要讓他打在資料庫上。另一種方式,則是將id=-1寫入cache中並回傳對應的處理,例如當id=-1則redis則回傳null。還有另一種方式則是使用 " 布隆過濾器 "(Bloom Filter)判斷請求的key是否存在於集合中,若存在則直接去redis拿取,若不在則直接回傳對應訊息。

--

--

gRPC是什麼 ? gRPC是一套開源的遠端程序呼叫(remote procedure call) 系統,可搭配C#、python、Go等等(支援語言),由 google在2015年提出的,其http協定是"使用http/2" (http/2是什麼?),因此傳輸速率會比http/1.1來的快,又其使用 "Protocol Bufferes作為介面定義語言(interface definition language, IDL)",因此在開發上可以更快速的在不同的語言、服務上互動。有別於一般open api使用url、http methods、參數等在client與server間互動,gRPC的IDL則更為直觀明確,"client與server端皆須使用同一份 .proto 檔案作為介面"。寫了這麼多文謅謅的字,我想還是用軟體工程師的語言表達會來的直觀些,以下我會以C# .net core 3為example試著解釋給大家聽。

http/2 為協定

Binary framing layer (二進制影格層)、Server push (伺服器推送)、Header compression (標頭壓縮)、Request and response multiplexing (多路複用)皆為http/2協定的基本feature,目的則是為了加速http request傳輸的效率(http/2是什麼?)。

在.net core 3中,若要使用gRPC則需先安裝下述三個套件(nuget)
1. Grpc.Net.Client
2. Google.Protobuf
3. Grpc.Tools

安裝好後,可以新增Protos folder作為分類,並且新增副檔名為 .proto的檔案,此檔案就是以Protocol Buffers 作為IDL。

--

--

http/2是什麼? http/2 其實就是http通訊協定的第二版,目前http版本由最初的0.9、1.0、1.1(1999年發布)在到現在的2(wiki)以及還在草案的3(wiki),那麼這些版本到底差在哪呢?本篇文章主要會介紹為何會有http/2 ? 它要改善甚麼 ? 以及它如何改善 ?

為何會有http/2 ? 它要改善甚麼 ?

http/2標準發布於2015年5月,其主要目的是透過一些措施改善瀏覽器瀏覽網頁加載的速度(page load)。目前大多數的瀏覽器已支援 http/2 (chrome, firefox, safari等)標準,又 http/2與 http/1.1有著高度的相容信,舉凡request method(post, get..etc), http status code, url, header 等等,因此對於web developer來說,只需要確保你的網站有支援https(因為瀏覽器只支援https 在http/2上)。那麼http/1.1與http/2到底相差多快呢,下列有幾個網站可以比較其差異,可以自行體驗!

  1. http://www.http2demo.io/
  2. https://www.httpvshttps.com/

http/2 是如何改善 ?

Request and response multiplexing (多路複用)

在http/1.1中,client端時常會同時發起多個request至server拿取檔案(像是js, css, image等),以此方式達到快速載入頁面。如下圖在http/1.1中會同時與server建立3個TCP connection,但是瀏覽器通常會限制TCP connection同時建立的數目。因此在http/2協定中,允許client端與同一server建立單一TCP connection並以非同步方式傳輸要的檔案。

--

--

快速的紀錄一下conemu terminal 在windows上的安裝與使用。首先,先安裝 conemu(https://conemu.github.io/),打開powershell並安裝下列兩個powershell 的module(posh-git, oh-my-posh)。

Install-Module posh-git
Install-Module oh-my-posh

安裝好後同樣在powershell內下 $profile 指令,找到你的 powershell profile 位置,將下列三行貼入存檔(沒有檔案就自己建立一個相同檔名的吧!)。

Import-Module posh-git
Import-Module oh-my-posh
Set-PoshPrompt -Theme aliens //設定你要的主題

--

--

最近因為電腦重灌,很多環境的東西要重新設定,因此遇到了下圖的問題,
整體來說是powershell預設的 security protocol 是TLS1.0,因此在使用shell下關於http reqeust會發生錯誤,解決方法則是將powershell 預設的security protocol 從TLS1.0 改到1.2。

下這行指令即可
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

--

--

每個開發 .net 的人對於 Newtonsoft.Json 套件肯定都不陌生,它幫助我們日常開發時物件的序列化、反序列化以及掛載 JsonPropertyName 等。但是 .net 在 .net core內建了 System.Text.Json 這套類似於 Newtonsoft.Json 功能的套件,不過在使用上還是有些許的差異,廢話不多說,以下是我目前親自踩到的雷整理後分享給大家。

System.Text.Json Newtonsoft.Json 差異

  1. String, Int 型態轉換
  2. Property 大小寫mapping

String, Int 型態轉換

在Newtonsoft.Json中,物件反序列化若內容為純數字則接起物件的property可為String or Int 皆可,也就是說附圖的測試都可以過。

但在 System.Text.Json 中,對於這樣的轉換則較為嚴格,這樣的case則會噴錯,一樣如下圖。

由上圖兩個測試可得知,System.Text.Json 比 Newtonsoft.Json規範更來的嚴格。筆者是在與第三方串接時發現這個問題,第三方的文件上規格定義 String,但是實作時發現傳來的 raw value是 Int 。

不過如果堅持要使用 System.Text.Json 解決上述型態問題,則可以自製converter

Property 大小寫mapping

在Newtonsoft.Json中,反序列化前Property 大小寫會自動幫你轉換,System.Text.Json則相反,不囉嗦,一樣先上圖。

在 System.Text.Json 中,對於大小寫得的轉換則較為嚴格,這樣的case物件則接不起來值,一樣如下圖。

總結 : 在.net core 中使用 System.Text.Json 請注意"大小寫""型態轉換",在Newtonsoft.Json 因為已經幫你轉換了,因此可以安心使用,但是他的效能會差一點 (Reference)。

--

--