只有累積,沒有奇蹟

2025年12月25日 星期四

[meetup] DevOps Taiwan Meetup #74 《建構多租戶 SaaS 架構》新書導讀

議程介紹
主題 : 《建構多租戶 SaaS 架構》新書導讀
《建構多租戶 SaaS 架構》新書導讀

課程大綱
▋ 從單體到多租戶:是升級還是修羅場?
  「從單體轉向多租戶」——你以為這是一場升級,結果它往往是一場墜落。
  一個讓系統變複雜、讓工程師變沉默的坑。
  剛開始以為只要多加一個 TenantId 就能搞定,
  結果查詢變慢、資料變亂、部署變痛,成本更是像記憶體洩漏一樣,一旦開始就難以回收。
  每解一個問題,就會掉進另一個坑——
  效能解了,卻出現租戶干擾;
  資料分開了,Migration 又成災;
  部署自動化了,成本卻無法對齊。
  本來以為自己能從從容容、游刃有餘地打造架構,
  結果變成匆匆忙忙、連滾帶爬地追著 bug、救著火。
  那一刻你會明白,這條路不是升級路線,而是一次又一次的試煉。
  你寫的不只是程式,而是一連串的補丁與懺悔。
  查 log、修腳本、追異常成為日常;功能開發成了奢侈。
  你以為自己在救火,但其實你正在為系統的複雜度繳學費。
  當團隊的焦點從「創造價值」轉為「維持穩定」,
  工程師也從「開發者」變成「問題管理員」。
  你才真正理解——
  → 多租戶不只是架構上的挑戰,它更是團隊心理韌性與工程紀律的考驗。
▋ 從坑到結構的覺醒
  當你從坑裡爬出來回頭看,你會發現這些問題早已不是偶發事件,
  而是每個 SaaS 團隊都得面對的共同考題。
  這也是《建構多租戶 SaaS 架構》真正想帶你看見的現實:
  → 多租戶不是一種部署方式,而是一場關於效能、資料、維運與成本的修行。
  理解這四件事,才是真正邁向多租戶成熟的起點。
一、效能:不只是跑得快,而是信得過
  如果你曾被客戶問過:「為什麼今天比昨天慢?」
  那你就知道效能不只是技術問題,而是信任問題。
  在單體架構時,你只在意系統跑得快不快;
  進入多租戶後,問題變成——誰讓誰變慢了。
  A 客戶開了一個報表,B 客戶就開始卡頓。
  這不是 bug,而是「Noisy Neighbor」的現實。
  → 效能不只是數字,而是一種信任契約。
二、資料架構:風險與效率的對話
  每一個架構師都會面臨這個靈魂拷問:
  要不要共用 Schema?要不要分庫?
  這些看似是技術問題,其實每一個決策背後都是風險選擇。
  共用架構代表成本低,但錯誤可能牽連所有租戶;
  獨立架構代表安全,但維運與版本控制的成本將倍增。
  → 架構沒有完美的答案,但成熟的團隊懂得在風險與效率之間,
  找到能讓產品長久運行的平衡點。
三、維運:從部署變成節奏
  當部署頻率越高、租戶越多,
  每一次上線都像踩在一個尚未確認的地雷區。
  單體時,部署只是動作;
  多租戶後,部署變成節奏。
  一次上線,影響所有租戶;
  你開始需要灰度釋出、分群升級、即時回滾。
  這不再只是 CI/CD 的自動化,而是整個團隊如何定義「穩定」的制度。
  → DevOps 在這裡不只是流程,而是一種信任治理的文化。
  維運,不只是穩定系統,而是穩定人心。
四、成本切分:從效率到價值的覺醒
  如果你曾在帳單前皺眉,
  你就知道多租戶最難的,不是效能,而是「看不見的成本」。
  A 客戶每天跑十次報表、佔滿資源;
  B 客戶只上傳一份 Excel,卻付相同的錢。
  久而久之,你會發現 SaaS 的瓶頸不在 CPU,
  而在於成本缺乏對應與衡量機制。
  沒有清楚的成本映射,團隊就只能憑直覺調整。
  真正成熟的架構,不是壓低成本,而是讓成本與價值產生對應。
  → 那不只是技術能力,而是經營能力。
