2026/09/14

JEP 467 Markdown Documentation Comments

自 JDK 23 開始,javadoc 支援在每一行 javadoc 中,以 /// 開頭的方式,標記為markdown 格式的 javadoc,這種方式取代舊的 /** **/ ,並支援 markdown 語法。

markdown 是簡化的 html,以往在 javadoc,需要用大量的 html tag,標記為

,

    , ,現在支援 markdown 語法的 標題、列表、代碼塊、連結、粗體/斜體,讓 javadoc 的內容更精簡。

    新舊兩種註解寫法是同時支援的。新的 markdown,除了比較簡潔以外,解決了傳統的 javadoc 使用 html,太難寫,需要寫很多 html tag 的問題,在查看 code 裡面的註解時,markdown 的可讀性明顯比 html 高。

    支援的 markdown 語法

    • 粗體,斜體文字

    • 段落與換行

    • 有序及無序的列表 list

    • 程式碼

    • 標題

    • 連結

    • 表格

    markdown javadoc 範例

        /// 這是使用 Markdown 格式的註釋。
        ///
        /// # 範例功能
        /// * 使用 **Highlight** 語法。
        ///
        /// # 程式區塊:
        /// ```java
        /// test("param");
        /// ```
        ///
        /// # 列表
        /// 1. 項目1
        /// 2. 項目2
        /// 3. 項目3
        ///
        /// # 連結 [google]("https://www.google.com")
        /// * 連結
        /// - 模組 [java.base/]
        /// - 套件 [java.util]
        /// - 類別 [String]
        /// - 欄位 [String#CASE_INSENSITIVE_ORDER]
        /// - 方法 [String#chars()]
        /// - 同一類別其他方法: [equals][#equals(Object)]
        ///
        /// # 表格
        ///
        /// | Latin | Greek |
        /// |-------|-------|
        /// | a     | alpha |
        /// | b     | beta  |
        /// | c     | gamma |
        ///
        /// @param param1 參數
        /// @return 回傳值

2026/09/07

SSOT Single Source of Truth

單一真理來源、唯一事實來源。資訊系統架構中的一個核心概念。其核心目標在於確保組織內的每個人、每個系統,在需要特定數據時,都參考同一個來源,從而避免數據不一致導致的決策錯誤。

這樣做可以確保:

  • 所有資訊的一致性和準確性

  • 減少重複數據和資訊衝突

  • 方便查找與更新

  • 簡化備份、遷移和共享流程

  • 促進團隊協作與溝通

SSOT 並不是指將「所有數據」都存在同一個資料庫中,而是指對於某個特定的數據點(例如:客戶地址、產品價格、庫存數量),在整個系統中只有一個權威的來源(Master Copy)。

在 IT 領域的應用意義

1. 確保數據一致性 (Data Consistency)

在大型 IT 架構中,多個系統(如 ERP、CRM、電商網站)往往會共用相同的數據。若沒有 SSOT,當客戶修改地址時,若只更新了 CRM 而沒更新 ERP,就會導致出貨錯誤。實施 SSOT 後,所有系統都會向「客戶主資料庫」看齊。

2. 降低數據冗餘與維護成本

重複的數據存儲不僅浪費空間,更增加了維護難度。透過 SSOT,開發人員不需要編寫複雜的邏輯來比對多個資料庫之間的差異,簡化了系統整合的複雜度。

3. 提升決策與分析的準確性

對於商業智慧(BI)與大數據分析而言,SSOT 是基礎。如果財務部門和銷售部門提供的營收報表數據對不起來(可能因為計算邏輯或數據來源不同),管理層將難以做出正確判斷。SSOT 確保了「數據來源一致」。

4. 加速開發與自動化

在 DevOps 或現代軟體開發中,SSOT 的概念也被應用於:

  • Infrastructure as Code (IaC): 例如 Git 就是基礎設施配置的 SSOT。

  • API 驅動架構: 透過統一的 API 接口存取權威數據,避免直接對原始資料庫進行多點讀寫。

實施 SSOT 的挑戰

