Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
タイムアウトにご用心 / Timeout might break application state
Search
Fumiaki MATSUSHIMA
October 10, 2021
6
2.4k
タイムアウトにご用心 / Timeout might break application state
https://kaigionrails.doorkeeper.jp/events/127339
Kaigi on Rails _2021_ new LT 発表資料
Fumiaki MATSUSHIMA
October 10, 2021
Tweet
Share
More Decks by Fumiaki MATSUSHIMA
See All by Fumiaki MATSUSHIMA
Learning from performance improvements on GraphQL Ruby
mtsmfm
1
960
Ruby で作る Ruby (物理)
mtsmfm
0
170
GraphQL Ruby benchmark
mtsmfm
1
700
Build REST API with GraphQL Ruby
mtsmfm
0
260
GraphQL Ruby をちょっとだけ速くした / Make graphql-ruby faster a bit
mtsmfm
1
660
Gaming PC on GCP
mtsmfm
0
650
How to introduce GraphQL to an existing React-Redux application
mtsmfm
1
200
Canary release in StudySapuri
mtsmfm
0
2.9k
Analyze Rails CI
mtsmfm
2
760
Featured
See All Featured
Intergalactic Javascript Robots from Outer Space
tanoku
268
27k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
327
21k
A designer walks into a library…
pauljervisheath
201
24k
Large-scale JavaScript Application Architecture
addyosmani
509
110k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
44
2k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
4
110
Fontdeck: Realign not Redesign
paulrobertlloyd
81
5.2k
A Tale of Four Properties
chriscoyier
155
22k
Robots, Beer and Maslow
schacon
PRO
157
8.2k
How GitHub Uses GitHub to Build GitHub
holman
473
290k
Designing for Performance
lara
604
68k
Rails Girls Zürich Keynote
gr2m
93
13k
Transcript
@mtsmfm タイムアウトにご用心
松島 史秋 GitHub, Twitter @mtsmfm
https://ninirb.github.io
https://www.meetup.com/ja-JP/GraphQL-Tokyo/
伝えたいこと タイムアウトしたプロセスを再利 用してはいけない
どんな問題が起きるか - タイムアウト後、アプリケーションの状態が崩壊 する可能性がある
User.where(name: "foo").not_deleted /users_count /users?name=foo User.not_deleted.count
User.where(name: "foo").not_deleted /users_count 1. リクエストがくる /users?name=foo User.not_deleted.count
User.where(name: "foo").not_deleted /users_count User.not_deleted.count 1. リクエストがくる 2. not_deleted scope を組み立
て中にタイムアウトになる /users?name=foo
User.where(name: "foo").not_deleted /users_count 1. リクエストがくる 2. not_deleted scope を組み立 て中にタイムアウトになる
/users?name=foo 3. 別のリクエストがくる User.not_deleted.count
User.where(name: "foo").not_deleted /users_count 1. リクエストがくる 2. not_deleted scope を組み立 て中にタイムアウトになる
4. タイムアウトしたときにスタックされ ていた where が適用される /users?name=foo 3. 別のリクエストがくる User.where(name: "foo").not_deleted.count User.not_deleted.count
どんな問題が起きるか - タイムアウト後、アプリケーションの状態が崩壊 する可能性がある - タイムアウトのタイミング次第では、その瞬間の状態が 保持されてしまうケースがある - 例えば、User.count と書いてあるのに、タイムアウト以
後、そのプロセスは User.where(name: "foo").count 相当の処理をする
なぜそうなるのか - ensure 中に Thread#raise されるとそこで ensure が全部実行されることなく終わってしま うから
class Stack def stack @stack ||= [] end def with(name)
stack.push(name) yield stack ensure stack.pop end end stack = Stack.new stack.with('foo') do p stack.stack #=> ["foo"] stack.with('bar') do p stack.stack #=> ["foo", "bar"] end p stack.stack #=> ["foo"] end
ここでタイムア ウトしても セーフ class Stack def stack @stack ||= []
end def with(name) stack.push(name) yield stack ensure stack.pop end end
ここでタイムア ウトすると pop されない class Stack def stack @stack ||=
[] end def with(name) stack.push(name) yield stack ensure stack.pop end end
Rails のバグ? - 違う - あらゆるタイミングで Thread#raise されること を考慮するのは厳しいので諦めている -
https://github.com/rails/rails/pull/17607#issuecomme nt-70538060 - Scope 以外にも ensure で状態をリセットすると ころはタイムアウトで壊れる可能性有
どんなときに踏みやすいか - 自分で Timeout.timeout を書くことはそんなに ない気がする - 注意すべきは gem、特に Web
サーバとか Rack middleware とか
rack-timeout の罠 - rails new して書かれている Puma にはタイム アウト機構はなく、rack-timeout が事実上デファ
クト - Heroku のチュートリアルでも紹介されていたり - デフォルト設定だとまさにやばいケースに該当 する
rack-timeout の罠 - term_on_timeout: true にすれば、タイムアウト したら TERM で殺してくれる -
これはデフォルトではない - Puma を Clustered mode で動かしていない場合、true にするとサーバが完全に死ぬ
https://github.com/sharpstone/rack-timeout/issues/169
デフォルトやばいのでは? - 警告だけでも提案したが通らなかった - rack-timeout gem が歴史的に TERM するわけではな い
- 危ないという説明も既にある (doc/risks.md) - Puma のデフォルトは Clustered mode じゃない
伝えたいこと - タイムアウトしたプロセスを再利用してはいけな い - Middleware っぽいところでやってると特に危ない - rack-timeout は
term_on_timeout を必ず true に - 具体的な再現コードなどは https://zenn.dev/mtsmfm/articles/d55d739104e87c
Credits Background pattern from Toptal Subtle Patterns https://www.toptal.com/designers/subtlepatterns/