▋ 從效能治理到價值治理
  在雲端時代,SaaS 不只是技術選擇,
  更是一種產品與營運思維。
  《建構多租戶 SaaS 架構》就是你的解藥。
  本書由 AWS 資深架構師 Tod Golding 撰寫,
  他以多年協助 SaaS 團隊轉型的實戰經驗,
  總結出多租戶設計、部署與營運的完整方法論。
  那些讓你掉坑的問題,書中都有出口 
  ・第 09 章〈租戶隔離〉:如何避免 Noisy Neighbor
  ・第 08 章〈資料分區〉:在共用與分庫間找到平衡
  ・第 12 章〈租戶感知營運〉:建立租戶級的監控與自動化
  ・第 14、17 章〈分級策略/指導原則〉:讓架構、營運與商業模式對齊
  Golding 在書中不斷提醒我們:
  SaaS 的本質不是「上雲」,而是「統一思維與多樣彈性之間的平衡」。
  從第 01 章〈SaaS理念〉到第 17 章〈指導原則〉,
  他帶領讀者看見 SaaS 架構不只是技術結構,
  更是一種願景、策略、組織與營運文化的總和。
  如果你還不懂多租戶,這本書會帶你從 0 到 1。
  如果你正陷在坑裡,這本書能讓你少走幾年冤枉路。
  如果你已撐過那些坑,這本書會幫你整理經驗,帶領下一個團隊走得更穩。

主辦單位 : DevOps Taiwan 技術社群
議程表 : 連結
投影片 : 連結



2025年11月28日 星期五

[conference] .NET Conf Taiwan 2025 - Spec-kit x O.D.D:AI 時代的 .NET 開發新選擇

分享心得
AI 可以說是不可逆的趨勢,但礙於 LLM 先天的限制有幻覺性,大家在開發上雖然使用的很開心,但實際開發還是會有些不如預期的地方。這次就跟大家分享自己研究一款熱門的 open source 框架 spec-kit,有了 AI 後怎麼降低系統上線營運的問題也可以說是一大挑戰,這裡就帶入了之前研究可觀測性的一些重要觀念,可以透過 AI 的規範性將可觀測性重要的 singals 讓大家在開發時可以更輕鬆,當然也有帶到我個人覺得當 AI 更便利後,他也是一個放大器,放大我們不會的項目跟資訊,因此有哪些基本公式重要的也一併帶入,希望可以為大家帶來些不一樣的思考,謝謝 :D

議程介紹
主題 : Spec-kit x O.D.D:AI 時代的 .NET 開發新選擇?
Spec-kit x O.D.D:AI 時代的 .NET 開發新選擇?

課程大綱
AI 加速了開發流程,卻也讓「品質」與「透明度」成為新的挑戰。 本場分享將介紹如何結合 Spec-Kit 的規格驅動開發(Spec-Driven Development, SDD) 與 可觀測驅動開發(Observability-Driven Development, ODD),讓 .NET 開發者能從需求定義到系統行為驗證,打造一條「AI 寫得快、系統看得清」的開發流程,讓每一次上線都能被觀測、被驗證、被信任。

主辦單位 : Study4
議程表 : 連結
投影片 : 連結



2025年10月14日 星期二

[conference] Hello World Dev Conference 2025 - 從錯誤到成長:新手主管必經的修煉之路

分享心得
這是我今年在 Hello World Dev 的分享,起心動念源於去年聽了好友 Kyle 的議程後,決定動手整理這幾年的技術管理經驗;這份簡報聚焦於我在新手主管時期踩過的無數個坑,是一份關於「從入門到差點放棄」的真實紀錄。 老實說我自己以前聽管理學講座時也很容易睡著,所以當我要分享這段從資深工程師轉職為主管的「血淚史」時,我決定用 RPG 遊戲攻略來講故事! 還記得剛拿到 Supervisor 頭銜時 ,以為自己轉職成了「英雄」,結果進了副本才發現,自己只是換了個地方當「高級打雜工」。 這份簡報試圖幫大家拆解那個最可怕的 Dead Loop(死循環): 💀 任務變多 ➔ 解釋太慢 ➔ 自己動手做 ➔ 授權變少 ➔ 團隊依賴 ➔ 主管更忙 其實忙到年底,原本已經忘記這場演講了,直到最近收到大會寄來的 Feedback Report,看到許多會眾的回饋讓我很有收穫,而且評分竟然有 8.89 / 10(全場最高分是 9.33);回想起自己在跌倒爬起來的過程中,也曾受到很多 mentor 與前輩的幫忙;抱著或許也能拉後來的人一把的心情,我決定「厚著臉皮」把這份簡報貼出來 最後,就算今天 Game Over 了也別怕,這份攻略就是你的 復活點 (Save Point)。 真的再過不去... 先去茶水間 CD 補個血,我們隨時可以按下重啟 restart (重生) 再戰

