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
980
Ruby で作る Ruby (物理)
mtsmfm
0
180
GraphQL Ruby benchmark
mtsmfm
1
720
Build REST API with GraphQL Ruby
mtsmfm
0
270
GraphQL Ruby をちょっとだけ速くした / Make graphql-ruby faster a bit
mtsmfm
1
670
Gaming PC on GCP
mtsmfm
0
660
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
780
Featured
See All Featured
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
28
9.1k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
41
2.1k
Adopting Sorbet at Scale
ufuk
73
9k
Building Flexible Design Systems
yeseniaperezcruz
327
38k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
504
140k
A better future with KSS
kneath
238
17k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
191
16k
Gamification - CAS2011
davidbonilla
80
5k
Code Reviewing Like a Champion
maltzj
519
39k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
32
1.8k
Thoughts on Productivity
jonyablonski
67
4.3k
Six Lessons from altMBA
skipperchong
26
3.5k
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/