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.6k
タイムアウトにご用心 / 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
1.2k
Ruby で作る Ruby (物理)
mtsmfm
1
210
GraphQL Ruby benchmark
mtsmfm
1
830
Build REST API with GraphQL Ruby
mtsmfm
0
330
GraphQL Ruby をちょっとだけ速くした / Make graphql-ruby faster a bit
mtsmfm
1
730
Gaming PC on GCP
mtsmfm
0
740
How to introduce GraphQL to an existing React-Redux application
mtsmfm
1
250
Canary release in StudySapuri
mtsmfm
0
3.1k
Analyze Rails CI
mtsmfm
2
890
Featured
See All Featured
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
45
7.5k
Large-scale JavaScript Application Architecture
addyosmani
512
110k
Stop Working from a Prison Cell
hatefulcrawdad
271
21k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
53
2.9k
Product Roadmaps are Hard
iamctodd
PRO
54
11k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
21
1.3k
The Cult of Friendly URLs
andyhume
79
6.5k
Building an army of robots
kneath
306
45k
Why You Should Never Use an ORM
jnunemaker
PRO
58
9.5k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
331
22k
Practical Orchestrator
shlominoach
189
11k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
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/