議程介紹
主題 : 從錯誤到成長:新手主管必經的修煉之路
從錯誤到成長:新手主管必經的修煉之路

課程大綱
從專業的開發者,轉變為帶領團隊協同作戰的主管,這是一場思維模式與職責重心的革命。許多新手主管在初期往往誤以為只要延續過去的成功經驗,或僅憑一腔熱血就能勝任。但現實上管理職不僅要求你驅動團隊達成目標,更要你在上層的戰略期望與成員的職涯發展之間,尋求精妙的平衡點,複雜度遠超想像。第一次被賦予管理責任,總對這個新角色抱持著美好憧憬,但這些想像真的能幫助我們應對真實世界中那些隱藏的挑戰嗎?
在這場議程中,我將以自身失敗經驗出發,帶你走過新手主管最容易因為認知偏差與實踐誤區所導致的五大盲點。我會分享這些問題是如何發生的,以及其背後的核心癥結(例如:溝通壁壘、授權困境、衝突迴避等),並提供實用的應對策略與思維框架。這條路上我學到了許多關於領導、協作與自我反思的寶貴經驗。希望透過這次分享能幫助與會者快速識破這些潛在的陷阱,少走冤枉路,從容應對管理上的複雜挑戰,共同成長,實現從專業技術開發者到新手主管的轉型。

主辦單位 : DevOpsDays Taipei iThome 主辦
議程表 : 連結
投影片 : 連結



2025年6月5日 星期四

[conference] DevOpsDays Taipei 2025 Bootcamp 從 Day 0 開始的可觀測性:用 ODD 與 SLO 的實作工作坊

分享心得
很高興再次有機會可以在台灣最熱門的技術研討會 DevOpsDays 分享,會有這次分享是因為艦長的邀請一起籌辦 Devops bootcamp x observability,自己也在這準備的過程中進行了第一場的工作坊,過去很多時間都是用講的方式來進行,今天希望把自己過去的經驗在工作坊設計中帶給大家體會,希望大家會喜歡

議程介紹
主題 : 從 Day 0 開始的可觀測性:用 ODD 與 SLO 的實作工作坊?
DevOpsDays Taipei 2025 Bootcamp 從 Day 0 開始的可觀測性:用 ODD 與 SLO 的實作工作坊

課程大綱
在不斷發展的雲端原生技術領域中,觀察應用程式的性能和健康狀態已不再是一種奢侈,而是必要的關鍵。隨著微服務架構成為常態,分散式系統擴展,以及資料量的爆炸性增長,傳統的監控工具難難以捕捉服務之間錯綜複雜的互動和依賴關系。這種缺乏連貫的可見性,導致了可見性缺口,使得難以精確定位性能瓶頸、診斷問題以及確保應用程式的健康。可觀測性工程的出現將補足這樣的缺口,該次工作坊將深入淺出地介紹將可觀測性理念轉化為實際行動的方法。

課程目標
體驗 Observability 帶來的可見性價值
學會制定 SLO,確保服務穩定性與可用性
設計符合自己團隊的 Observability 推動策略

主辦單位 : DevOpsDays Taipei iThome 主辦
議程表 : 連結



[conference] DevopsDays Taipei 2025 - 為什麼我們需要 Observability?

分享心得
很高興再次有機會可以在台灣最熱門的技術研討會 DevOpsDays 分享,這次受到 Devops Taipei 社群夥伴艦長的邀請,在 Devops Taipei bootcamp 規劃與籌辦 observability 可觀測性 bootcamp,可觀測系這議題在這幾年已非常火熱,但對於剛入門的新手來說可能有點挑戰,怎麼讓大家知道他的基本觀念與可以解決什麼問題是非常重要的,因此在研討會過程中設計了技術分享 + 工作坊多種議題,希望從基本觀念與實作的角度上來幫助大家,這分享是可觀測性 bootcamp 第一場,歡迎大家提出來進行討論,Happy learning 🙂

