Hero Image
Design Reflection

需求設計與反省 最近面試遇到些需要我描述 SA 或是 SD 的工作經驗描述,發現我講得的零零落落的,不然就是根本忘了,故挑幾點印象比較深刻做文字整理,以便以後需要的時候可以回來這裡回想。 郵局信箱與招領 所有信箱都來自實際存在的地址,在第一次申請(141)建立可投遞的信箱維護所有基本資料(姓名、電話等等…)依賴信箱主檔與客戶基本檔。 實際投遞遇到問題或是租戶自行申請將影響信箱狀態變更(142 狀態如:續租或暫停使用等等…),影響信箱生命存續終止(145、146 如退租、屆期未續、轉空戶)。 若通訊地址有更改請先執行維護信箱交易(154 調整為改投或i郵箱)再執行退租,此時的通訊地址才會正確。 由多個交易可以看出信箱的所有狀態與存續的的生命週期。 所有變更資料面依賴信箱主檔、變更歷程寫入 BoxChange_LG(變更歷程)且幾乎所有報表查詢都會依賴變更歷程的最新一筆。 大量的計算邏輯(報表 781、782…)有大量的 sql 重複查詢,其實就是不同的查詢條件,可以彙總成共用 lib 抽離不同件數計算邏輯,不需要每個欄位都一個複雜又重工的 sql 指令。 反省: 礙於專案時程壓力,只好先寫寫看在再回過頭看需求細節的真實用意,其實很危險,很多姑且先寫寫看的功能,都會在終於懂得哪一刻發現很多多此一舉的地方,甚至在 QA 深入各個交易互測階段發現一些明顯邏輯不通的錯誤。 如果可以先了解欄位/物件真義,再進行開發還是比較好,但就是會需要說服 SA 把其他相關的交易規格都拿到,即便是大致掃一眼也是好的。 個資軌跡 h 銀行 個資軌跡交易類別,依 dal 實際邏輯做 function 做預設值參考,服務可以傳入參數強制改為要或不要寫入個資軌跡。 trackType比如: 查詢(新增/修改/刪除交易的查詢、新增 、修改 、刪除 等等。 db Entity 新增 annotation 註記不同機敏程度的代號,透過共用的 Repositary 層偵測更新的 model 牽涉機敏欄位多寡來記錄個資軌跡,並抽離以方便維護是否紀錄的邏輯 if (A_TypeCount >= 2 || (A_TypeCount >= 1 && B_TypeCount >= 1)) return 則記錄個資軌跡; 反省: 資料面攔截所有系統的機敏軌跡,但忽略列的業務邏輯層建立的 dto 也有個資,dal 可以寫入的內容有限,只能記錄自定義的 trackType 且依賴回傳的 TEntity result,如果回傳結果有多層 entities 結構,無法紀錄深層機敏資料( 多層 Entity 結構 )且會顯示 Expression Tree (LINQ 原始表達式字串) 無法讀取內容物例如: c.IdNo == value(HuaNan.Service+<>c__DisplayClass3_0).input.IdNo)

Hero Image
Distributed System

Distributed System 分散式系統設計,Net 8 服務,啟用 nginx upstream 從單機到多實例後,遇到的設計問題。 核心概念:Stateless Service 什麼是 Stateless? 定義:服務的每個實例不保留任何與特定請求或使用者相關的狀態資訊。 為什麼需要 Stateless? ┌─────────┐ ┌──────────────┐ ┌──────────┐ │ Client │────▶│ Load Balancer│────▶│Instance A│ └─────────┘ └──────────────┘ ├──────────┤ │ │Instance B│ │ ├──────────┤ └─────────────▶ │Instance C│ └──────────┘ 當你的系統從 1 台機器擴展到 N 台時: 請求分散:用戶的連續請求可能落在不同實例 實例隨時變動:Auto-scaling 會新增/移除實例 故障轉移:某個實例掛掉,流量會轉到其他實例 ❌ 禁止使用的狀態儲存方式 方式 為什麼不行 實際案例 IMemoryCache 只存在單一實例 User A 的資料在 Instance A,但下次請求到 Instance B static 變數 無法跨實例共享 計數器在每個實例都是獨立的 Singleton 內部狀態 每個實例有自己的 Singleton Session 資料只存在啟動該請求的實例 檔案系統 本地儲存 上傳的檔案只在一台機器上 ✅ 狀態必須外部化 所有狀態都必須存放在所有實例都能存取的外部系統:

