只有累積,沒有奇蹟

2020年7月1日 星期三

[NETCore] ASP.NET Core 靜態檔案設定 - UseStaticFiles

前言
在過去開發 .NET Framework 時代在專案使用靜態檔案是一塊小蛋糕,只需要在專案指定 Folder 加入需要的靜態檔案內容即可,像是圖片就放在 image、javascript 內容就放在 js 資料底下...等等,但同樣事情在 ASP.NET Core 專案可就完全不同,在 .NET Core 專案中是無法直接瀏覽靜態檔案的,需要透過一些設定方式才可以在專案看到像是 HTML、CSS、Image 或是 javascript 靜態檔案,這篇文章就是簡單說明在 ASP.NET Core 專案中如何設定才可以看到靜態檔案內容,若有問題歡迎提出一起討論或是給予指導。

靜態檔案
在 ASP.NET Core 中 Web 檔案會存放在專案根目錄中,預設存放位置是專案根目錄  project / wwwroot  底下,其資料夾底下可以存放多個資料夾如下,如果要存取 image 子資料夾底下的 test.jpg,其 URL 格式為 http:// yourApplicaitonName:9487/image/test.jpg
以下就透過簡單的範例,在 ASP.NET Core 專案簡單示範如何加上靜態檔案
簡單來說兩個步驟可以完成
  1. 加入靜態實體檔案
  2. 加入 UseStaticFiles 方法
Step 1 : 前面提到預設靜態檔案目錄是 wwwroot,在 wwwroot 目錄底下新增一個 helloworrld.html 檔案
其 html 內容就簡單輸入 Hello World ASP.NET Core !!!
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
    Hello World ! ASP.NET Core 
</body>
</html>
Step 2 : 在 Startup 中 Configure 新增  UseStaticFiles  方法,UseStaticFile 是  IApplicationBuilder  的擴充方法,主要是啟用靜態文件服務,背後其實是呼叫另一個 middleware 幫妳進行靜態檔案的設定
app.UseStaticFiles();
好的,經過設定完畢之後在開啟網站並在網頁 url 後面加上 helloworld.html,即可在網頁上看到 Hello world ! ASP.NET Core 字眼,新增成功 !!
未設定 UseStaticFiles
如果未設定 UseStaticFiles 或是未將檔案放置在預設路徑底下,則會出現 Http Error 404 not found 錯誤畫面,如下圖所示
透過以上步驟,就可以輕鬆解決在 ASP.NET Core 無法顯示靜態檔案問題,讓靜態檔案找到回家的路(咦

UseStaticFiles 
為何透過 UseStaticFiles 方法就可以啟用靜態檔案呢? 接下來我們在往下追看看方法做了什麼事情以及實作細節,在  UseStaticFiles  方法提供三種多載情境給開發者使用,三種方法分別是
  • 預設路徑 : 無任何參數
  • 指定靜態檔案路徑 : requestPath
  • 指定 StaticFileOptions 物件
UseStaticFiles
無參數的方法如下
/// <summary>
/// Enables static file serving for the current request path
/// </summary>
/// <param name="app"></param>
/// <returns></returns>
public static IApplicationBuilder UseStaticFiles(this IApplicationBuilder app)
{
  if (app == null)
    throw new ArgumentNullException(nameof (app));
  return app.UseMiddleware<StaticFileMiddleware>(Array.Empty<object>());
}
從上述代碼可以看到,無參數的方法主要是透過設定  StaticFileMiddleware  來做靜態檔案的設定,在其 middleware invoke 方法中主要是處理已知靜態檔案 Request 請求,也就是確認 MIME 的 Content Type 是可以被識別的才會處理其靜態檔案請求內容,路徑則是透過預設的 wwwroot 路徑位置來讀取檔案位置,

UseStaticFiles 指定靜態檔案路徑
此方法是指定檔案路徑位置作為參數,接著再透過 UseStaticFiles  指定其 StaticFileOptions 作為參數,相關代碼如下
/// <summary>
/// Enables static file serving for the given request path
/// </summary>
/// <param name="app"></param>
/// <param name="requestPath">The relative request path.</param>
/// <returns></returns>
public static IApplicationBuilder UseStaticFiles(this IApplicationBuilder app, string requestPath)
{
  if (app == null)
    throw new ArgumentNullException(nameof (app));
  IApplicationBuilder app1 = app;
  StaticFileOptions options = new StaticFileOptions();
  options.RequestPath = new PathString(requestPath);
  return app1.UseStaticFiles(options);
}
或者這樣講有點抽象,這就簡單的舉個範例讓大家更容易了解,下面的範例是透過設定 StaticFileOptions 公開 MyStaticFiles 目錄資料夾作為存放靜態檔案的位置
public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles(); // 預設公開位置 wwwroot 
    app.UseStaticFiles(new StaticFileOptions
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), "MyStaticFiles")),
        RequestPath = "/StaticFiles"
    });
}

