Upload
kazuhiro-sera
View
162
Download
0
Embed Size (px)
Citation preview
Future on ServletKazuhiro Sera @seratch
2015/08/01
Who am I
• @seratch
• ScalikeJDBC(2011 ~)
• Skinny Framework(2013 ~)
• Scalatra、json4s、Scalate
• M3, Inc. Software Developer
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
Why Future
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
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
Thread local things in the wild
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
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
Future has its own thread pool
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
Servlet API’s mutability
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
recycling request issue in async mode
JSR 340: Java Servlet 3.1 Specification https://jcp.org/en/jsr/detail?id=340
Bug 433321 - request.getContextPath() is null when working in async mode https://bugs.eclipse.org/bugs/show_bug.cgi?id=433321
Jetty
Bug 46792 - NullPointerException in org.apache.catalina.connector https://bz.apache.org/bugzilla/show_bug.cgi?id=46792#c5
Tomcat
JSR 340: Java Servlet 3.1 Specification https://jcp.org/en/jsr/detail?id=340
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
Scalatra DynamicScope issue
Too easy to access this valueeverywhere including Future
threads created on this Servlet
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)
Skinny 2’s solution
Skinny 2.0
skinny-engine
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
stable request
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
No more DynamicScope
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’
New async trait
Scalatra compatible trait
Oh-ki-ni! :) (‘Thanks’ in Osaka)