34
Future on Servlet Kazuhiro Sera @seratch 2015/08/01

Future on Servlet #scala_ks

Embed Size (px)

Citation preview

Page 1: Future on Servlet #scala_ks

Future on ServletKazuhiro Sera @seratch

2015/08/01

Page 2: Future on Servlet #scala_ks

Who am I

• @seratch

• ScalikeJDBC(2011 ~)

• Skinny Framework(2013 ~)

• Scalatra、json4s、Scalate

• M3, Inc. Software Developer

Page 3: Future on Servlet #scala_ks

Agenda•Why Future

• Thread local things in the wild

• Future has its own thread pool

• Servlet API’s mutability

• recycling request issue in async mode

• Scalatra DynamicScope issue

• Skinny 2’s solution

Page 4: Future on Servlet #scala_ks

Why Future

Page 5: Future on Servlet #scala_ks

How to use Future

• 1) Creating and composing multiple Futures and then Await.result(Future), returning Servlet response synchronously

• 2) Running Servlets in async mode supported since Servlet 3

Page 6: Future on Servlet #scala_ks

Why Future

• Using Future on Servlet is not always recommended

• OTOH, Future is the standard in Scala now, sometimes needed to smoothly integrate Future-based libraries

• My near affair: using nulab/scala-oauth2-provider in a Servlet application

Page 7: Future on Servlet #scala_ks

Thread local things in the wild

Page 8: Future on Servlet #scala_ks

Threaded model

• one thread for one request

• A thread returns a response for a request

• On the same thread for whole process

• Thread pool managed by containers

• JavaEE 7 has JSR-236 to show how to use concurrency

Page 9: Future on Servlet #scala_ks

ThreadLocal

• DynamicVariable in Scala

• Sometimes have an easy time of it by using ThreadLocal if no multithreading

• No need to take state around to methods

• AOP friendly

• Implicit state makes code simple

Page 10: Future on Servlet #scala_ks

Future has its own thread pool

Page 11: Future on Servlet #scala_ks

Future• Future scaladoc

• Future.apply { different thread here }

• Future.successful { same thread here }

• Can easily create async operations that run on different threads managed by thread pool (ExecutionContext)

• Too easy to access fields on the Servlet thread from Future threads

Page 12: Future on Servlet #scala_ks

Servlet API’s mutability

Page 13: Future on Servlet #scala_ks

Servlet API is mutable

• Request#setAttribute(String, AnyRef)

• Implementation patterns that depend on request attributes

• Objects managed by containers

• Writing result value on response any time

• Simply accessing them among multiple threads is so fragile

Page 14: Future on Servlet #scala_ks

recycling request issue in async mode

Page 15: Future on Servlet #scala_ks

JSR 340: Java Servlet 3.1 Specification https://jcp.org/en/jsr/detail?id=340

Page 16: Future on Servlet #scala_ks

Bug 433321 - request.getContextPath() is null when working in async mode https://bugs.eclipse.org/bugs/show_bug.cgi?id=433321

Jetty

Page 17: Future on Servlet #scala_ks

Bug 46792 - NullPointerException in org.apache.catalina.connector https://bz.apache.org/bugzilla/show_bug.cgi?id=46792#c5

Tomcat

Page 18: Future on Servlet #scala_ks

JSR 340: Java Servlet 3.1 Specification https://jcp.org/en/jsr/detail?id=340

Page 19: Future on Servlet #scala_ks

recycling requests

• In fact, request can be recycled before AsyncContext#complete()

• Containers commonly do the “recycle” in order to avoid performance overhead

• If I understand right, even though Servlet spec says same about response (5.7), response won’t be recycled until its closure at least in cases of stateless HTTP

Page 20: Future on Servlet #scala_ks

Scalatra DynamicScope issue

Page 21: Future on Servlet #scala_ks

Too easy to access this valueeverywhere including Future

threads created on this Servlet

Page 22: Future on Servlet #scala_ks
Page 23: Future on Servlet #scala_ks

request/response

• ScalatraBase’s request/response are thread local, too dangerous to access them from Future threads

• All the DSL and extensions don’t accept request as implicit parameter

• In the initial state, this design is reasonable (Future didn’t exist at the time, Sinatra concept)

Page 24: Future on Servlet #scala_ks

Skinny 2’s solution

Page 25: Future on Servlet #scala_ks

Skinny 2.0

Page 26: Future on Servlet #scala_ks

skinny-engine

Page 27: Future on Servlet #scala_ks

skinny-engine

• Started as a Scalatra fork, much improved internal code while DSL source compatibility is kept

• Many renaming/re-packaging and a few removal on traits

• Passed all the Scalatra’s existing tests

• I’d love to contribute skinny-engine’s improvements to Scalatra too

Page 28: Future on Servlet #scala_ks

stable request

Page 29: Future on Servlet #scala_ks

stable request

• Stable access to read-only data, request attributes even when request has been recycled while Future ops are still running

• Validates unstable access to objects managed by containers (2.0.0.M3)

• Should work at least on Jetty and Tomcat

Page 30: Future on Servlet #scala_ks

No more DynamicScope

Page 31: Future on Servlet #scala_ks

No more DynamicScope

• Pass skinny.engine.Context as implicit parameter to all the DSL APIs

• AsyncSkinnyEngineServlet/Filter accept (Context) => Any as action instead

• On Scalatra compatible traits, detect fragile code by checking compilation errors: ‘error: ambiguous implicit values’

Page 32: Future on Servlet #scala_ks

New async trait

Page 33: Future on Servlet #scala_ks

Scalatra compatible trait

Page 34: Future on Servlet #scala_ks

Oh-ki-ni! :) (‘Thanks’ in Osaka)