Skip to content

Commit 2d1eaff

Browse files
authored
非同期設計ガイドライン: FIFOキューのDLQの扱いに付いて更新 (#256)
1 parent 9fe9316 commit 2d1eaff

File tree

1 file changed

+29
-15
lines changed

1 file changed

+29
-15
lines changed

documents/forAsync/async_guidelines.md

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,15 @@ graph LR
202202
FlowCheck2 -- No --> FinalChain
203203
204204
FinalChain>非同期の連鎖を検討]
205+
206+
%% Style Definitions
207+
style FinalChain fill:#fff0f0,stroke:#990000,stroke-width:2px,color:#000000
208+
style RetryAll fill:#e6ffed,stroke:#006600,stroke-width:2px,color:#000000
209+
    style ProgThread fill:#e6ffed,stroke:#006600,stroke-width:2px,color:#000000
210+
    style SplitTask fill:#e6ffed,stroke:#006600,stroke-width:2px,color:#000000
211+
    style Avoid1 fill:#e6ffed,stroke:#006600,stroke-width:2px,color:#000000
212+
    style AdoptPolling fill:#e6ffed,stroke:#006600,stroke-width:2px,color:#000000
213+
    style Avoid2 fill:#e6ffed,stroke:#006600,stroke-width:2px,color:#000000
205214
```
206215

207216
# バッチから非同期呼び出し
@@ -239,6 +248,10 @@ flowchart LR
239248
Q1 -- Yes --> Q2{2. インフラ管理・運用を<br>クラウドに任せたいか?}
240249
Q2 -- Yes --> ManagedRuntime>マネージドランタイム]
241250
Q2 -- No<br>特定のバージョン指定など --> SelfHosted>セルフホスト]
251+
252+
style FullyManaged fill:#e6ffed,stroke:#006600,stroke-width:2px,color:#000000
253+
style ManagedRuntime fill:#fff0f0,stroke:#990000,stroke-width:2px,color:#000000
254+
style SelfHosted fill:#fff0f0,stroke:#990000,stroke-width:2px,color:#000000
242255
```
243256

244257
# プロトコル
@@ -287,7 +300,7 @@ RedisにはPUBLISH/SUBSCRIBE(揮発性)とは別に、Streamsという永続
287300

288301
:::
289302

290-
# 順序制御
303+
# 順序保障
291304

292305
多くの標準的なキュー(AWS SQS の標準キューなど)は、スループットを最大化するためにメッセージの処理順序を「ベストエフォート」としており、厳密な順序を保証していない。しかし、非同期処理においてメッセージ処理の順序保証が必要となった場合は設計方式を検討する必要がある。
293306