議程介紹
主題 : 為什麼我們需要 Observability?
為什麼我們需要 Observability?

課程大綱
隨著 Observability(可觀測性)的觀念逐漸普及,它早已不只是工具或儀表板的選擇,更成為團隊理解系統行為、優化效能,以及即時應對異常狀況的關鍵能力。
本場演講將從「台灣企業在導入 Observability 的真實現況與挑戰」出發,揭示企業在實作過程中最常遇到的技術困境與落地瓶頸。你將認識 Observability 如何從傳統的監控(Monitoring)演進而來,並透過 OpenTelemetry 等開放標準實現跨系統的資料串接與分析,協助團隊更有效地觀察、診斷與優化系統。
除了技術視角,我們也將初探導入 Observability 的組織挑戰,包括開發、SRE、產品與營運團隊間的溝通落差、SLO(服務水準目標)的制定困難,以及遙測數據雖豐但洞察不足的常見困境。
演講最後,我們將介紹 Observability Bootcamp 的設計核心,帶你一探團隊如何從「讓系統說話」,到「聽見並理解訊號」,最終「以數據驅動優化」,幫助與會者理解如何將 Observability 落實於日常工作流程中,以正確的觀念與態度面對 Observability。

主辦單位 : DevOpsDays Taipei iThome 主辦
議程表 : 連結



2025年3月8日 星期六

[NET] 移除未使用的 ASP.NET SDK 版本

前言
最近筆電空間告急,在 Google 解決方案時發現過去自己有撰寫過一篇文章是 移除未使用的 ASP.NET Core SDK,但仔細看完內容加上已經過了五年的時間,深深覺得五年過去會有更好的解決方法,於是乎終於讓我找到更有效的方法可以移除未使用的 dotnet framework 版本,這篇就跟大家簡單分享,與若對於上述內容有問題或是不清楚的地方,歡迎提出來一起討論。

查看 SDK 版本
首先,我們來透過指令來看目前電腦有安裝哪些版本 SDK (chatGPT 用多了,在用字描述上都不自覺用首先...其次 XDDDD)
dotnet --list-sdks 
透過此指令可以查詢到目前電腦中安裝的 SDK 版本與安裝路徑位置
如果想要查看 runtime 則可以輸入
dotnet --list-runtimes
透過上述方式看到目前電腦所安裝的 Runtime 與 SDK 版本,如果長期使用 dotnet 開發的朋友們可能也知道安裝時會在固定位置,例如
執行檔 : C:\program files\dotnet\dotnet.exe
.NET SDK : C:\program files\dotnet\sdk\版號
.NET Runtime : C:\program files\dotnet\shared\{runtime-type}\版號\

解法 : Windows 內建移除
如果是要移除單一的應用程式,一般可以到 應用程式 > 已安裝的應用程式 頁面來移除 .NET SDK 與 Runtime,
解法 : dotnet-core-uninstall
但上述做法只適用於 SDK 量比較少的狀況,如果你電腦使用一段時間比較多的時候要逐一移除就會比較辛苦跟麻煩,這次主要是分享的方法是微軟官方提供在 2020 年所提供的新方法,提供一個好用的工具,將系統中的 SDK 進行控制與清理的動作,只保留自己在開發時所需版本的 runtime 和 SDK。

工具下載連結 : https://github.com/dotnet/cli-lab/releases

接著往下滑到 asset 區域,我所使用的 OS 是 windows 因此選擇下載 dotnet-core-unistall.msi 檔案
執行安裝下載的檔案,以目前最新版為例是 1.7.550802,安裝完畢後,開啟命令提示字元輸入 dotnet-core-uninstall
可以看到所支援的 command 如下
list : List .NET Core SDKs or Runtimes that can be removed with this tool.
 dry-run, whatif  : Display .NET Core SDKs and Runtimes that will be removed.
 remove  : Remove the specified .NET Core SDKs or Runtimes.
該程式在移除上還是有提醒工具的限制
This tool cannot uninstall versions of the runtime or SDK that are?
    - SDKs installed using Visual Studio 2019 Update 3 or later.
    - SDKs and runtimes installed via zip/scripts.
    - Runtimes installed with SDKs (these should be removed by removing that SDK).
