Kotlin Coroutines と Ktor HTTP Client で作るスケールするタスク実行
by
Hideyuki Takeuchi
×
Copy
Open
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Slide 1
Slide 1 text
Kotlin Coroutines と Ktor HTTP Client で作る スケールするタスク実⾏
Slide 2
Slide 2 text
⾃⼰紹介 たけうち ひでゆき @chimerast 株式会社イエソド エンジニア
Slide 3
Slide 3 text
イエソド社 提供サービス SaaS 統制 プラットフォーム 「 YESOD 」 ⼈・組織・情報と SaaS をシームレスに 管理するためのSaaS
Slide 4
Slide 4 text
No content
Slide 5
Slide 5 text
No content
Slide 6
Slide 6 text
No content
Slide 7
Slide 7 text
No content
Slide 8
Slide 8 text
本題
Slide 9
Slide 9 text
本⽇扱うコルーチンの対象範囲 ⼤量のタスクの並⾏実⾏
Slide 10
Slide 10 text
サービスの要件の⼀つ 毎朝午前 4 時に、顧客が利⽤している、 全ての SaaS のアカウント状態を取り込みたい
Slide 11
Slide 11 text
No content
Slide 12
Slide 12 text
SaaS 連携サーバの課題 SaaS 連携サーバからのHTTP レスポンスが、 2 秒〜20 分 SaaS 連携サーバは各SaaS からアカウントの状態を取り込む SaaS 連携サーバは無限に⽔平スケールする想定(GKE) もちろんDDoS っぽくならないようにスロットリングはする
Slide 13
Slide 13 text
そこから派⽣する課題 「全てのお客さんが使っている、全てのSaaS のアカウント」 100 企業 × 100 SaaS = 10,000 リクエスト 1,000 企業 × 100 SaaS = 100,000 リクエスト Kotlin/Java でHTTP のブロッキングAPI を利⽤して作ると、 スレッド数の限界を超える
Slide 14
Slide 14 text
スレッドを利⽤したダメな例 fun main() { val pool = Executors.newFixedThreadPool(4) repeat(10000) { // 10,000 タスク pool.submit { // 10 秒レスポンスを待つだけのタスク Thread.sleep(10000L) println("DONE: " + Thread.currentThread().name) } } pool.shutdown() } → 実質4 並列でしか動かず、10 秒に4 つタスクが終わる。 全て終わるまで約7 時間。
Slide 15
Slide 15 text
並⾏タスク実⾏における スレッド & コルーチンおさらい
Slide 16
Slide 16 text
並⾏プログラミング観点から プロセス プリエンプティブマルチタスク メモリ空間: 独⽴ タスク切り替え: OS レイヤー スレッド プリエンプティブマルチタスク メモリ空間: 共有 タスク切り替え: OS レイヤー コルーチン ノンプリエンプティブマルチタスク メモリ空間: 共有 タスク切り替え: アプリレイヤー
Slide 17
Slide 17 text
同期・⾮同期プログラミング観点から スレッド ブロッキングモデル タスク実⾏中に、待ちが発⽣した際に、他のタスクにスレッドを 明け渡せない コルーチン ノンブロッキングモデル タスク実⾏中に、待ちが発⽣した際に、スレッドを明け渡せる 変な待ち⽅をすると他の全てのタスクが⽌まる
Slide 18
Slide 18 text
スレッド vs コルーチン スレッド コルーチン タスク辺りのメモリ使⽤量 多くなる 少ない コンテキストスイッチのオーバーヘッド ある 少ない プログラムのしやすさ 簡単 難しい (?) プログラムのしやすさは諸説ある コルーチンは、プログラマが他のタスクに、 いつCPU を明け渡すか制御しなければならない。
Slide 19
Slide 19 text
スレッド と コルーチン の関係性 スレッド と コルーチン は排他ではない。 複数スレッドの上で複数コルーチンを動かすことができる Node.js 1 スレッド x 複数コルーチン (Promise) Kotlin 複数スレッド x 複数コルーチン (suspending function)
Slide 20
Slide 20 text
Coroutines | Kotlin https://kotlinlang.org/docs/coroutines-overview.html コルーチンをいい感じに実装できるAPI 群
Slide 21
Slide 21 text
Coroutines を複数スレッドで⾛らせる正しい例 fun main() { val pool = Executors.newFixedThreadPool(4) runBlocking(pool.asCoroutineDispatcher()) { repeat(10000) { // 10,000 タスク async { // 10 秒レスポンスを待つだけのタスク delay(10000L) println("DONE: " + Thread.currentThread().name) } } } pool.shutdown() } → 10 秒(10000L) で10000 タスク全部終わる
Slide 22
Slide 22 text
Coroutines を使ってるけどダメな例 fun main() { val pool = Executors.newFixedThreadPool(4) runBlocking(pool.asCoroutineDispatcher()) { repeat(10000) { // 10,000 タスク async { // 10 秒レスポンスを待つだけのタスク Thread.sleep(10000L) // delay(10000L) println("DONE: " + Thread.currentThread().name) } } } pool.shutdown() } → 10 秒(10000L) に⼀回4 つタスクが流れるだけ
Slide 23
Slide 23 text
Coroutines を使っているのに、なにが違うか? delay(10000L) suspending function → ノンブロッキング 他のコルーチンが動ける Thread.sleep(10000L) 普通のfunction → ブロッキング 他のコルーチンが動けない
Slide 24
Slide 24 text
Ktor HTTP Client https://ktor.io/docs/client.html JetBrains 謹製のフレームワーク「Ktor 」の HTTP Client API 群 Kotlin coroutines を利⽤した、awesome な HTTP Client ( 意訳) もちろんすべてノンブロッキングAPI
Slide 25
Slide 25 text
Ktor HTTP Client で HTTP リクエストを投げる fun main() { val client = HttpClient() val pool = Executors.newFixedThreadPool(4) runBlocking(pool.asCoroutineDispatcher()) { repeat(10000) { async { val response = client.get("http://localhost:4000/healthcheck") println("DONE [${Thread.currentThread().name}]: $response") } } } pool.shutdown() } → HTTP サーバからレスポンスが待たされたとしても、 他のリクエストが並⾏で実⾏される
Slide 26
Slide 26 text
並⾏ / 並列処理プログラミング TIPS ローカルでの開発時には、 すべてのスレッドプールの数を1 にする DB のコネクションプールの数も1 にする
Slide 27
Slide 27 text
Ktor TIPS デフォルトのHTTP 待ち受けスレッドプールの数が Runtime.getRuntime().availableProcessors() (CPU 論理コア数) に 設定される。 クラスタのノードがしょぼいインスタンスだとこれが1 になって、 本番環境だとなんか動かないと焦る時がある ktor { deployment { connectionGroupSize = < 適切な値> workerGroupSize = < 適切な値> callGroupSize = < 適切な値> } }
Slide 28
Slide 28 text
まとめ 並⾏・並列処理と コルーチンはおもしろいよ 並⾏と並列の⾔葉遣い間違ってたら すみません 右の画像は、15 年前の本だけどガチ でお勧めな本
Slide 29
Slide 29 text
Kotlin Ktor Exposed TypeScript Vue.js Vuex Kubenetes (GKE) Istio Grafana Prometheus Argo CD