@@ -309,20 +322,19 @@ RedisにはPUBLISH/SUBSCRIBE(揮発性)とは別に、Streamsという永続
309322
- 「厳密な順序保証が必要な場合」は(1)を採用する
310323
- SQS FIFOを採用する場合、MessageGroupId の設計がスループットの鍵であることを認識し、順序保証が必要な最小単位でグループ化すること
311324
- (2)は「FIFOキューが利用不可能なレガシー環境かつアプリケーション処理上で冪等性が担保できない場合」でなければ非推奨とする
325+
- 復旧可能性の「ある」エラーへの対応は [リトライ](#リトライ) 章の通りコンシューマー側で対応する
312326

313-
厳密な順序制御が必要な場合においても、復旧可能性の「ある」エラーへの対応は [リトライ](#リトライ) 章の通りコンシューマー側のリトライで対応する。
314-
315-
一方、復旧可能性の「ない」エラーへの対応について、**SQS FIFOを採用した場合はDLQとの併用は推奨しない。** FIFOとDLQを併用すると、DLQに入ったメッセージと同一メッセージグループの後続のメッセージが処理されなくなる(DLQに送られたメッセージが処理完了するまでブロックされる)ためである。
327+
復旧可能性の「ない」エラーへの対応について、**SQS FIFOで厳密な順序保証が必要な場合はDLQを使用してはならない**。 FIFOキューでDLQを利用すると、エラーメッセージがDLQに移動した時点で、後続のメッセージのロックが解除され処理が開始される。つまり、エラーとなった処理がスキップされた状態で後続が動くため、業務上の厳密な順序性が崩れることになる。
316328

317329
復旧可能性の「ない」エラーへの対応については、以下の2つの戦略が考えられる。
318330

319-
| 設計案 | (1)エラーが発生したら即時停止 \+ 手動介入 | (2)エラーが発生したメッセージをスキップ |
320-
| :------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
321-
| 概要 | 永続的エラーと判断したら即時アラートして、運用にてリカバリ対応を行う | エラーが発生したメッセージは諦める(別途リカバリする)が、後続の正常なメッセージの処理は止めない |
322-
| 処理方式 |コンシューマー側は永続的なエラーと判断した時点でCloudWatch等のサービスで即時にエラー発砲する<br> ・運用側はアラート通知を受けて適切な処理を行い、後続の処理を復旧させる(メッセージはDLQに移動させず、削除(Ack)もしないので運用でのリカバリが終わるまでコンシューマー側で異常終了が継続することになる) | ・コンシューマー側は永続的なエラーと判断したメッセージの内容をデータベースやログなどに保存して、キューに正常終了(Ack)を応答する<br>・後続メッセージの処理が再開されるが、エラーとして記録された内容を解析して運用やバッチ処理などによって適切にリカバリを行う |
323-
| 順序の厳密性 | あり | なし |
324-
| 可用性・スループット | ❌️低い | ✅️高い |
325-
| 運用コスト | ❌️非常に高い | ✅️比較して低い |
331+
| 設計案 | (1)エラーが発生したら即時停止 \+ 手動介入 | (2)エラーが発生したメッセージをスキップ |
332+
| :------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
333+
| 概要 | 永続的エラーと判断したら即時アラートして、運用にてリカバリ対応を行う | エラーが発生したメッセージは諦める(別途リカバリする)が、後続の正常なメッセージの処理は止めない |
334+
| 処理方式 |コンシューマー側は永続的なエラーと判断した時点でエラー通知する<br> ・運用側はアラート通知を受けて復旧させる(メッセージはDLQに移動させず、削除もしないのでリカバリが終わるまでコンシューマー側で異常終了が継続することになる) | ・コンシューマー側は永続的なエラーと判断したメッセージの内容をデータベースやログなどに保存して、DLQに送信する<br>・後続メッセージの処理が再開される。DLQは適切にリカバリする |
335+
| 順序の厳密性 | あり | なし |
336+
| 可用性・スループット | ❌️低い | ✅️高い |
337+
| 運用コスト | ❌️非常に高い | ✅️比較して低い |
326338

327339
推奨は以下の通り。
328340

@@ -331,7 +343,7 @@ RedisにはPUBLISH/SUBSCRIBE(揮発性)とは別に、Streamsという永続
331343
- この場合、何か1つでもエラーになるとそれ以降の処理がブロッキングされるため、早期のリカバリが求められる。運用負荷は非常に高くなるためできる限り緩和できないか考える
332344

333345
::: info 参考
334-
[Using dead-letter queues in Amazon SQS](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-dead-letter-queues.html)
346+
[Amazon SQS でのデッドレターキューの使用](https://docs.aws.amazon.com/ja_jp/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-dead-letter-queues.html) に、「メッセージまたは操作の正確な順序を維持する必要がある場合は、FIFOキューでデッドレターキューを使用しないでください」とある。
335347
:::
336348

337349
# 重複排除と冪等性
@@ -411,7 +423,7 @@ sequenceDiagram
411423
App->>Queue: Send Message
412424
Queue-->>App: OK (Ack)
413425
414-
rect rgb(255, 230, 230)
426+
rect rgb(255, 230, 230, 0.5)
415427
App->>DB: COMMIT
416428
DB--xApp: ❌ エラー / タイムアウト
417429
end
@@ -443,8 +455,10 @@ sequenceDiagram
443455
App->>DB: COMMIT
444456
DB-->>App: OK
445457
446-
App->>Queue: Send Message
447-
Queue--xApp: ❌ ネットワークエラー / 障害
458+
rect rgb(255, 230, 230, 0.5)
459+
App->>Queue: Send Message
460+
Queue--xApp: ❌ ネットワークエラー / 障害
461+
end
448462
449463
Note over Worker: ❌️後続処理が起動しない
450464
```

0 commit comments

Comments
 (0)