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
NestJS で 重たい処理と軽い処理が 干渉しないようにデプロイするには
Search
whatasoda
March 16, 2025
Technology
1
630
NestJS で 重たい処理と軽い処理が 干渉しないようにデプロイするには
NestJS Meetup #6 2025/3/17
whatasoda
March 16, 2025
Tweet
Share
More Decks by whatasoda
See All by whatasoda
バランスを見極めよう!実装の意味を明示するための型定義 TSKaigi 2025 Day2 (5/24)
whatasoda
2
940
急速に利用拡大を続ける飲食店向けサービスで 店内端末同士のローカル通信を追加設定なしで実現した話
whatasoda
0
340
ReactNative アプリ同士の通信のために型情報をサクッと共有した話 #TSKaigi サブイベント
whatasoda
1
1k
GraphQL でネストしたクエリを書いたら Apollo Client が無限に計算し続けるようになった話
whatasoda
0
590
Other Decks in Technology
See All in Technology
TS-S205_昨年対比2倍以上の機能追加を実現するデータ基盤プロジェクトでのAI活用について
kaz3284
1
170
下手な強制、ダメ!絶対! 「ガードレール」を「檻」にさせない"ガバナンス"の取り方とは?
tsukaman
2
450
5分でカオスエンジニアリングを分かった気になろう
pandayumi
0
250
CDK CLIで使ってたあの機能、CDK Toolkit Libraryではどうやるの?
smt7174
4
180
複数サービスを支えるマルチテナント型Batch MLプラットフォーム
lycorptech_jp
PRO
1
390
Agile PBL at New Grads Trainings
kawaguti
PRO
1
440
共有と分離 - Compose Multiplatform "本番導入" の設計指針
error96num
2
580
まずはマネコンでちゃちゃっと作ってから、それをCDKにしてみよか。
yamada_r
2
110
スマートファクトリーの第一歩 〜AWSマネージドサービスで 実現する予知保全と生成AI活用まで
ganota
2
220
新規プロダクトでプロトタイプから正式リリースまでNext.jsで開発したリアル
kawanoriku0
1
120
Function Body Macros で、SwiftUI の View に Accessibility Identifier を自動付与する/Function Body Macros: Autogenerate accessibility identifiers for SwiftUI Views
miichan
2
180
未経験者・初心者に贈る!40分でわかるAndroidアプリ開発の今と大事なポイント
operando
5
640
Featured
See All Featured
VelocityConf: Rendering Performance Case Studies
addyosmani
332
24k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
16k
GraphQLとの向き合い方2022年版
quramy
49
14k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
358
30k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
jQuery: Nuts, Bolts and Bling
dougneiner
64
7.9k
Bash Introduction
62gerente
615
210k
For a Future-Friendly Web
brad_frost
180
9.9k
Raft: Consensus for Rubyists
vanstee
140
7.1k
Music & Morning Musume
bryan
46
6.8k
Building an army of robots
kneath
306
46k
Transcript
© 2025 Dinii Inc. NestJS Meetup #6 2025/3/17 NestJS で
重たい処理と軽い処理が 干渉しないようにデプロイするには Shota Hatada (@whatasoda)
株式会社 ダイニー © 2025 Dinii Inc. NestJS で重たい処理と軽い処理が干渉しないようにデプロイするには ━━ NestJS
Meetup #6 2025/3/17 自己紹介 2020 - 2022 SWE (Frontend) at mercari 2022 - Platform Engineer at Dinii Inc. Shota Hatada (@whatasoda) やっていること • Google Cloud を使ったインフラ整備 • NestJS / React Native アプリの基盤実装 • サービス安定性・拡張性向上に向けた活動 すきなもの/こと • TypeScript • スパラクーア • アニメ・ゲーム
株式会社 ダイニー © 2025 Dinii Inc. NestJS で重たい処理と軽い処理が干渉しないようにデプロイするには ━━ NestJS
Meetup #6 2025/3/17 3行で要約 • モノリスなサービスでは重たい処理が軽い処理を邪魔することがある • Node.js の特性を知り、避けられない運命であることを知る • NestJS でインターフェイス層だけ分割してデプロイしてみよう!
株式会社 ダイニー © 2025 Dinii Inc. 重たい処理が軽い処理を邪魔する NestJS で重たい処理と軽い処理が干渉しないようにデプロイするには ━━
NestJS Meetup #6 2025/3/17 色々あると思うが… 1つのアプリケーションはいろいろな処理の集合体として存在している (括弧内はダイニーの例) • リアルタイム性が求められる処理 ◦ レイテンシをできるだけ下げたい(注文・会計) • 大量のデータを元に大量の計算を行う処理 ◦ 多少時間がかかっても許容できる(売上集計・分析) • 定期的に実行したいバッチ処理 ◦ 数分かかる処理もあるが、許容できる(メッセージ配信・送金) • 高頻度で Polling される処理 ◦ たまに失敗してもいいが、数がとにかく多い(プリンターに印刷物を配信する) モノリスなアプリケーションの特徴
株式会社 ダイニー © 2025 Dinii Inc. 重たい処理が軽い処理を邪魔する NestJS で重たい処理と軽い処理が干渉しないようにデプロイするには ━━
NestJS Meetup #6 2025/3/17 色々あると思うが… 1つのアプリケーションはいろいろな処理の集合体として存在している (括弧内はダイニーの例) • リアルタイム性が求められる処理 ◦ レイテンシをできるだけ下げたい(注文・会計) • 大量のデータを元に大量の計算を行う処理 ◦ 多少時間がかかっても許容できる(売上集計・分析) • 定期的に実行したいバッチ処理 ◦ 数分かかる処理もあるが、許容できる(メッセージ配信・送金) • 高頻度で Polling される処理 ◦ たまに失敗してもいいが、数がとにかく多い(プリンターに印刷物を配信する) モノリスなアプリケーションの特徴 この2つが同じ Cloud Run に デプロイされていた時期がある
株式会社 ダイニー © 2025 Dinii Inc. • Cloud Run +
AlloyDB な構成 ◦ Google Cloud 内の通信経路を利用している • タイムアウトのエラーは node-postgres 由来のもの ◦ setTimeout が使われていて、初回は 3 秒に設定している • 全く同じタイミングで走っている処理では成功していそう ◦ 通信部分に問題はなさそう…? 重たい処理が軽い処理を邪魔する NestJS で重たい処理と軽い処理が干渉しないようにデプロイするには ━━ NestJS Meetup #6 2025/3/17 データベースとの接続にタイムアウトすることがあった
株式会社 ダイニー © 2025 Dinii Inc. • タイムアウトのログの直前に Slow な
Query が完了したことを示すログがある ◦ 怪しい • Slow な Query のログの直前、そのインスタンスのログが不自然に抜けている ◦ 怪しい……! • 大量のデータを取得するクエリが実行されていた! ◦ 怪しすぎる………!!! 重たい処理が軽い処理を邪魔する NestJS で重たい処理と軽い処理が干渉しないようにデプロイするには ━━ NestJS Meetup #6 2025/3/17 更に調査を進めると…
株式会社 ダイニー © 2025 Dinii Inc. 重たい処理が軽い処理を邪魔する NestJS で重たい処理と軽い処理が干渉しないようにデプロイするには ━━
NestJS Meetup #6 2025/3/17 ※諸々のログを追加した後の様子 9.6秒
株式会社 ダイニー © 2025 Dinii Inc. なのにどうして最終的にはタイムアウトになってしまうのか… (時系列的には接続成功のほうが先のハズ…) • 受け取ったデータを読み込む
or パースする処理がスレッドを占有している • 実は接続に成功しているが、成功したときに行う処理ができていない • ただ、タイムアウトが来ても setTimeout のコールバックも処理できていない Node.js の特性を知る NestJS で重たい処理と軽い処理が干渉しないようにデプロイするには ━━ NestJS Meetup #6 2025/3/17 ① Node.js はシングルスレッド (同時に1つの処理しかできない ※) ※ libuv のスレッドプールに空きがある場合、内部的には一部の処理がマルチスレッドで処理される場合があります。 しかし、今回は vCPU x 1 の構成をとっているため、 JavaScript としての処理と libuv 内部の処理のどちらがスレッドを利用しているかどうかの区 別をつけられていません。 (そもそも今回は DB との IO についての話なので、仮にマルチスレッド環境だったとしてもあんまり関係ないかも…)
株式会社 ダイニー © 2025 Dinii Inc. 1. poll でデータ量の多いクエリの結果を受け取る 2.
micro task で結果を処理する ↑ ここに時間がかかかる 3. timers が評価され、Promise が reject される 4. 接続できたことは次の poll でわかるが、 その前に Promise が reject されてしまっている… Node.js の特性を知る NestJS で重たい処理と軽い処理が干渉しないようにデプロイするには ━━ NestJS Meetup #6 2025/3/17 ② Node.js は イベントループに従って処理が進む https://nodejs.org/en/learn/asynchronous-work/event-loop-timers-and-nexttick
株式会社 ダイニー © 2025 Dinii Inc. • setImmediate を使い、時間がかかったイベントをログに出す (check
で評価される) • async_hooks を使い、時間がかかった micro task をログに出す • node-postgres のログもちょっぴり改善して詳細がわかるようにした Node.js の特性を知る NestJS で重たい処理と軽い処理が干渉しないようにデプロイするには ━━ NestJS Meetup #6 2025/3/17 check check poll + micro tasks timers 12.6秒
株式会社 ダイニー © 2025 Dinii Inc. • データベースへの接続に関する処理がブロックされる • レスポンスやリクエストに関する処理も遅れる
• タイムアウトが絡むと、ただ遅れる以外の問題も発生する Node.js の特性を知る NestJS で重たい処理と軽い処理が干渉しないようにデプロイするには ━━ NestJS Meetup #6 2025/3/17 check check poll + micro tasks timers 12.6秒
重たいデータを扱うときは 他の処理を止める覚悟を持つべし
株式会社 ダイニー © 2025 Dinii Inc. • 本来は処理に 1 秒もかからないものでも、スレッドがブロックされると数秒かかる
• 「ログが出ない」という挙動になりがちなので、気が付きにくい • Node.js の特性上、発生そのものを回避することはできない(抑制はできるヨ) 重たい処理と軽い処理を別々のスレッドで処理する NestJS で重たい処理と軽い処理が干渉しないようにデプロイするには ━━ NestJS Meetup #6 2025/3/17 重たいデータを扱うときは処理が止まる覚悟を持つべし もう、別々のスレッドで処理するしかない…
株式会社 ダイニー © 2025 Dinii Inc. 全部分けるのは大変なので… インターフェイスだけ分割してデプロイしてみる • controller
や resolver を含む Module をまとめる Module をつくる ◦ まずはリクエストを分類する必要がある ◦ 命名例: primary, task, batch, etc. • 環境変数によって選択的に Module を import する ◦ アプリケーションレベルでも分割が行われる ◦ 副次的にモジュールの読み込み時間も短縮できる • 同じ Docker Image を使って複数の Cloud Run サービスをデプロイする ◦ インフラを分ける ◦ クライアント側は呼び出し先をよしなに切り替える 重たい処理と軽い処理を別々のスレッドで処理する NestJS で重たい処理と軽い処理が干渉しないようにデプロイするには ━━ NestJS Meetup #6 2025/3/17
株式会社 ダイニー © 2025 Dinii Inc. 重たい処理と軽い処理を別々のスレッドで処理する NestJS で重たい処理と軽い処理が干渉しないようにデプロイするには ━━
NestJS Meetup #6 2025/3/17 ← 選択的 import 先のマッピング ↙ モジュールをまとめる ↓ 選択的 import を行う Module
株式会社 ダイニー © 2025 Dinii Inc. 分け方のすすめ • リクエストの量 ◦
同じ傾向でリクエスト量が増えるのであればインフラのスケールも揃えたい • リクエストに求められるリアルタイム性(リアルタイム性 ≠ レイテンシの低さ) ◦ リアルタイム性が要求されずとも、たまたまレイテンシが低いものもある • 明らかにスレッドブロックを発生させることがわかっているもの ◦ バッチ処理や分析系の処理は分ける ◦ 理想的にはバッチ処理は 1 プロセス 1 リクエストがいい 重たい処理と軽い処理を別々のスレッドで処理する NestJS で重たい処理と軽い処理が干渉しないようにデプロイするには ━━ NestJS Meetup #6 2025/3/17
株式会社 ダイニー © 2025 Dinii Inc. おしらせ NestJS で重たい処理と軽い処理が干渉しないようにデプロイするには ━━
NestJS Meetup #6 2025/3/17 https://dinii.connpass.com/event/348179/