Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Servlet と Future の関わり方 #scala_ks

6,460 views

Published on

English version is here: http://www.slideshare.net/seratch/future-on-servlet-scalaks

http://summit.scala-kansai.org/ でのプレゼンです

Published in: Technology
  • Be the first to comment

Servlet と Future の関わり方 #scala_ks

  1. 1. Servlet と Future の関わり方 Kazuhiro Sera @seratch_ja 2015/08/01
  2. 2. 自己紹介 •東京から来ました •@seratch / @seratch_ja •ScalikeJDBC(2011 ∼) •Skinny Framework(2013 ∼) •Scalatra、json4s、Scalate メンテナ •エムスリー株式会社 ソフトウェアエンジニア
  3. 3. アジェンダ •前提・背景 •スレッドローカルが存在する世界 •Future はスレッドプールが裏にいる •Servlet API の mutability •Async モードでの request リサイクル問題 •Scalatra の DynamicScope 問題 •Skinny 2 でのソリューション
  4. 4. 前提・背景
  5. 5. 2 つのパターン •メインスレッドから Future を複数投げて Await.result(Future) で待ち合わせ、同期で Servlet response を返す •Servlet 3 からの async mode により非同期 で Servlet response を返す(今日のテーマは 主にこっち)
  6. 6. なぜ Future か •Servlet において Scala の Future を積極的に 使っていく必要性は特にない •とはいえ 2.10 から入った Future は十分に普 及してきた、Future を返す実装の組み込みに 対応できないと実用上困るケースがある •身近な具体例では nulab/scala-oauth2- provider を使うにあたり、支障があった
  7. 7. スレッドローカル が存在する世界
  8. 8. スレッドモデル •request を受けて response を返すスレッド •HTTP レスポンス返すまでメインスレッドだけ で処理するのが基本的なスタイル •このメインスレッドは Servlet コンテナが持つ スレッドプールで管理される •JavaEE 7 は JSR-236 でコンポーネント管理 と非同期処理を両立するための仕様を提示
  9. 9. スレッドローカル •Scala では DynamicVariable •シングルスレッドで完結する前提ならスレッド ローカルを使って色々楽ができる •状態をパラメータで引き回さない •AOP で透過的な処理をはさみこみやすい •暗黙の状態を活用、コードがシンプルに
  10. 10. Future は スレッドプールが 裏にいる
  11. 11. Future •Future scaladoc •Future.apply { ここは別スレッド } •Future.successful { ここは同じスレッド } •カジュアルに別スレッドの処理が生まれる、適 当にやってもスレッドプール (ExecutionContext で指定)で管理される •Future を生んだ元スレッドの値を Future 側 のスレッドから簡単に参照できてしまう(後述)
  12. 12. Servlet API の mutability
  13. 13. mutability •request#setAttribute(String, AnyRef) を始 めとする setter メソッド •request attributes に依存する実装パターン •session などコンテナ管理のオブジェクト •任意のタイミングで response を出力 •マルチスレッドでアクセスする場合、素のまま で扱うのはあやうい
  14. 14. Async モードでの request リサイクル問題
  15. 15. JSR 340: Java Servlet 3.1 Specification https://jcp.org/en/jsr/detail?id=340
  16. 16. Bug 433321 - request.getContextPath() is null when working in async mode https://bugs.eclipse.org/bugs/show_bug.cgi?id=433321 Jetty
  17. 17. Bug 46792 - NullPointerException in org.apache.catalina.connector https://bz.apache.org/bugzilla/show_bug.cgi?id=46792#c5 Tomcat
  18. 18. JSR 340: Java Servlet 3.1 Specification https://jcp.org/en/jsr/detail?id=340
  19. 19. recycling objects •実際の挙動として request は AsyncContext#complete() が呼ばれる前に recycle されることがある •パフォーマンス上のオーバーヘッドを避けるた め複数の Servlet コンテナに共通する挙動 •Servlet の仕様に response についても同様の 記述(5.7)はあるが、少なくとも stateless な HTTP 通信に関しては close まで維持され ると考えてよいはず
  20. 20. Scalatra の DynamicScope 問題
  21. 21. この Servlet 上で作られた Future のスレッド内も含め どこからでもこの request に 気軽にアクセスできてしまう
  22. 22. request/response •Scalatra の request/response はスレッドロー カル、Future 側からそのまま触れない •implicit パラメータで引き渡すアプローチにす べての DSL、拡張が対応していない、意図せ ず DynamicScope が呼び出される •最初期の目的・設計は妥当だった(Future は まだメインストリームでなかった、模倣した Sinatra は Rack アプリ)
  23. 23. Skinny 2 での ソリューション
  24. 24. Skinny 2.0
  25. 25. skinny-engine
  26. 26. skinny-engine •Scalatra を fork して DSL の互換性は維持し つつ、内部実装を大きく変えた •trait の構成はあまり互換性を維持していない (改名・構造の変更・削除) •Scalatra の既存のテストをほぼそのままの状 態ですべて pass している •改善アイデア、潜在的問題の発見があった、 Scalatra にもフィードバックしていきたい
  27. 27. stable request
  28. 28. stable request •request を Future が処理中のタイミングで recycle されたとしても read-only な情報、 request attributes 等へのアクセスを保証 •request attributes の更新も考慮 •コンテナ管理オブジェクトの操作はメインスレッ ド以外ではアクセスエラーに(2.0.0.M3) •少なくとも Jetty、Tomcat で動作保証
  29. 29. No more DynamicScope
  30. 30. No more DynamicScope •前提として、すべての DSL に Context を implicit parameter として渡す •Context を引数にとる関数をアクションとして とる AsyncSkinnyEngineServlet/Filter •Scalatra 互換な trait では error: ambiguous implicit values (コンパイルエ ラー)を発生させて確実に潰す
  31. 31. New async trait
  32. 32. Scalatra compatible trait
  33. 33. 話したこと •前提・背景 •スレッドローカルが存在する世界 •Future はスレッドプールが裏にいる •Servlet API の mutability •Async モードでの request リサイクル問題 •Scalatra の DynamicScope 問題 •Skinny 2 でのソリューション
  34. 34. ハンズオンの宣伝
  35. 35. Minimum Skinny 2 App おそらく一番簡単な Scala Web アプリ実装
  36. 36. 13:30 ∼ @第4会議室 •これから Scala を始めたい方向けです •Servlet に馴染みがあるなら、まず Skinny で Scala を始めてみましょう •安定版の 1.3 or skinny-engine-server で •作者なので使い方の質問すぐ答えます •13:30 - 第 4 会議室でお待ちしています
  37. 37. おおきに :)

×