雖然 SSOT 理想上很完美,但在實際運作中常遇到以下困難:

  • 跨部門溝通: 定義「誰才是權威來源」往往涉及組織權責分配。

  • 系統效能: 若所有系統都即時請求同一個數據源,可能造成效能瓶頸(通常透過緩存同步機制解決)。

  • 舊系統轉型: 整合缺乏標準接口的舊有系統(Legacy Systems)需要極大成本。

2026/08/31

tc (traffic control) in linux

tc(traffic control)是 Linux 裡用來做網路流量控制(QoS, Quality of Service)的工具。可針對網路卡,進行限速(rate limiting)、排程(traffic scheduling)、優先權控制(priority)、模擬網路狀況(延遲、丟包、抖動)、封包分類與整形(shaping)的網路封包控制。主要用途是用來模擬網際網路的封包狀況。

流量控制方式

  • shaping

    當流量被shaping限制後,它的傳輸速率就被控制在某個值以下。限制值可以遠小於有效頻寬,這樣可以平滑突發的資料流量,使網路更爲穩定。shaping(限制)只適用於向外的流量。shaping 只能用在 egress 對外的資料輸出。

  • scheduling

    通過調度封包的傳輸,可以在頻寬範圍內,按照優先等級分配頻寬。scheduling 只能用在 egress 對外的資料輸出。

  • policing

    shaping用於處理 egress 對外的流量,而 policing 用於處理 ingress 接收到的流量。

  • dropping

    如果流量超過某個設定的頻寬,就丟棄資料,可用在 egress 及 ingress。

主要元件

  1. qdisc (Queueing Discipline)

    佇列規則,決定封包排隊的送出規則。當kernel需要通過某個網絡port發送資料,它都需要按照爲這個port配置的qdisc排隊規則,把資料加入queue。然後kernel會儘可能地從qdisc裏面取出資料,交給網絡適配器驅動模塊。最簡單的qdisc是 pfifo,它不對進入的封包做任何的處理,採用先入先出的方式通過隊列。不過,它會暫存網絡接口短時間內無法處理的封包。

    常見的 qdisc:

    • pfifo_fast(預設)

    • htb(常用做限速)

    • fq_codel(改善 bufferbloat)

    • netem(模擬網路)

  2. class

    在 qdisc 底下建立不同流量分類,用來分配不同頻寬。不同的類別中可以包含更深入的QDisc(排隊規則),通過這些細分的QDisc還可以爲進入的隊列的封包排隊。通過設置各種類別封包的離隊次序,QDisc可以設定網路數據流量的優先等級。

  3. filter, policy 過濾器

    用來把封包分類到不同 class,決定它們按照何種QDisc進入隊列。分類的方法可以有多種,使用fileter(過濾器)就是其中之一。使用filter(過濾器)分類時,kernel會呼叫附屬於這個 class 的所有過濾器,直到回傳一個判決。如果沒有判決返回,就作進一步的處理,而處理方式和QDISC有關。filter(過濾器)是放在QDisc內部。

指令

tc [OPTIONS] OBJECT COMMAND

常見 OBJECT:

  • qdisc

  • class

  • filter

指令內可使用的資料單位

  • 頻寬或流量單位

    kbps
    mbps
    kbit
    mbit
    bps
  • 資料單位

    kb
    mb
    mbit
    kbit
    b
  • 時間

    s/sec/secs
    ms/msec/msecs
    us/usec/usecs

options

-s, -stats, -statistics: output more statistics about packet usage.
-d, -details: output more detailed information about rates and cell sizes.
-r, -raw: output raw hex values for handles.
-p, -pretty: decode filter offset and mask values to equivalent filter commands based on TCP/IP.
-iec: print rates in IEC units (ie. 1K = 1024).

Examples

tc 通常是控制 egress 的流量

查看設定

tc -s qdisc show dev eth0
tc class show dev eth0
tc filter show dev eth0
# tc -s qdisc show dev enp1s0
qdisc mq 0: root
 Sent 220264 bytes 431 pkt (dropped 0, overlimits 0 requeues 2)
 backlog 0b 0p requeues 2