UseStaticFiles 指定 StaticOptions
UseStaticFiles 指定靜態檔案路徑與此方法有點類似,都是設定其 StaticOptions 參數資料,差異是上面的方法僅提供設定路徑位置 RequestPath,此方法提供設定範圍比較廣,可以定義 StaticOptions 類別更多的細節,先看看 API 簽章
/// <summary>Enables static file serving with the given options</summary>
/// <param name="app"></param>
/// <param name="options"></param>
/// <returns></returns>
public static IApplicationBuilder UseStaticFiles(this IApplicationBuilder app, StaticFileOptions options)
{
  if (app == null)
    throw new ArgumentNullException(nameof (app));
  if (options == null)
    throw new ArgumentNullException(nameof (options));
  return app.UseMiddleware<StaticFileMiddleware>((object) Microsoft.Extensions.Options.Options.Create<StaticFileOptions>(options));
}
甚麼時候有可能會用到呢? 舉例來說有時希望在回傳靜態檔案時加上 cache 機器,讓瀏覽器的 Browser 幫忙做點事不用相同檔案的 Request 重複跟 Server 要資料,這時就可以透過 OnPrepareResponse 方法在回傳前做點小加工,實作方式如下
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    var cachePeriod = "600";
    app.UseStaticFiles(new StaticFileOptions
    {
        OnPrepareResponse = ctx =>
        {            
            ctx.Context.Response.Headers.Append("Cache-Control", $"public, max-age={cachePeriod}");
        }
    });
}
在回傳的 Head 上加上 cache 有效時間為 600 秒,從網頁 Response 結果就可以看出設定成功

後記
以上簡單介紹關於 UseStaticFiles 的基本應用與說明,在其中有更多進階的應用像是檔案授權、如何開啟靜態檔案目錄方式瀏覽、提供預設文件的方式等更多情境的應用,如果有需要可以參考官方網站的說明與 sample code : 傳送門在此,當然對以上的內容說是有疑問的地方歡迎隨時提出來,謝謝

參考
ASP.NET Core 中的靜態檔案

2020年5月17日 星期日

[筆記] TGONext 架構組 - 資料庫 Migration 及軟體架構的演進

前言
這一篇是紀錄參加 TGONext - TGONetworks 導師計畫架構一組第三次聚會的旁聽筆記,導師計畫歡迎小組間跨組討論因此自己只要時間允許會參加其他組的討論,參加完後也會整理討論的筆記方便日後回顧,在過去兩個月有參加的架構組筆記分別如下 為了日後讓自己可以更快理解因此整理筆記時有加上自己理解的說明與圖片,其中若是自己有理解不正確的地方是錯誤的部分歡迎各位高手一同討論或給予指導

Database Migration
在這次聚會的一開始同學拋出 Database Migration 的議題,程式碼有版本控制系統,遇到異常狀況時可以找到原本執行正常的程式碼快速進行 Rollback 的動作,那麼資料庫遇到類似狀況要如何 rollback 呢? Ant 請同學分享針對過去的經驗或是解法,可能的解決方案如下
  • 不刪除資料及欄位
  • 保存刪除資料,使用 Trigger 將資料複製到另一個 Table
  • 將要異動的 Table 建立一份 snapshot 快照
  • Rename & Copy
這問題沒有一定標準的答案,導師也提醒需要考慮在特定的法規中需要保留資料特定年限才能刪除,像是在金融業政府就規定交易紀錄須保存五年以上,方便稽核單位進行查核的動作。
導師 : 如果不刪除資料的話,大家覺得會有什麼問題?
如果資料庫有很多非必要資料或是欄位時,如果不刪除的話會占用 disk 或是 memory,在傳輸時會多占用網路頻寬;存放過多 Dirty data,後人在維護時也有可能因為不敢亂刪除資料或是欄位,因而繼續存放演變為技術債,也可能會讓 db 的 loading 越來越高,因此可能會影響到資料庫的效能,為了不影響資料庫的效能處理方式有很多種,常見有兩種方式處理
  • 將沒用到的放置在另一個 Table,如果之後 Database 需要 Migration 時可以將所需要資料移回來
  • 將不需要用到的資料 snapshot,有需要 Rollback 時再將 snapshot 資料回復到原本的資料庫中