Hero Image
NFS

NFS Local-like File Access 類本地讀寫 Network FileSystem 網路檔案系統,NFS 是一種讓多台電腦可以像操作本地硬碟一樣訪問遠端檔案的系統。 是一種 RPC Service(Remote Procedure Call),當你用 NFS 讀寫檔案時,客戶端其實是在透過 RPC 向伺服器發送「打開檔案」「讀檔案」「寫檔案」這些遠端操作的請求, Dynamic Port Allocation 動態端口 容器配置不需要額外維護 port export,rpcbind 會自動協調服務所使用的 TCP/UDP port,並且同一個 network 內的容器可以直接訪問這些 port;若存在防火牆或跨主機通信時,則需要額外開通對應 port,配置相對複雜。 Server/Client 伺服器/客戶端 因為是一種 RPC Service,所以會有兩種角色 Server、Client 就像 FileZilla 也是,你要遠端可以 FileZilla 連到,你需要在 target server 安裝 FileZilla server 或其他 ftp 類型 server on 著 listening ( 持續運行以監聽連線請求 ) 當 server 啟用時,可以讓服務跨 os、跨 server,同步讀取、寫入本地檔案。 ┌─────────────────┐ 網路 ┌─────────────────┐ │ NFS Server │ <─────────────────> │ NFS Client │ │ (141) │ │ (142) │ │ │ │ │ │ /nfs (實體目錄) │ ─────匯出(export)──> │ /nfs (掛載點) │ │ chmod 777 │ │ mount 後可存取 │ └─────────────────┘ └─────────────────┘ 安裝 Windows 啟用 server/client 開啟或關閉 Windows 功能

Hero Image
RAG

RAG Retrieval-Augmented Generation RAG(檢索增強生成)是一種架構模式。 在 LLM 生成答案前,先從外部知識庫檢索相關資料,再將檢索結果提供給模型作為上下文,提升回答的正確性、可控性與即時性。 LLM 的本質:條件機率模型(Conditional Probability Model) 定義 大型語言模型(LLM)的核心任務只有一個:在給定前文條件下,預測下一個 token 的機率分佈。 數學形式為: P(token_t | token_1 … token_{t-1}) 表示在給定前文 token 的情況下,模型預測下一個 token 的機率。 這個機率分佈是由模型內部的所有參數(weights)共同決定的。 這些參數並不儲存任何可直接查詢的知識內容,而是隱式地編碼了大量語言片段之間的統計關聯與結構模式。 LLM 並不具備「查詢」、「記憶文件」或「事實驗證」能力。 LLM「知識」從何而來 X LLM 沒有文件 X LLM 沒有資料表 X LLM 沒有條目式知識 O 參數空間中所編碼的統計關聯結構 壓縮後的語言世界模型 訓練階段:把世界「壓縮」成參數,訓練資料(書籍、文件、程式碼、維基百科)僅用於不斷調整模型參數,強化 token 與 token 之間的關聯機率 資料不會被儲存,僅留下統計痕跡。 小模型仍「看起來懂很多」 多數人類知識是低熵、可高度壓縮的 技術文件與教科書高度模板化 (token 關聯穩定) 常識與基礎知識在語料中反覆出現 因此:只需要很少參數就能學到這種穩定規律,LLM 並非記住內容,而是學會「怎樣說才像懂」。 Transformer 擅長「關聯建模」 世界不是隨機的,而是高度可壓縮: 長距離 token 關聯 抽象語義空間 結構對齊(Structure Alignment) Transformer 等於一個超強壓縮器,這讓它可以: 將問題對齊到「已見過的語言模式」 再生成對應回應 回答不是「查到」,而是「生成」,不是回憶,是重建 類比

Hero Image
Multi-Tenant JWT Authentication