qdisc fq_codel 0: parent :4 limit 10240p flows 1024 quantum 1514 target 5ms interval 100ms memory_limit 32Mb ecn drop_batch 64
 Sent 20103 bytes 107 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
  maxpacket 0 drop_overlimit 0 new_flow_count 0 ecn_mark 0
  new_flows_len 0 old_flows_len 0
qdisc fq_codel 0: parent :3 limit 10240p flows 1024 quantum 1514 target 5ms interval 100ms memory_limit 32Mb ecn drop_batch 64
 Sent 43974 bytes 148 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
  maxpacket 0 drop_overlimit 0 new_flow_count 0 ecn_mark 0
  new_flows_len 0 old_flows_len 0
qdisc fq_codel 0: parent :2 limit 10240p flows 1024 quantum 1514 target 5ms interval 100ms memory_limit 32Mb ecn drop_batch 64
 Sent 146267 bytes 124 pkt (dropped 0, overlimits 0 requeues 2)
 backlog 0b 0p requeues 2
  maxpacket 8925 drop_overlimit 0 new_flow_count 1 ecn_mark 0
  new_flows_len 0 old_flows_len 0
qdisc fq_codel 0: parent :1 limit 10240p flows 1024 quantum 1514 target 5ms interval 100ms memory_limit 32Mb ecn drop_batch 64
 Sent 9920 bytes 52 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
  maxpacket 0 drop_overlimit 0 new_flow_count 0 ecn_mark 0
  new_flows_len 0 old_flows_len 0
# tc -d qdisc show dev enp1s0
qdisc mq 0: root
qdisc fq_codel 0: parent :4 limit 10240p flows 1024 quantum 1514 target 5ms interval 100ms memory_limit 32Mb ecn drop_batch 64
qdisc fq_codel 0: parent :3 limit 10240p flows 1024 quantum 1514 target 5ms interval 100ms memory_limit 32Mb ecn drop_batch 64
qdisc fq_codel 0: parent :2 limit 10240p flows 1024 quantum 1514 target 5ms interval 100ms memory_limit 32Mb ecn drop_batch 64
qdisc fq_codel 0: parent :1 limit 10240p flows 1024 quantum 1514 target 5ms interval 100ms memory_limit 32Mb ecn drop_batch 64
  • qdisc mq 0: root

    根節點 mq : multi-queue

    代表你的硬體網路卡有多個傳輸佇列(在這個例子中是 4 個,分別對應 parent :1:4)。通常發生在多核心 CPU 的伺服器上,系統會將網路流量分散到不同的 CPU 核心處理,以提升效能

  • fq_codel (Fair Queuing Controlled Delay)

    這是目前 Linux 系統非常推薦的排隊規則,它由兩個部分組成

    • FQ (Fair Queuing):確保每個「連線」(Flow)都能公平分配頻寬。例如,即使有人在下載大檔案,你的網頁瀏覽或視訊通話依然能順暢通過。

    • CoDel (Controlled Delay):這是一個智慧演算法,當它發現緩衝區(Buffer)塞車太久時,會主動丟棄封包或標記 ECN,強制降低延遲,解決「緩衝區膨脹」問題。

  • 以其中一個 fq_codel 為例:

    • limit 10240p: 佇列中最多可以存放 10,240 個封包。

    • flows 1024: 它最多可以同時追蹤並隔離 1024 個不同的連線。

    • target 5ms / interval 100ms: 這是 CoDel 的核心參數。它會嘗試將延遲控制在 5ms 以內;如果延遲超過這個數值持續 100ms,它就會開始干預流量。

    • ecn: 支援顯式擁塞通知。當網路塞車時,它會通知發送端減速,而不是直接丟棄封包。

  • -s 統計

    Sent 146267 bytes 124 pkt (dropped 0, overlimits 0 requeues 2)

    • Sent: 該佇列目前傳送的資料量與封包數。

    • dropped 0: 這是一個好現象。 代表目前沒有封包因為塞車而被強制丟棄。

    • requeues 2: 封包重新排隊的次數。通常發生在硬體驅動程式暫時無法處理封包時(例如網路卡發送視窗滿了),這在正常運作下是偶爾會發生的。

    • new_flow_count 1: 代表自從統計開始以來,有一個「新連線」被偵測到。fq_codel 會優先處理新連線(互動式流量),以保證反應速度。