小提醒 : 在使用上還是記得開啟執行程式 cmd or powershell 前,需要使用系統管理員權限才能夠移除,權限不夠會出現 The current user does not have adequate privileges.提示

找出電腦所安裝的 SDK
輸入 dotnet-core-uninstall list 指令,可以透過程式找到目前電腦所安裝的 SDK 清單
移除 SDK
移除時請輸入指令 dotnet-core-uninstall remove 加上特定版本,例如上面看到目前電腦中有 7.0 & 8.0 版本,要移除時請輸入完整版號與指令,例如 dotnet-core-uninstall remove 7.0.410 --sdk 才會生效,確定後在下 Yes 即可

小結
以上快速介紹了使用微軟所提供的工具來刪除所安裝的 SDK,希望可以有機會幫到跟我一樣困擾的夥伴們,happy Coding !

參考
cli-lab

2025年2月8日 星期六

[NET] 探索 OpenTelemetry Auto-Instrumentation 的核心技術

前言
Observability 是手段,不是目的。透過 Auto-Instrumentation,我們更接近「讓系統自己說話」的願景。

在 COSCUP 2024 我有幸(不要臉) 再次參與並分享這一年來我在可觀測性實踐上最有趣的內容:「OpenTelemetry 的 Auto-Instrumentation 技術核心與應用實戰」。這篇文章,我會完整拆解 OpenTelemetry SDK 的 Auto-Instrumentation 的原理、架構、實務流程,並從開發者的視角出發,帶你理解什麼是「讓系統自己說話」,希望可以讓想要了解 OTel SDK 底層細節實作的朋友有幫助。


OpenTelemetry 是什麼

OpenTelemetry(簡稱 OTel)是 CNCF(Cloud Native Computing Foundation)旗下的觀測性開源計畫。它整合了 OpenTracing 和 OpenCensus,成為雲原生時代的統一觀測標準。

它主要處理三件事:

  • Instrument:幫助你從應用中收集觀測訊號(Signals)
  • OTLP:無論是 Trace、Metric 還是 Log,都有標準格式
  • Export:支援多種後端(如 Jaeger、Zipkin、Grafana Tempo、Prometheus...)

OpenTelemetry 是目前 CNCF 第二活躍的專案(僅次於 Kubernetes),也是現代 Observability 的標準。


Code-based v.s zero-code

讓程式「可以被觀察」,首先就要「儀表化」程式碼(Instrumentation)。這裡透過一張表整理 Code-based 與 zero-code 兩者的差異,更重要的是實際應用場景

小小建議:「Auto-Instrumentation 優先、Manual 優化補強」

Auto-Instrumentation 設計願景

根據 OpenTelemetry .NET Auto-Instrumentation 官方設計文件,這個 SDK 是以五大設計願景(Vision)為核心來開發的,每一個願景都對應到實務中我們真正關心的「導入門檻」、「維運穩定」、「擴充能力」。

高效能(High Performance)
  • 使用 IL 重寫,不改原始碼
  • Lazy Loading 降低資源開銷
  • 非同步匯出 Trace 資料
開箱即用(Useful by Default)
  • 內建常見欄位與框架支援
  • 啟動即生效
穩定可靠(Reliable)
  • 錯誤不影響應用
  • 具容錯能力與 fallback
可見(Visible)
  • 啟動時列出已啟用套件
  • 支援 metrics 與 debug mode
可擴展(Extensible)
  • 插件化結構,支援自定義與社群套件

Auto-Instrumentation 架構與元件
Application & Runtime(應用與執行環境)
  • Application IL(中間語言)
    .NET 應用程式編譯後的中間碼,是 Auto-Instrumentation 插入追蹤邏輯的目標對象。
  • CLR(Common Language Runtime)
    .NET 的執行核心,提供 ICorProfilerCallback / ICorProfilerInfo 介面供原生 Profiler 攔截執行事件與注入邏輯。
OTel CLR Profiler(Native)
  • 職責: 掛載在 CLR 上,透過 ICorProfiler API 攔截應用啟動流程。
  • 功能: 將 Bytecode Instrumentation 插入 Application IL,實現 Zero-code Observability。