Add New Columns
RDBMS 是 row base database,新增一個欄位所需要的時間取決於目前資料量的多寡,如果目前異動的 Table 有兩千萬筆 row data 時,這兩千萬筆資料都需要新增 columns,在 Production 的 Table 新增欄位會有 lock 的情況發生,也就是說可能會有 downtime 的狀況產生,在過去的經驗如果要在核心 Table 進行異動或是 index rebuild 的話,會在網站者使用者相對較少的時間進行停機告知用戶網站正在維修中(Under Maintenance),在交易量大的網站中對於 downtime 是格外重視的,在 PostgreSQL 11 與 MySQL 8 分別都有支援新增欄位不會 Table lock 的方法。
那麼不停機要新增欄位,要怎麼做會比較好呢? 
在 MySQL 有工具可以協助達到此目的 : gh-ost,原理如下 了解運作原理之後,那麼它可能的缺點會是什麼?舉例來說目前資料庫中有些 Table 近 2G 的空間,會進行 COPY Table 資料,可能問題會是 COPY 原有 Table 資料過程中,由於資料量非常龐大此時 Disk IO 會飆高,cpu high或是既有空間會不足的情況發生,這都是使用前需要留意的地方。

Row Based Database vs Column Based Database
在比較 RDBMS 與 NoSQL 的特性時,導師也提到可以從 Row Based Database 與 Column Based Database 的設計進行研究,這方面比較不熟因此列出網路上文章日後有時間拖稿再繼續研究

資料結構 : Tree
接著討論有關 RDBMS 資料庫與 NoSQL 本質上的差異,以及資料庫中的重要觀念 B Tree & B+ Tree,內容相信大家都了解這裡就不在說明,這裡列出幾個自己覺得說明蠻清楚的網站讓大家了解其原理

軟體架構演進
接著回到軟體架構的討論,在上次的討論中有提到 架構的演進,在討論的一開始導師又拋出問題給同學
導師 : 當單機承受不住的時候,為了支持更大的量,你會怎麼做 ? 

  • 機器硬體加大
  • 橫向擴充
  • 服務拆分
  • Cache Server
  • Queue
導師強調演進沒有一定的答案,每個解決方案都有適合他的情境,架構也有各自的瓶頸點,舉例來說選擇使用垂直擴充加強機器的硬體,但升級並不是無限擴充的會有物理的上限問題;如果選擇橫向擴充了100台機器,機器的管理就是一個問題,像是如何將新功能在最短時間佈署至100台機器,佈署策略要如何去定義,分散式系統的問題開始浮上檯面不得不面對;在上次聚會中提到 cache server 可能是其中的一種方法,但是團隊是否有能力可以處理 cache 帶來的問題,要如何處理因為 cache 異常引起的雪崩效應,常用的 cache 有 Redis 與 Memcached 兩種,Redis 相信大家都不陌生,在 Facebook 與 google 仍然在使用 Memcached,導師也請同學們思考看看背後的原因。