刪除設定

清除所有設定

tc qdisc del dev eth0 root

備份/還原完整設定

# 備份
tc -dump qdisc show dev eth0 > tc-backup.txt
tc -dump class show dev eth0 >> tc-backup.txt
tc -dump filter show dev eth0 >> tc-backup.txt

# 還原前先清空
tc qdisc del dev eth0 root
tc qdisc del dev eth0 ingress
tc -batch tc-backup.txt

完整備份所有網卡

tc -dump qdisc show > tc-all.txt
tc -dump class show >> tc-all.txt
tc -dump filter show >> tc-all.txt

# 還原
tc -batch tc-all.txt

限制整個網卡頻寬

限制 eth0 最大 1Mbps

tc qdisc add dev eth0 root tbf rate 1mbit burst 32kbit latency 400ms
  • tbf = Token Bucket Filter(簡單限速)

  • rate = 頻寬

  • burst = 突發流量

  • latency = 最大延遲

使用 HTB 做分流

# 建立 root qdisc
tc qdisc add dev eth0 root handle 1: htb default 30

# 建立 class 做頻寬分配
tc class add dev eth0 parent 1: classid 1:1 htb rate 10mbit
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 5mbit
tc class add dev eth0 parent 1:1 classid 1:20 htb rate 2mbit
1: (root)
 └── 1:1 (10mbit)
      ├── 1:10 (5mbit)
      └── 1:20 (2mbit)

依 IP 分流

ex

192.168.1.100 → 5Mbps
其他 → 2Mbps
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 \
match ip dst 192.168.1.100 flowid 1:10

模擬網路延遲

增加 100ms 延遲

tc qdisc add dev eth0 root netem delay 100ms

模擬丟包

10% 封包丟失

tc qdisc add dev eth0 root netem loss 10%

延遲 + 抖動 + 丟包

tc qdisc add dev eth0 root netem delay 100ms 20ms loss 5%
  • 100ms = 基本延遲

  • 20ms = 抖動(jitter)

  • loss 5% = 丟包

控制 ingress

tc qdisc add dev eth0 handle ffff: ingress

ingress shaping ifb

tc 原生只能控制 egress(送出流量) ,要控制 ingress(進來的流量),就要「轉送」到 ifb 再做 shaping

eth0 (ingress)
   ↓ redirect
ifb0 (egress)
   ↓ tc 控制

限制下載速度(ingress 10Mbps)

# 載入 ifb 模組
modprobe ifb

# 指定數量
modprobe ifb numifbs=1

# 啟用 ifb0
ip link add ifb0 type ifb
ip link set dev ifb0 up

# 在 eth0 加 ingress qdisc
tc qdisc add dev eth0 handle ffff: ingress

# 把 ingress 流量導到 ifb0
# mirred = mirror/redirect
tc filter add dev eth0 parent ffff: protocol ip u32 \
match u32 0 0 action mirred egress redirect dev ifb0

# 在 ifb0 上做限速
tc qdisc add dev ifb0 root tbf rate 10mbit burst 32k latency 400ms

# show
tc -s qdisc show dev ifb0

clear

tc qdisc del dev eth0 ingress
tc qdisc del dev ifb0 root
ip link delete ifb0

不同 IP 不同下載速度

ex

192.168.1.100 → 5 Mbps
其他 → 2 Mbps

用 HTB

tc qdisc add dev ifb0 root handle 1: htb default 20

tc class add dev ifb0 parent 1: classid 1:1 htb rate 10mbit

tc class add dev ifb0 parent 1:1 classid 1:10 htb rate 5mbit
tc class add dev ifb0 parent 1:1 classid 1:20 htb rate 2mbit

# filter 分流
# ingress → ifb 後.  source IP 才是外部來源 IP
tc filter add dev ifb0 protocol ip parent 1: prio 1 u32 \
match ip src 192.168.1.100 flowid 1:10

note: ingress 只能有一個 qdisc

References

程式扎記: [Linux 文章收集] TC 入門 (traffic control)

TC (Traffic Control) - HackMD