@@ -9,7 +9,7 @@ import StatusBadge from "@site/src/components/StatusBadge";
99import ImageLightbox from " @site/src/components/ImageLightbox" ;
1010
1111<SeverityBadge level = " medium" />
12- <StatusBadge status = " investigating " />
12+ <StatusBadge status = " resolved " />
1313
1414---
1515
@@ -18,7 +18,7 @@ import ImageLightbox from "@site/src/components/ImageLightbox";
1818- ** 發生時間:** 2025/12/13 03:33 (UTC+8) 左右
1919- ** 觸發條件:** 維護過程中
2020- ** 問題描述:** TREM Lite 地震報告重複推送的問題
21- - ** 根本原因:** API 資料雜湊值不一致,導致地震報告重複推送
21+ - ** 根本原因:** 快取鍵衝突
2222
2323## 時間軸
2424
@@ -38,180 +38,91 @@ import ImageLightbox from "@site/src/components/ImageLightbox";
3838
3939### 問題根源
4040
41- 兩個不同來源的 API 伺服器(` api-1.exptech.dev ` 和 ` api-2.exptech.dev ` )對於相同的地震事件,產生的 MD5 雜湊值不一致,導致客戶端判斷為新的地震報告,進而產生重複推送的問題。
42-
43- ** 關鍵差異:**
44-
45- 從上述 API 回應資料可以觀察到,相同的地震事件(相同的 ` id ` )在兩個 API 伺服器上:
46-
47- - ` trem ` 時間戳不同(例如:` 1765484671592 ` vs ` 1765484672700 ` )
48- - 因此計算出的 ` md5 ` 雜湊值也不同(例如:` B00F1BCF25C80D8A4EAA865D1D8EEC33 ` vs ` DA5510C9B54576B883E04F4DD7178E9C ` )
49-
50- ` api-1.exptech.dev `
51-
52- ``` json
53- [
54- {
55- "id" : " 114149-2025-1212-042428" ,
56- "lat" : 23.19 ,
57- "lon" : 120.47 ,
58- "depth" : 8.9 ,
59- "loc" : " 臺南市政府東北方 36.4 公里 (位於臺南市楠西區)" ,
60- "mag" : 4 ,
61- "time" : 1765484668000 ,
62- "int" : 4 ,
63- "trem" : 1765484671592 ,
64- "md5" : " B00F1BCF25C80D8A4EAA865D1D8EEC33"
65- },
66- {
67- "id" : " 114148-2025-1211-231940" ,
68- "lat" : 23.18 ,
69- "lon" : 120.66 ,
70- "depth" : 8.2 ,
71- "loc" : " 高雄市政府北北東方 71.5 公里 (位於高雄市甲仙區)" ,
72- "mag" : 4.7 ,
73- "time" : 1765466380000 ,
74- "int" : 4 ,
75- "trem" : 1765466391158 ,
76- "md5" : " F2B6AE32A6E4D8A459ECEDFDE19180E6"
77- },
78- {
79- "id" : " 114000-2025-1211-225941" ,
80- "lat" : 23.17 ,
81- "lon" : 120.67 ,
82- "depth" : 8 ,
83- "loc" : " 高雄市政府北北東方 71.2 公里 (位於高雄市甲仙區)" ,
84- "mag" : 3.5 ,
85- "time" : 1765465181000 ,
86- "int" : 2 ,
87- "trem" : 1765465199063 ,
88- "md5" : " 685F5C6EC26FBF1F9159906486A5C127"
89- },
90- {
91- "id" : " 114147-2025-1211-224902" ,
92- "lat" : 23.18 ,
93- "lon" : 120.66 ,
94- "depth" : 8 ,
95- "loc" : " 高雄市政府北北東方 71.1 公里 (位於高雄市甲仙區)" ,
96- "mag" : 4.7 ,
97- "time" : 1765464542000 ,
98- "int" : 4 ,
99- "trem" : 1765464552546 ,
100- "md5" : " F34095B26D0895AA0995F3028B76DE02"
101- },
102- {
103- "id" : " 114000-2025-1211-124902" ,
104- "lat" : 24.62 ,
105- "lon" : 121.75 ,
106- "depth" : 45.4 ,
107- "loc" : " 宜蘭縣政府南方 12.3 公里 (位於宜蘭縣冬山鄉)" ,
108- "mag" : 4 ,
109- "time" : 1765428542000 ,
110- "int" : 1 ,
111- "trem" : 1765428550547 ,
112- "md5" : " F1CC648A41D465CA2F60264ACCABC7A3"
113- }
114- ]
41+ 快取鍵設定不當,導致不同參數的請求共用相同的快取結果,造成 API 回應不符合預期。
42+
43+ ### 問題說明
44+
45+ ** 問題主因:**
46+
47+ 當系統從不同的 upstream 取得資料時,會將不一致的資料寫入 cache。
48+
49+ 故障時 Nginx 設定如下:
50+
51+ ``` bash
52+ location ~ ^/api/(v1| v2)/eq/report {
53+ set $cache_key " $uri |$arg_limit |$arg_page |$arg_minIntensity |$arg_maxIntensity |$arg_minMagnitude |$arg_maxMagnitude |$arg_minDepth |$arg_maxDepth " ;
54+ proxy_pass http://report;
55+ proxy_cache_key $cache_key ;
56+ include /etc/nginx/conf.d/cache_1s.inc;
57+ }
11558```
11659
117- ` api-2.exptech.dev `
118-
119- ``` json
120- [
121- {
122- "id" : " 114149-2025-1212-042428" ,
123- "lat" : 23.19 ,
124- "lon" : 120.47 ,
125- "depth" : 8.9 ,
126- "loc" : " 臺南市政府東北方 36.4 公里 (位於臺南市楠西區)" ,
127- "mag" : 4 ,
128- "time" : 1765484668000 ,
129- "int" : 4 ,
130- "trem" : 1765484672700 ,
131- "md5" : " DA5510C9B54576B883E04F4DD7178E9C"
132- },
133- {
134- "id" : " 114148-2025-1211-231940" ,
135- "lat" : 23.18 ,
136- "lon" : 120.66 ,
137- "depth" : 8.2 ,
138- "loc" : " 高雄市政府北北東方 71.5 公里 (位於高雄市甲仙區)" ,
139- "mag" : 4.7 ,
140- "time" : 1765466380000 ,
141- "int" : 4 ,
142- "trem" : 1765466391208 ,
143- "md5" : " D207D655C1A9E720E7BBC33B1F4CCD33"
144- },
145- {
146- "id" : " 114000-2025-1211-225941" ,
147- "lat" : 23.17 ,
148- "lon" : 120.67 ,
149- "depth" : 8 ,
150- "loc" : " 高雄市政府北北東方 71.2 公里 (位於高雄市甲仙區)" ,
151- "mag" : 3.5 ,
152- "time" : 1765465181000 ,
153- "int" : 2 ,
154- "trem" : 1765465199151 ,
155- "md5" : " 25A440BC96AC17E401AEFFFED42CD06C"
156- },
157- {
158- "id" : " 114147-2025-1211-224902" ,
159- "lat" : 23.18 ,
160- "lon" : 120.66 ,
161- "depth" : 8 ,
162- "loc" : " 高雄市政府北北東方 71.1 公里 (位於高雄市甲仙區)" ,
163- "mag" : 4.7 ,
164- "time" : 1765464542000 ,
165- "int" : 4 ,
166- "trem" : 1765464552550 ,
167- "md5" : " 24C4744A01521C9540CE2D5FD209AF07"
168- },
169- {
170- "id" : " 114000-2025-1211-124902" ,
171- "lat" : 24.62 ,
172- "lon" : 121.75 ,
173- "depth" : 45.4 ,
174- "loc" : " 宜蘭縣政府南方 12.3 公里 (位於宜蘭縣冬山鄉)" ,
175- "mag" : 4 ,
176- "time" : 1765428542000 ,
177- "int" : 1 ,
178- "trem" : 0 ,
179- "md5" : " 6C759AE5E57359B06662C6B0C31B68B1"
180- }
181- ]
60+ ` cache_1s.inc `
61+
62+ ``` bash
63+ proxy_cache my_cache;
64+ proxy_cache_key $url ;
65+ proxy_cache_valid 200 1s;
66+ proxy_cache_lock on;
67+ proxy_cache_lock_timeout 1s;
68+ proxy_cache_use_stale updating error timeout http_500 http_502 http_503 http_504;
69+ proxy_cache_background_update on;
18270```
18371
184- ### 問題說明
72+ ** 問題點: **
18573
186- ** 問題主因 :**
74+ 1 . ** 快取鍵設定衝突 :**
18775
188- 可以從下方圖片發現,兩邊 (` TNN ` 、` TPE ` ) 的 ** ID** 不一致。
76+ - 在 ` location ` 區塊中設定了 ` proxy_cache_key $cache_key ` (使用自訂的快取鍵)
77+ - 但在 ` cache_1s.inc ` 中又設定了 ` proxy_cache_key $url ` (使用 URL 作為快取鍵)
78+ - 兩個 ` proxy_cache_key ` 設定衝突,導致快取鍵不一致
18979
190- < ImageLightbox src = " /img/RCA/2025-12-13_1/image.png " alt = " 問題說明圖 " />
80+ 2 . ** 回應不符預期: **
19181
192- 伺服器上的 ** MD5 雜湊值** 計算方式如下:
82+ - ` cache_1s.inc ` 中的 ` proxy_cache_key $url; ` 會覆蓋 ` location ` 區塊中的 ` proxy_cache_key $cache_key; `
83+ - 當請求有查詢參數和沒有查詢參數時,` $url ` 可能產生相同的快取鍵
84+ - 例如:` /api/v1/eq/report ` 和 ` /api/v1/eq/report?limit=10 ` 可能使用相同的快取鍵
85+ - 導致不同參數的請求共用相同的快取結果,返回不符合預期的資料
19386
194- ``` js
195- const ans = {
196- ... earthquakeData, // CWA 地震報告
197- trem, // TREM EQ ID
198- md5: calculateMD5Hash (
199- JSON .stringify ({
200- ... earthquakeData,
201- trem,
202- })
203- ).toLocaleUpperCase (), // MD5 雜湊值
204- };
87+ 3 . ** 影響:**
88+ - 客戶端收到不一致的地震報告資料
89+ - 相同的地震事件被重複推送
90+
91+ ## 解決方案
92+
93+ ### 修改後的設定
94+
95+ 移除 ` cache_1s.inc ` 中的 ` proxy_cache_key $url; ` 設定,統一使用 ` location ` 區塊中定義的 ` $cache_key ` :
96+
97+ ``` bash
98+ location ~ ^/api/(v1| v2)/eq/report {
99+ set $cache_key " $uri |$arg_limit |$arg_page |$arg_minIntensity |$arg_maxIntensity |$arg_minMagnitude |$arg_maxMagnitude |$arg_minDepth |$arg_maxDepth " ;
100+ proxy_pass http://report;
101+ proxy_cache_key $cache_key ;
102+ include /etc/nginx/conf.d/cache_1s.inc;
103+ }
205104```
206105
207- ** TREM EQ ID ** 的取得方式如下:
106+ ` cache_1s.inc ` (修改後)
208107
209- ``` sql
210- SELECT ID FROM trem_report WHERE Cwa_id = ? LIMIT 1 ;
108+ ``` bash
109+ proxy_cache my_cache;
110+ # 移除 proxy_cache_key $url; 避免與 location 區塊中的設定衝突
111+ proxy_cache_valid 200 1s;
112+ proxy_cache_lock on;
113+ proxy_cache_lock_timeout 1s;
114+ proxy_cache_use_stale updating error timeout http_500 http_502 http_503 http_504;
115+ proxy_cache_background_update on;
211116```
212117
213- 綜上所述, ** MD5 雜湊值 ** 的不一致最終導致問題的發生。
118+ ### 改進說明
214119
215- ## 解決方案
120+ 1 . ** 統一快取鍵設定:** 移除 ` cache_1s.inc ` 中的 ` proxy_cache_key $url; ` ,避免與 ` location ` 區塊中的自訂快取鍵衝突
121+
122+ 2 . ** 確保快取鍵唯一性:** 使用包含所有查詢參數的自訂快取鍵,確保有參數和無參數的請求使用不同的快取鍵
123+
124+ 3 . ** 確保回應正確性:** 透過正確的快取鍵設定,確保不同參數的請求使用不同的快取,返回符合預期的資料
216125
217126## 後續觀察
127+
128+ 經觀察後,問題已得到緩解。
0 commit comments