擴充方式
  • Scale up : 垂直擴充 (Scale vertically),提升單體 Server 硬體效能,像是增加 CPU 核心數、硬碟換為SSD、升級記憶體 Memory、升及網路卡速度,硬體升好升滿的概念。
  • Scale out : 水平擴充 (Scale horizontally),增加伺服器數量,使用更多機器一起來負擔更多的用戶與 Request 請求數量
  • 但在垂直擴充到某個程度可能會有硬體的物理上限,相對的硬體資源更好的伺服器費用也較為昂貴,
    使用大量硬體較便宜伺服器來實現提升整體效能成本上會來的較為便宜,機器異常時造成服務中斷的風險也比較低。

    Database 擴充
    在 RDBMS Database 相對於 Application 來說,擴充上是較不容易的(不考慮分散式系統或是讀寫分離的情況),如下圖所示

    此是一個簡易的前後端分離架構圖,當用戶透過瀏覽器發送請求到資料庫處理的流程來區分,網路可以透過 CDN 快取加速,前端 FrondEnd 網站與 Backend API 可以透過 local cache 或是 Redis 等快取機制加快處理速度,當 Server 機器數量不夠時可以透過 Scale out 擴充承接更大量的 Request 請求,前面假設機器加到 50 或 100 台 server 能夠應付更大的流量,最後在做資料異動還是需要透過 Database 來處理,由於 RDBMS Database 的特性(Atomicity、Consistency、Isolation、Durability) 注重資料的一致性,因此在擴充上是較難分為多台水平擴充,如果遇到效能的問題需要做擴充大多都會選擇硬體升級方向出發,但是升級都會遇到機器物理的上限無法無止境的提升,因此保護好資料庫變成一件很重要的事情。

    資源的限制
    在架構的選擇中,資源(Resource)也是考量的重點之一,常見的資源有 CPU、Memory、Storage space、Disk IO、Network bandwidth、Network latency 等,請大家思考哪一個項目是覺得比較難擴充的,有人回答 Disk IO,因為 Network 的問題或許可以靠 CDN 去解決,但 Disk IO 可能跟不上 CPU 的速度,大家都提出自己的觀點與看法,接著導師請大家思考
    導師 : 在雲端服務廠商裡面,上述提到的(Resource)有什麼服務是不能選擇的 ? 
    導師提出他的觀點 Network 是無法選擇的,Google 推出 Protocol Buffers 以及 MessagePack 等新的 format 就是為了解決網路傳輸的問題,主要是透過(使用CPU)壓縮的方式讓傳輸資料輕量化,以加快資料網路傳輸的速度,也就是用 CPU 去換傳輸資料輕量化。

    Queue
    導師 : 甚麼時候應該要用 Queue ? 它的特性應該是什麼 ? 
    • 有順序性,存放暫存的請求內容(狀態state)資料
    • 在架構設計上常會用於系統與系統間解偶(Loosely Coupled)
    • 像是非同步,處理完畢的時間不確定 (asynchronous 的缺點都有)
    使用上要注意的是要有(限制) 容量 (memory) 的上限,不能是無限制的使用;另一點要注意的是當 producer 要將請求內容放置到 Queue 的時候,如果遇到 Queue 已經滿了放不進去時該如何處理 ? 遇到 Queue 滿了是否有將 producer 的內容 block 住,保證內容不會因為 Queue 滿了而遺失,但也可能會因此造成連鎖效應,如果發生異常 block 住的數量過多要如何快速地消耗,是否團隊有建立監控機制來預防此狀況發生,與上次討論提到的 cache 相似,團隊在選用前應該了解會遇到的問題及如何解決,才不會在上線後踩雷後無法處理造成業務上的損失。

    Kafka & RabbitMQ
    接著討論到常見的 Queue service 有 Kafka 及 RabbitMQ,分別是使用 Java 與 Erlang 不同的程式語言所開發,分別有各自程式語言的特性,像是 RabbitMQ 預設記憶體超過 40% 時會發出 memory 不足的警告,當 GC (Garbage Collection) 機制回收時會消耗兩倍記憶體量為 80% (50% used memory + 50% Crach memory,確保失敗的記憶體可以復原),這是 Erlang 程式語言的 safe to crash 的特性也是可能在使用 RabbitMQ 必須要注意的地方(缺點);接著談到 Kafka,Kafka 是 Linkedin 開發的 open source,Kafka 快的原因是 Java 有使用 off-heap,off-heap 是 GC 的一種技術,在 Java 有提供 unsafe 基礎類別 API 可以自己去控制記憶體或回收記憶體 (備註1),從效能鐵三角的角度來看 Kafka 是追求高 throughput。

    備註1 : 當 GC 啟動在執行時記憶體回收時,正在進行的執行緒會將暫停直到 GC 回收完畢為止,為了解決內存記憶體過大造成 GC 回收時間過長的問題, JAVA 提供 off-heap memory,將記憶體放在 heap 中將控制權交由作業系統處理,(感謝 Ant 大協助 Review & 糾正)

    心得
    過去曾經在面試中被問到 RDBMS 與 NoSQL 如何選擇,自己當時回答得七零八落,但經過這兩次小組的討論陸續有講到 RDBMS、NoSQL與 NewSQL 的本質設計,對於這問題的答案自己也開始有些頭緒。如同於程式架構的演進一樣,從 RDBMS 到 NoSQL 到最近的 NewSQL,各有適用的強項(解決的問題)與適用的場景,沒有一招打遍天下的解決方案。另外在討論架構時也提到不同解決方案的差異,也提醒同學必須思考什麼情況下會從一種模式轉為另一種架構模式,考量的點會是甚麼,舉例來說如果架構中某個服務loading 較高時,可以選擇抽出來提高其可用性與吞吐量,其餘沒有問題的研究既有架構繼續使用,像是積木一樣做組合與分配,選擇可以解決問題的方案才是真正的王道。

    參考
    Elasticache : 比較 Memcached 和 Redis 的差別
    Queue 的應用(4) - ManualResetEvent 與 Lock 的 BlockQueue 補完
    堆外內存(off-heap),堆內存(on-heap)
    Java魔法类:Unsafe应用解析
    Apache Kafka 介紹
    Blocking Queue
    RabbitMQ性能优化
    Difference between Row oriented and Column oriented data stores in DBMS
    Rowise vs Columnar Database? Theory and in Practice
    關聯式與NoSQL 資料
    Multi-Tenancy Application #2, 資料層的選擇
    Protocol Buffers
    MessagePack

    2020年4月30日 星期四

    [Tool] Redis 管理工具 - Another Redis Desktop Manager

    前言
    在之前推薦過 Redis 管理工具 [Redis] Redis 管理工具 - Redis Desktop Manager,方便開發者可以輕鬆的使用 GUI 工具查看或設定 Redis 的資訊,如果要下載新版使用則需要另外付費 (4.99/Month ),最近又發現另一款好用的 Redis 管理工具 Another Redis Desktop Manager,在 Github 說明如下
    A faster, better and more stable redis desktop manager, compatible with Linux, windows, mac. What's more, it won't crash when loading a large number of keys.
    除了支援 Windows、Linux 與 Mac 三種環境之外,語系部分還支援繁體中文說明,經過幾天的使用個人覺得不輸給 Redis Desktop Manager,今天這篇文章就來推坑這款好用的工具,若有問題歡迎提出來一起討論。

    安裝
    下載位置可以從 Github 頁面 Another Redis Desktop Manager release 進行下載安裝檔的動作,舉例來說目前最新版本為 v1.3.5,裡面就提供各個環境的安裝檔案,如果是使用 Windows 可以選擇 Another.Redis.Desktop.Manager.1.3.5.exe 進行下載的動作

    接著就是大家熟悉的安裝流程,點選下一步到完成為止

    建立連線
    在開啟應用程式之後,第一步就是要連線到 Redis Server,為了 Demo 方便這裡我先使用 Docker 在本機啟用 Redis,port 為預設的 6379,接著是點選左上角的 New connection,輸入要連線到的 Redis Server 內容,按下 OK 選擇下一步

    Redis 資訊
    與 Redis Server 建立連線成功之後,即可以看到目前 Redis 目前的資訊像是使用 Redis 使用的版本為和、記憶體的使用量,目前的連線數等資訊,另外在右下方也可以看的到目前我們存放在 Redis key 的資料數據,這些數據分別存放在哪一個 Redis 中哪一個 db 位置
    Redis Console
    如果習慣 command 指令的朋友,也可以在應用程式直接下指令來達到你的目的,舉例來說在 Console 輸入 Ping 則會回覆 PONG 關鍵字

    新增 key & 資料
    也支援在介面上新增 Redis key 與資料,舉例來說我新增一個 key 為 test 資料型態為 hash,接著可以繼續在介面上新增內容資料,這功能最近在開發新專案時很常用到,可以很方便的加入所需要的資料針對專案與 Redis 的介接與測試,不用在另外熟記指令來進行新增/調整資料的動作 (我比較懶惰...)

    感想
    另外還有支援繁體中文語系,進階搜尋 Redis key 與切換 dark 介面等功能,整體來說目前使用上功能蠻完善的,使用了幾天也未遇到當機或是異常 crash 等問題,對於 Redis 管理工具有需求的朋友,或許可以嘗試看看 Another Redis Desktop Manager如果有不清楚的地方歡迎一起討論,hope it helps !


    參考
    AnotherRedisDesktopManager


    2020年4月9日 星期四

    [筆記] TGONext 架構組 - 架構師的自我修煉

    前言
    上一篇 TGONext 架構組 - 高併發高流量 分享參加架構一組的書僮筆記,這一篇則是記錄由 Taien 擔任導師的架構三組討論心得,在 TGONext 導師計畫 開學儀式當天小組內的組員有各自做簡單的自我介紹,並針對工作上的痛點做簡單討論,導師與同學分享未來五個月聚會的主題與規劃,以及推薦可以幫助到大家的書籍清單,架構3組三月份討論主題是 架構師的自我修煉,預計討論內容如下
    心態與思想
    深耕專業技能
    團隊合作典範
    如何影響團隊
    這篇是根據微薄的記憶整理小組討論的筆記,部分內容為了讓初老症狀越來越嚴重的自己更好理解加上自己說明與圖片,若有問題或是錯誤的地方歡迎各位大大一同討論或給予指導

    推薦書籍
    在每次的聚會之前導師都有推薦的閱讀清單,清單如下
    • QBQ問題背後的問題 : 這本書之前主管 gipi 就很推薦部門同事一定要閱讀,在 T社也是將這本書列為要求新人必讀書籍之一,最近在博客來發現出了30萬冊紀念版,可見其受歡迎的程度。
    • 我編程,我快樂 : 談到程式猿的成長與職涯規劃之道,作者分享自己過去的經驗提醒程式猿不能只注重技術的提升,還要關注自己職涯上的發展,但礙於自己閱讀簡體字有障礙,目前只看一半還沒看完。
    • 軟體架構師的12項修煉 : 作者認為軟技能是架構師的必修課,整理出 3 大方面分別是關係、個人與商務技能,教導程序猿修煉如何將三大項底下的12 項軟技能點滿,才可以算是一位合格的架構師。
    除了上述提到的三本書之外,我個人也推薦 高效能程序員的修煉一書,其中一個章節提到程序猿應該培養寫作的習慣,當你學習到一技能/對某項事物有興趣/解決某個難搞的問題等事情都可以寫部落格文章,將所學到的內容消化最後在用自己理解的方式呈現出來,91哥也有寫過一篇文 我為什麼鼓勵工程師寫 blog,有興趣的朋友可以看看。

    技能樹
    由於組員來自四面八方每個人所擅長的技能都有所不同,組內有前端工程師、後端工程師、AI 資料工程師等,因此導師有先請同學在家整理以下資訊與同學分享
    專業技能:Skill Tree
    管理:Skill Tree
    職涯目標
    其中專業技能與管理希望同學用 Mind Map 呈現,並用顏色標示出對於技術的熟悉度,主要用意是希望大家都可以知道哪些技能是應該具備(守備範圍),自己目前已經會了那些,而那些內容是自己還不會或是還沒有機會學到的,這些資訊可以透過整理成 Mind Map 的過程中讓自己更加清楚;由於管理的層面涵蓋很廣,像是溝通管理、時間管理..因此可以盡量延展,沒有標準的對錯與答案,以下分享小弟整理的內容,若有疑問歡迎一起討論

    專業技能 Mind Map

    身為一位前端低能兒因此這是以 Backend 後端工程師角度出發,如果有經驗的工程師都會知道,開發不僅僅是把 Code 寫好交付就可以,程式上線後還需要進行應用程式的監控等重要的事情,因此在整理時從幾個環節出發分別是分析、設計、Coding、測試、上線、維護監控,從這幾點分別去整理對應到的技能或是工具,其中 CI/CD 與分散式系統設計是這一兩年希望自己加強的重點。在開發應用程式時隨著請求量的倍增,可能會從單一應用程式Scale up/out 擴充為多台應用程式,這時就需要依據當下的情境設計出合適的架構,如何在設計新架構時兼具效能與彈性讓系統可以承受高流量與高併發的考驗,亦有可能需要與舊架構為伍也就是常提到的讓飛行中的飛機換引擎,這之中有非常多的眉眉角角需要探討與研究的,也是自己覺得想挑戰的部分(自虐)。

    管理 Mind Map
    管理則是由架構師的角度出發,架構師除了基本要具備一定程度的技術能力,對於整個軟體開發流程從需求分析到系統上線後的監控與數據報表分析也都需要了解,從一開始的需求釐清與分析能力需要蒐集高階主管(長官)想要解決的商業問題是甚麼,才有可能在架構設計時選擇適合的方案;技術選型上需要了解選用的解決方案的本質與帶來的side effect為何,還有選用技術/產品的成熟度與穩定性,團隊的能力等多方面的考量出發,而非一昧地追求新技術而忽略帶來的成本與風險;除了技術能力之外軟技能也是不可或缺的項目之一,需要具備 Domain Knowledge 與商業思維而非一昧地以技術的角度出發來解決問題,須具備簡報技巧讓高層願意替你設計的新架構買單;高層 Buy in 後做出來的 POC 方案是否能讓團隊對於新架構是認同;最後是持續學習部分,需要持續學習與了解新技術增加自己的廣度,遇到問題時才有機會有更多解決方案而非單一解。(OS:為了不成為一位嘴砲架構師整理完發現列這麼多條件,覺得好像離架構師還有好長的路 XDDD)

    導師有針對大家分享的技能與管理 Mind Map 內容給建議,另外也補充大家在還沒那麼多經驗時可以多看 Github 上比較熱門的 open source 吸取經驗,熱心的同學也在會後在群組補充覺得不錯的 github 專案 system-design-primer 以及 blog 讓大家一起學習。


    HTTP Request Smuggling
    在討論中導師也提醒同學資安是不可忽視的重點之一,除了可以參考 OWASP TOP 10 之外 另外提醒大家最近一種新的攻擊方式 HTTP Request Smuggling,這種攻擊方式在2005年就被發現但一直被大家所忽略,Portswigger 主管 James Kettle 於2019年再次提醒大家其影響程度,以下就根據 HTTP Desync Attacks: Request Smuggling Reborn 原文做簡單的介紹與說明

    原理
    當客戶在網站上操作行為時會透過 Front-end 服務器 (nginx、CDN、負載均衡或反向代理) 將 HTTP 請求發送至 Web 後端 (Back-end) 伺服器,為了提高其傳輸速度與效率,通常會經由同一個後端網路來傳送多個請求 (HTTP/1.1 提供 Keep-Alive 允許單個連接上傳送多個請求),HTTP 會按照順序進行發送的動作,收到請求的伺服器會根據 HTTP 中 Request 表頭定義請求結束的位置 (Transfer-Encoding或是Content-Length),如下圖所示

    由上圖可以發現,Front-end 與 Back-end 是兩台不同的服務或伺服器,HTTP 請求偷渡是因為 Front-end(反向代理) 與 Back-end 後端處理請求的伺服器對於 HTTP 請求解析處理不一致,駭客可以透過不一致的差異在一個 HTTP 請求中放置 (偷渡) 另一個 HTTP 請求,後端接收到請求後會處理夾帶的攻擊內容 (橘色部分) ,直接在內部網路服務進行攻擊

    HTTP Request Smuggling 將 Content-Length標頭和Transfer-Encoding 放在 HTTP 請求中,在透過 CL.TE、TE.CL、TE.TE 漏洞進行請求解析不一致的動作,詳細原理與細節可以參考下列文章有更詳細的說明與內容
    Service Level
    在定義服務的品質通常會提到 SLA、SLO、SLI,三個名詞的全名如下
    • SLA : Service Level Agreement,服務等級協議
    • SLO : Service Level Objective,服務等級目標
    • SLI : Service Level Indicator,服務等級指標
    舉例來說,假設今天開發的是電商系統,為了給客戶更好的品質與速度因此定義 SLA 為 Latency <= 300ms ;為了達到目標,Sevel level 可能會定義如下
    • SLA : Latency <= 300ms
    • SLO : latency <=200ms,會定義比承諾客戶更小數字的目標以達到 SLA 標準
    • SLI : 每分鐘內 http status code 為 200 的 response,比較著重在指標的部分,常見的有throughput、latency、Availability或correctness等測量指標
    有管理經驗的朋友可以發現像是在定義部門目標使用 Bottom-Up 的方式向下延伸,從下往上看就是要做到這些指標內容SLA才有可能達到,以上只是簡單的說明,更詳細的內容可以參考 Google Cloud 中的 SLOs, SLIs, SLAs, oh my - CRE life lessons 或是 Ant 大的 軟體技術架構如何正確與商業需求快速對齊:談 MAU 換算至 RPS,SLA 回推至 SLI 兩篇文章內容的詳細說明;因此在架構設計上,除了要考慮到需求情境之外,還需要考量到 SLI、SLO及SLA三者的目標,反思設計出來的架構是否都有包含上述功能性與非功能性需求,不斷反思是否有更好的解決方案。


    Design Process
    接著導師整理在設計架構時需要注意的的流程與議題
    Defining the service (Rough, Structured design, Measurable)
    3, and 4: Three-tier architecture (Data Layer[Storage], Biz logic Layer[Compute], Presentation Layer[Networking])
    Resiliency, Availabilty, Scalaility, and Disaster Recovery
    Security
    Capacity planing and Cost Optimization
    Deployment, Monitoring and Alerting, and Incident Response
    
    比如說目標是承受同時在線 10萬人,要思考的是設計出來的系統架構可以乘載同時 10萬人的 request量;設計出來的架構是否有彈性與擴充性,遇到災難是要如何進行快速的復原;要如何確保系統的Security,像是密碼一定要做 hash之類;使用量一年會產生多少 cost 是否有 plan ?;最後是如何進行 deployment ? 如何監控線上的環境與機器服務,如何第一時間知道使用者出問題,出問題時要如何處理 ?
    為了讓同學們有更好的理解,導師也分享過去工作上架構設計的專案與跟同學說明為什麼這樣設計(原由),也提醒同學簡報技巧也是重要的技能之一,當我們想要說服老闆使用或引入新架構時,從老闆的角度來出發像是思考老闆可能最關注的點像是會增加多少預算、會帶來多少效益以及瓶頸會在那裡跟如何解決,節省老闆的時間也讓決策者方便快速做決策。


    Business/Product Methodology
    最後導師補充一些與 PM 比較相關的觀念,希望同學在鑽研技術之餘,多去了解或學習一些常用商業模型對架構設計也是有幫助的,由於這領域自己不太熟悉因此在介紹時會加上 wiki 連結介紹,讓有興趣的朋友請自行點擊深入了解,若對於方法論內容理解有錯歡迎糾正。

    AARRR
    AARRR 模型是一個有名的方法論,每個英文單字都代表指標分別是Acquisition、Activation、Retention、Revenue以及Referral,主要是在談怎麼樣獲取用戶,在導師介紹完模型的說明讓我想起(後知後覺)待過的T社部門職責分工相似,部門分別負責特定指標,公司為了協助達標每個部門都有自己的RD團隊來專心支援前線單位完成其指標,

    Lean Startup
    Lean Startup 精實創業 : 概念與 scrum 類似,當你今天有一個 idea 時候以最小可行產品(MVP)來實現,提早讓使用者來驗證 idea 想法是否有效,並在使用過程中加上 measure,再透過 measure 產生的 data 思考要如何調整 idea 讓它更好,試圖在 measure 的過程中尋找可能的商機(契機)。這方法論很常在創業的朋友討論中提到,在公司草創初期都希望在最短的時間找到可行的模式,早日度過黑暗期。

    Scrum - Most Important is Value
    Scrum 敏捷開發 是這幾年很紅的方法論,用小步快跑的方式快速提交最有價值的功能,網路上已經有非常多相關知識這不在多廢話。
    另外導師還提到了像是 Steve Blank - Customer Development、Alexander Osterwalder - Business Model Canvas 與 Value Proposition 等方法論,但礙於大腦容量有極限且未接觸過,這就筆記下來日後有機會再自行研究。

    心得
    這是小組的第一次討論,組員分享自己的技能樹時聽到過去很多自己未接觸到的名詞,可以學到不同領域的知識感覺挺好的;在過去自己對於其守備範圍理解都是較為零碎的,可能是發現甚麼重要就盡力的去點滿其技能,在這次盤點 skill tree 的過程中才真正的去思考自己的目標(Goal)為何 ?自己希望哪些技能是應該具備的,對各技能的熟悉程度與目前還尚缺那些技能,這些資訊擁有之後或許可以訂為日後的長期目標,定期 review 自己完成百分比(自虐again);在兩個半小時的討論過程中,導師也很熱心的與同學分享自己所了解知識與架構設計的經驗,也補充技術以外常見的幾個商業方法論,提醒大家偶爾可以跳脫技術學習不同的解決方案提升自己的商業思維;透過更多實作累積更多經驗,成為一位能夠真正解決問題不嘴砲的架構師。

    參考
    AARRR
    Lean Startup 精實創業
    Scrum 敏捷開發
    The Four Steps to the Epiphany
    Business Model Canvas
    Value proposition
    架構師的修練
    深度剖析什么是 SLI、SLO和SLA?
    SLOs, SLIs, SLAs, oh my - CRE life lessons
    從零建立商業技術團隊
    [ModernWeb2019] Taien - 高併發的道與術
    HTTP-Request-Smuggling (pdf)
    HTTP request smuggling
    HTTP Request Smuggling (HTTP 請求走私)
    軟體技術架構如何正確與商業需求快速對齊

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

    Design by Anders Noren | Blogger Theme by NewBloggerThemes.com