Bytecode Instrumentations
  • 職責: 為特定框架提供具體的儀表邏輯,例如對 HttpClient、SQLClient、gRPC 注入觀測碼。
  • 功能: 在 method 內部插入 OTel API(如 StartSpan、SetAttribute)。
OTel Managed Profiler
  • 職責: 在應用執行階段進行進一步的邏輯注入與監控。
  • 用途: 管理細部的 Trace 拓展,例如更細緻的 DB query 或 gRPC 呼叫資訊。
Source Instrumentation / OTel SDK
  • Source Instrumentation: 指開發者手動使用 OTel API(例如 tracer.StartActiveSpan())插入觀測點。
  • OTel SDK: 提供觀測資料處理能力,負責收集、封裝並導出 Trace、Metrics、Logs 至後端。
架構運作流程
  1. 啟動階段: OTel CLR Profiler 掛載至 CLR,監控模組與 method 載入事件。
  2. 注入階段: Bytecode Instrumentations 對 IL 方法注入 StartSpan 等邏輯。
  3. 執行階段: Managed Profiler 進一步補強觀測點(如內部呼叫、Async 方法)。
  4. 資料導出: 所有訊號被 OTel SDK 收集後導出至 Tempo、Jaeger 等觀測平台。

設計重點 : 「模組化、低侵入、高彈性」


三大流程解析
註冊流程
重點:
  1. 設定環境變數:
    • CORECLR_ENABLE_PROFILING=1
    • CORECLR_PROFILER=OTel CLSID
    • CORECLR_PROFILER_PATH=Profiler DLL 路徑
  2. CoreCLR 啟動階段:
    • 檢查是否啟用 Profiling
    • 從 Registry 查找 CLSID 對應 DLL
    • 解析出 Profiler 的實際路徑
  3. 載入與初始化:
    • 載入 Profiler DLL
    • 呼叫 Initialize 方法註冊
    • 透過 ICorProfilerInfo 註冊事件攔截(Set Event Mask)

請求流程
重點 : 系統如何自動蒐集數據 Data (自己說話)
  1. 應用啟動: CoreCLR 發出多種事件通知,包括類別載入、JIT 編譯、方法進入與離開等。
  2. OTel CLR Profiler 攔截: 根據事件動態判斷並透過 IL 注入觀測邏輯(Bytecode Instrumentation)。
  3. Managed Profiler 建立與關閉 Span: 當方法被呼叫(FunctionEnter)時建立 Span;完成(FunctionLeave)後關閉該 Span。
  4. 外部服務呼叫: 如果方法內呼叫外部服務(API、DB),會建立額外的子 Span 表示呼叫鏈。
  5. OTel SDK 負責收集與導出: 所有已關閉的 Span 會統一被 SDK 收集並匯出至後端系統,如 Jaeger 或 Grafana Tempo。
數據流
重點
  • Application: 應用程式啟動,觸發 Auto-Instrumentation。
  • OTel CLR Profiler: 原生層級注入元件,處理 IL 攔截與上下文傳遞。
  • Bytecode Instrumentation: 插入具體的追蹤邏輯至目標方法(如 HTTP 請求)。
  • OTel Managed Profiler: 管理應用邏輯層級的觀測行為,呼叫 Instrumentation Handler。
  • OTel SDK: 中央資料處理站,封裝資料並準備匯出。
  • Collector: 集中資料後導出至 Jaeger(Trace)或 Prometheus(Metrics)。

ASP.NET Core 實作範例
services.AddOpenTelemetry()
    .WithTracing(builder => builder
        .AddAspNetCoreInstrumentation()
        .AddHttpClientInstrumentation()
        .AddGrpcClientInstrumentation()
        .AddOtlpExporter());

這段程式會自動收集:

  • http.method, http.status_code, http.url
  • trace_id, span_id, user_agent.original
.AddAspNetCoreInstrumentation()
  • Application : 在應用程式層級攔截整體 ASP.NET Core 的 Middleware Pipeline。自動追蹤整個 HTTP 請求從進入到離開的過程。
  • Controller : 對個別 Controller 進行觀測,例如:哪個 endpoint 被呼叫、哪些路由參數被解析
.AddHttpClientInstrumentation()、.AddGrpcClientInstrumentation()
  • 程式對外發出的 HTTP 請求(如 API 呼叫)
  • gRPC 呼叫事件,包含 method 名、service 名、status code
  • 只要你用標準的 HttpClient 或 .NET gRPC,這些都會被攔截、追蹤並補上 TraceContext。