LineCRM.CarCare 登入架構說明 Multi-Tenant JWT Authentication 多租戶(Multi-Tenant)JWT 雙 Token 認證機制(Access Token + Refresh Token),支援商店用戶(Store)與客戶用戶(Customer)兩種身份類型的獨立認證流程。透過泛型設計與介面抽象,實現了可擴展的多角色登入系統,並結合 Redis 快取機制管理 Refresh Token,提供安全且高效的身份驗證解決方案。 Key Features 雙 Token 機制:Access Token (短效) + Refresh Token (長效) 多角色支援:Store User 與 Customer User 獨立認證 自動 Token 更新:Middleware 自動偵測過期並刷新 分散式快取:Redis 管理 Refresh Token 狀態 安全性強化:HttpOnly Cookie + CSRF 防護 可擴展架構:新增用戶類型僅需實作兩個介面 1. Adapter Pattern (適配器模式) 位置: StoreInfo 、 CustomerInfo、 IClaimAdapter.cs public interface IClaimAdapter<CurrentUser> { IEnumerable<Claim> GetClaims(); static abstract CurrentUser? FromClaimsPrincipal(ClaimsPrincipal principal); } public class CustomerContext : AppDataContext<CustomerInfo> { public CustomerContext(IHttpContextAccessor httpContextAccessor, IBaseLogger log) : base(httpContextAccessor, log) { } public override CustomerInfo? CurrentUser { get { var user = _httpContextAccessor.HttpContext?.User; return CustomerInfo.FromClaimsPrincipal(user); } } } public class CustomerInfo : IClaimAdapter<CustomerInfo> { public IEnumerable<Claim> GetClaims(){} public static CustomerInfo? FromClaimsPrincipal(ClaimsPrincipal principal){} } 說明:

Hero Image
Typora

Typora a nice .md file editor IDE 撰寫者:Amanda Chou 日期:2025/04/17 .md ? md 是什麼? Markdown 文件的副檔名 Markdown 又是什麼? Markdown ? **Markdown **是一種輕量級標記式語言,創始人為約翰·格魯伯。 使用易讀易寫的純文字格式編寫文件,然後轉換成有效的XHTML(或者HTML)文件。 這種語言吸收了很多在電子郵件中已有的純文字標記的特性。 輕量化、易讀易寫特性,並且對於圖片,圖表、數學式都有支援 Markdown 用途廣泛 目前許多網站都廣泛使用Markdown來撰寫說明文件或是用於論壇上發表訊息。如GitHub、Reddit、Discord、Diaspora、Stack Exchange、OpenStreetMap 、SourceForge、簡書等,甚至還能被用來撰寫電子書。 之前介紹的 Vue 文件 重新認識 Vue.js | Kuro Hsu git book 也是 深入淺出 GitBook 寫作與自助出版,電子書也能多人協作 HackMD 也是 小題大作的30個 HackMD 技巧 現在演示的這個投影片也是 md fille 怎麼變 slide? 後面針對匯出章節會提到 Why Markdown 輕量易用:Markdown 語法簡單直觀,幾乎無學習成本。(幾乎沒有,但還是有一點,語法還是需要熟悉一下) 高度可移植:Markdown 文件是純文字格式,可以在任何平台上查看或編輯,方便與版本控制工具,適合開發者和團隊協作。 多用途輸出:支援導出為 PDF、HTML、Word、Slides 等多種格式。特別適合技術文件、筆記、部落格文章等用途。 多輸出主要是依賴 Pandoc 工具支援,後面針對匯出章節會提到 強大的生態系統:可擴展性強,支持 LaTeX(數學公式)、圖表(如 mermaid.js)、代碼高亮等功能。 開放性標準:Markdown 是一種開放格式,無專屬軟體依賴,確保文件長期可讀。 參考: 寫作&筆記神器 MarkDown 真希望我學生時期就懂 分享了 dillinger, Typora 還有影片介紹 Why Markdown 只要可以版控,就會好找很多 如果有要找,版控,就會好找很多

Hero Image
Infra Diagram Tool