.AddOtlpExporter()
  • 把觀測資料送到你的可視化平台
  • 例如 : OTLP → Grafana Tempo / Honeycomb / Lightstep / Jaeger / New Relic
用 C4 概念則可以劃出 Container 與 Component 內容
Container
Component

小結
Auto-Instrumentation 讓開發者可以不用動原始碼,就輕鬆讓系統「說出程式碼執行的狀態」,對於初學者在導入可觀測性文化中重要的環節,希望這篇介紹 Auto-Instrumentation 對各位有幫助,若以上內容有不清處的地方,歡迎留言討論,Hayyp Coding :)

參考
opentelemetry-dotnet
opentelemetry-dotnet-instrumentation
opentelemetry-dotnet-instrumentation/docs/design.md
dotnet/runtime/blob/main/docs/design/coreclr/botr/profiling

2025年1月16日 星期四

[NET] Task.WhenEach 等待多個任務的更靈活方式

前言
在過去如果要使用多個 Task 在 Dotnet 中可以使用 Task.WaitAll 和 Task.WhenAll 兩個內建的 API,其使用的差異之前也有撰寫文章 [NET] Task 等待多個任務 - Task.WaitAll 與 Task.WhenAll,這兩個方法都會等到所有任務完成後再繼續執行。如果當需求是完成一個就先進行處理,而不是全部完成後該怎麼辦呢 ? 這時就可以使用 Task.WhenEach 方法,來達到你所要的目的,這篇文章就簡單來介紹其概念與如何使用。

介紹
Task.WhenEach 是一種基於 Task.WhenAny 的模式,它的核心理念是當每個 Task 完成時立即執行對應的內容,而不用等待所有 Task 完成後再處理。這在某些場景下能提升應用的回應速度,尤其是當每個任務的執行時間不相同時,避免了某些較早完成的任務閒置等待其他長時間運行的任務,拖累到整體任務的完成時間。讓我們用一個範例來展示 Task.WhenEach 的概念。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

public class Program
{
    static async Task Main(string[] args)
    {
        List> tasks = new List>
        {
            SimulateWork(1, 1000),
            SimulateWork(2, 2000),
            SimulateWork(3, 3000),
            SimulateWork(4, 4000),
            SimulateWork(5, 5000),
        };

        await TaskWhenEach(tasks);
    }

    static async Task SimulateWork(int id, int delay)
    {
        await Task.Delay(delay);
        Console.WriteLine($"Task {id} completed after {delay / 1000.0:F2} seconds");
        return id;
    }

    static async Task TaskWhenEach(IEnumerable> tasks)
    {
        var taskList = tasks.ToList();
        
        while (taskList.Any())
        {
            var completedTask = await Task.WhenAny(taskList);
            taskList.Remove(completedTask);
            Console.WriteLine($"Processed result: {await completedTask}");
        }
    }
}

  
  
簡單說明 Task.WhenEach 的運作方式
1. 建立多個非同步任務,這些任務模擬不同時間長度的工作。
2. 使用 Task.WhenAny 找到第一個完成的任務,立即處理結果。
3. 從列表中移除已完成的任務,然後繼續等待剩餘的任務。
4. 重複上述步驟直到所有任務完成。
這樣的設計確保了不會有執行緒閒置等待較長的任務結束,而是每當一個任務完成就立即執行處理邏輯,提升了 application 或功能的回應速度。

執行結果
Task 1 completed after 1.00 seconds
Processed result: 1
Task 2 completed after 2.00 seconds
Processed result: 2
Task 3 completed after 3.00 seconds
Processed result: 3
Task 4 completed after 4.00 seconds
Processed result: 4
Task 5 completed after 5.00 seconds
Processed result: 5

 

應用場景
即時資料處理:
- 當一組異步任務代表不同的 API 請求時,可以使用 Task.WhenEach 來立即處理已完成的請求,提升使用者體驗。
非同步串流處理:
- 當我們要處理大量非同步工作時,Task.WhenEach 可以確保已完成的工作不會閒置,而是立即傳遞到下一個處理步驟。
UI 更新:
- 在 UI 應用中,當我們需要執行多個背景任務,並希望它們完成後立即更新 UI,可以使用 Task.WhenEach 來確保 UI 變更即時發生。