Infra Diagram Tool Drawio 系統架構圖 Infrastructure Diagram 高可用設計 安全 / Network / Trust Boundary 跨團隊、跨角色溝通 ✅服務 icon 支援多元 ❌可版控但 diff 不易閱讀 (xml) ❌無法整合 README.md (只能匯出 png/svg) Mermaid Service 關係示意 Request flow CI/CD pipeline 小型單機或單服務結構 ✅方便 diff 版控 ❌不支援服務 icon 顯示 ❌無法精準控制位置/大小 %%{init: { "theme": "base", "themeVariables": { "background": "#fdecef" } }}%% graph LR %% ====== Global Style ====== classDef default fill:#fdecef,stroke:#efb752,stroke-width:1px,color:#000; linkStyle default stroke:#333,stroke-width:1.5px; %% ====== Custom Styles ====== classDef serverStyle fill:#99d9ea,stroke:#6c9aa5,stroke-width:1px,color:#000; classDef vmStyle fill:#f7cb9f,stroke:#f79c67,stroke-width:1px,color:#000; classDef dockerSwarmStyle fill:#81e1f7,stroke:#4a90e2,stroke-width:1px,color:#000; classDef containerEngStyle fill:#97f7df,stroke:#2fa4a9,stroke-width:1px,color:#000; classDef idle fill:#ffb3c3,stroke:#ff5a78,stroke-width:1px,color:#000; red[["(1) netplan 192.168.168.n (2) red represent idle for manual stand by"]]:::idle client((client)) client --> Nginx subgraph Server100["Server 100 windows"] nfsc100["nfs client client conn 101"] mssql[("MSSQL 1436")] subgraph Server101["VM 101 ubuntu"] nfss["nfs server"] subgraph containerEng["101 Container Engine"] Nginx("Nginx dependent main proxy") redis("redis") seq("seq") subgraph dockerSwarm["Docker Swarm"] direction TB StoreWeb("store web") --> StoreApp("store api") CustomerWeb("customer web") --> CustomerApp("customer api") CRMBackend("CRMBackend") end end Nginx --> StoreWeb Nginx --> CustomerWeb Nginx --> CRMBackend end StoreApp --> mssql CustomerApp --> mssql CRMBackend --> mssql end subgraph Server200["Server 200 windows"] nfsc200["nfs client client conn 101"] mssql200[("MSSQL 1436")]:::idle subgraph Server201["VM 201 ubuntu"] nfss201["nfs server"]:::idle nfsc201["nfs client client conn 101"] subgraph containerEng201["201 Container Engine"] Nginx201("Nginx dependent main proxy"):::idle redis201("redis"):::idle seq201("seq"):::idle subgraph dockerSwarm201["Docker Swarm"] StoreWeb201("store web") --> CustomerWeb201("customer web") StoreApp201("store api") --> CustomerApp201("customer api") CRMBackend201("CRMBackend") end end Nginx --> StoreWeb201 Nginx --> CustomerWeb201 end StoreApp201 --> mssql CustomerApp201 --> mssql end %% ====== Apply Styles ====== class Server101,Server201 vmStyle class dockerSwarm,dockerSwarm201 dockerSwarmStyle class containerEng,containerEng201 containerEngStyle class Server100,Server200 serverStyle

Hero Image
MS SQL AutoGrowth

Performance Issue Table Column Setting Column store Index 資料行存放區索引 「資料行存放區索引」是儲存和查詢大型資料倉儲事實資料表的標準。 此索引使用以資料行為基礎的資料儲存和查詢處理,相較於傳統的資料列導向儲存,最高可在您的資料倉儲中達到 10 倍的查詢效能改善。 相較於未壓縮的資料大小,您也可以將資料壓縮提升高達 10 倍。 從 SQL Server 2016 (13.x) SP1 開始,資料行存放區索引可啟用作業分析:在交易式工作負載上執行高效能即時分析的能力。 Database Properties Setting Auto Shrink Database Properties Auto Shrink 的作用是釋放未使用的磁碟空間,而不是壓縮或刪除資料。但由於它對性能和碎片化的潛在影響,建議在大多數情況下不要啟用。如果需要清理磁碟空間,可以使用手動的方式來更有效地管理。 Autogrowth 自動增長設置 Database Properties 設計用來在資料檔案(Data File)或日誌檔案(Log File)空間不足時,自動擴展檔案大小,以保障交易和數據寫入的正常進行。 在處理高交易量與高併發的環境中,自動增長占用的效能可能成為效能瓶頸之一。 尤其當增長頻繁或配置不佳時,可能導致系統資源緊張或操作延遲。 適當規劃初始檔案大小與增長策略,不僅能避免增長對效能的負面影響,還能為穩定數據處理提供堅實基礎。 table 的資料,一頁一頁存在資料庫裡,每頁固定 8KB , SQL Server 檢查文件中是否有足夠的頁(8 KB 每頁)來滿足當前數據插入或更新操作的需要。 Check Unused spaces Check File Unused spaces SELECT (size - FILEPROPERTY(name, 'SpaceUsed')) * 8 / 1024 SpaceUnused, size, FILEPROPERTY(name, 'SpaceUsed') SpaceUsed, * FROM sys.database_files Check Table pages Unused spaces