小結
希望這篇文章能幫助讀者了解 Task.WhenEach 的基本概念與應用,如果有任何問題或建議,歡迎交流討論,happy Coding !

參考
Task.WhenEach 方法

2024年12月14日 星期六

[conference] .NET Conf 2024 - .NET x Keycloak:從 0 到 1 建構身份驗證與授權解決方案

分享心得
很高興再次有機會可以在 .NET Conf 分享,在開發的過程中相信授權與認證是非常重要的環節,但在 AuthN & AuthZ 都有不同的規範與協議,這在開發上可能需要遵守同時也需要開發者在傳接上多留意,在 open source 有套好用的工具可以協助開發者降低這方面的 loading,名字叫做 keycloak,在這議程中就要跟大家分享在 dotnet 上要如何使用此套件,以及在開發過程中需要注意的地方,歡迎大家提出來進行討論,Happy learning 🙂

議程介紹
主題 : .NET x Keycloak:從 0 到 1 建構身份驗證與授權解決方案
.NET x Keycloak:從 0 到 1 建構身份驗證與授權解決方案
課程大綱
隨著企業應用邁向微服務化與雲原生架構,身份驗證與授權管理的重要性日益提升。透過 Keycloak 與 .NET 的整合,我們可以構建一個高效且符合企業級需求的身份驗證平台。本次演講將從設計到實現,探討開發者在身份驗證中面臨的挑戰,並分享 Keycloak 與 .NET 的整合實務及系統維運中的設計與優化策略。

主辦單位 :study4.tw
議程表 : 連結
投影片 : 連結



2024年11月28日 星期四

[NET] 如何在 NLog 進行偵錯

發生情境
NLog 是在.NET 開發者中很受歡迎的 Open Source支援 .NET Framework 和 .NET Core安裝上可以很簡單的透過 Nuget 安裝下載使用,透過 NLog 定義的 Configure 定義專案自行紀錄/輸出的 Log Level 格式
,近同事反應在開發新專案使用上遇到離奇的事情,在使用 NLog 寫錯誤訊息時沒有辦法正常寫入到檔案中,NLog 在遇到問題時預設是不會 throw exception 的需要打開 NLog config 的 root element 一些設定
,以下簡單紀錄幫忙偵錯 NLog 的過程及該如何處理

偵錯方法 : 開啟 throwExpections = true
NLog 在遇到問題時預設是不會 throw exception,偵錯時可以開啟 throwExceptions = "true" 的設定,讓我們在除錯過程中知道 NLog 的錯誤訊息可以透過以下兩種方式設定
1. NLog Config
   在 NLog config 的根 element 定義 throwExceptions = true 
2. 在程式中設定
        static void Main()
        {
            LogManager.ThrowExceptions = true;

            Logger logger = LogManager.GetCurrentClassLogger();
            logger.Info("Start");
            logger.Info("This is a book");
        }

偵錯方法 : 開啟 NLog Internal Logging 設定
NLog 有自己的 logging 機制可以提供偵錯及除錯使用一般我們常用的都是 NLog.Logger 類別來記錄訊息,在需要使用內部 Logging 機制時可以用 InternalLogger 類別,使用上與 Logger 有點相似需要定義 LoggerLevel, Logger FileName 等資訊,在偵錯時可以設定以下兩個 attribute 設定紀錄 internalLogger 的錯誤訊息 ( 亦可在 NLog 檔案設定 )
1. internalLogFile : 設定 internalLogging 時檔案寫入的位置
2. internalLogLevel : 設定需要寫入的 Log Rule level
        static void Main()
        {
            InternalLogger.LogFile = "c:\\Logs\\log.txt";            
            InternalLogger.LogLevel = LogLevel.Error;
        }
 

後記
透過以上設定就可以看到 NLog 內部的錯誤訊息,可以更明確的知道程式爆炸的地方
舉例以一開始幫同事 Debug 的案例如下圖,發現他的NLog file copy 別專案的config內容,但未 copy 到 NLog_ELK的config內容導致 LogManager 讀取失敗發生 FileNotFount exception宣告結案 !!!




參考
Logging Troubleshooting
NLog
NLog Tutorial
NLog internalLogging

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

Design by Anders Noren | Blogger Theme by NewBloggerThemes.com