Presented at Feb 2014 Iowa Scala Enthusiasts meetup: http://www.meetup.com/ia-scala/events/158419152/
Git repo contains runnable code samples not in slides: https://github.com/zcox/iascala-dont-block
Actors and Futures make writing concurrent, asynchronous, non-blocking, reactive applications much simpler than dealing with threads, locks and synchronization directly. However, it’s also really easy to inadvertently block in the wrong place and bring your entire system to a grinding halt. We’ll demonstrate some of the common, simple ways to destroy Akka and Spray applications, examine the internals of these libraries to explore what’s happening, and discuss some best practices they provide for avoiding these problems.
6. What is Blocking?
Code that takes a long time to run
Network I/O
HTTP requests
Database access
File I/O
Really heavy computation
Nothing after the blocking function can run on this thread until
it is done
7. Java: R n a l , E e u o
unbe xctr
tatRnal {
ri unbe
dfrn) Ui
e u(: nt
}
tatEeuo {
ri xctr
dfeeuecmad Rnal) Ui
e xct(omn: unbe: nt
}
8. TraPoEeuo
hedolxctr
casTraPoEeuo etnsEeuo {
ls hedolxctr xed xctr
vlpo:StTra]=Stepy
a ol e[hed
e.mt
vltss BoknQeeRnal]=??
a ak: lciguu[unbe
?
dfeeuecmad Rnal) Ui ={
e xct(omn: unbe: nt
/rncmado nwtra,o qeei,o rjc i,dpnigo stig..
/u omn n e hed r uu t r eet t eedn n etns.
}
}
9. How to block T r a P o E e u o
hedolxctr
Execute tasks that block in run() method
All threads in pool get blocked
Tasks are queued before execution (until queue is full)
How it is supposed to work...
Need to be aware of the blocking though
10. FrJiPo
okonol
E e u o S r i eimplementation
xctrevc
saacnurn.okon
cl.ocretfrji
j v . t l c n u r n (Java7)
aaui.ocret
Sub-dividing tasks, work queue, worker thread pool, work stealing, ...
https://www.google.com/search?q=java+fork+join
11. How to block F r J i P o
okonol
Same as T r a P o E e u o
hedolxctr
12. Solutions for Blocked E e u o
xctr
vleeuo =EeuosnwieTraPo(oehed)
a xctr
xctr.eFxdhedolmrTras
vleeuo1=EeuosnwieTraPo(olSz)
a xctr
xctr.eFxdhedolpo1ie
vleeuo2=EeuosnwieTraPo(olSz)
a xctr
xctr.eFxdhedolpo2ie
13. Java: C l a l , F t r ,
albe uue
EeuoSrie
xctrevc
tatClal[]{
ri albeV
dfcl(:V
e al)
}
tatFtr[]{
ri uueV
dfiDn(:Boen
e soe) ola
dfgt) V
e e(:
}
tatEeuoSrieetnsEeuo {
ri xctrevc xed xctr
dfsbi(ak Rnal) Ftr[]
e umtts: unbe: uue_
dfsbi[]ts:Clal[]:Ftr[]
e umtT(ak albeT) uueT
}
14.
15. Ftr[]
uueT
Monad that eventually contains either:
A value of type T(success)
A T r w b e(failure)
hoal
F t r [ ]is the read-side; P o i e T is the write-side
uueT
rms[]
Value is computed and placed into promise/future on some other
thread (usually)
/TD cmeln eapeo Ftr..
/OO oplig xml f uue.
16. Eeuinotx
xctoCnet
Runs code that asynchronously completes futures
Scala version of E e u o /E e u o S r i e
xctr xctrevc
Implementations usually wrap one
E e u o => E e u i n o t x
xctr
xctoCnet
E e u o S r i e=> E e u i n o t x
xctrevc
xctoCnet
F t r . p l runs body function using E e u i n o t x
uueapy
xctoCnet
Wraps the body function in a R n a l
unbe
Executes that R n a l on an E e u i n o t x
unbe
xctoCnet
That R n a l completes a P o i e
unbe
rms
Eeuinotx.lbl
xctoCnetgoa
Tries to use F r J i P o
okonol
Falls back to T r a P o E e u o
hedolxctr
17. How to block F t r /E e u i n o t x
uue xctoCnet
E e u i n o t x just wraps an E e u o /E e u o S r i e
xctoCnet
xctr xctrevc
E e u i n o t x . l b lusually wraps either a
xctoCnetgoa
F r J i P o or a T r a P o E e u o
okonol
hedolxctr
We already know how to block those
tldr function passed to F t r . p l blocks the underlying thread,
uueapy
exhaust the pool
18. Solutions for blocked
F t r /E e u i n o t x
uue xctoCnet
jv ..
aa .
-saacnurn.otx.iTras8
Dcl.ocretcnetmnhed=
-saacnurn.otx.uTras1
Dcl.ocretcnetnmhed=6
-saacnurn.otx.aTras2
Dcl.ocretcnetmxhed=4
..
.
ipii vlc=Eeuinotx.rmxctrEeuosnwieTraPo(2)
mlct a
xctoCnetfoEeuo(xctr.eFxdhedol13)
ipii vldfutotx =Eeuinotx.lbl
mlct a ealCnet
xctoCnetgoa
vldtbsCnet=Eeuinotx.rmxctrnl)
a aaaeotx
xctoCnetfoEeuo(ul
Ftr(dfutpoesn"
uue"eal rcsig)
Ftr(dtbs oeain"(aaaeotx)
uue"aaae prtos)dtbsCnet
19. Actors and Dispatchers
atr!mg
co
s
m gplaced in actor''s M i b xqueue
s
alo
M i b xis a R n a l
alo
unbe
M i b xexecuted on dispatcher''s E e u o S r i e
alo
xctrevc
By default, all actors use the same default dispatcher
20. How to Block Actors
Remember how to block E e u o ? Do that.
xctr
Block in A t r r c i e
co.eev
Enough blocked actors will exhaust the dispatcher''s thread pool
22. Fun Fact
M s a e i p t h ris an E e u i n o t x
esgDsace
xctoCnet
vljbCnet=sse.ipthr.okp"dcdsace"
a dcotx
ytmdsaceslou(jb-ipthr)
Ftr(sTeaaae(dcotx)
uueuehDtbs)jbCnet
23. Spray
spray-io/akka-io: Java NIO + Actors
spray-can: HTTP server & client built on spray-io
spray-routing: HTTP request/response DSL
24. How to Block Spray
Built on actors
We know how to block those
S m l R u i g p uses a single actor to route all requests (!!!)
ipeotnAp
That actor synchronously calls runRoute - easily blocked!
That actor uses default Akka dispatcher - easily blocked!
Example code
25. Solutions for Blocking Spray
Do not call blocking functions directly in routes
Instead detach to F t r or A t r
uue
co
Spray can complete a response using a F t r
uue
Use separate dispatchers
Give Spray its own dispatcher(s)
Give your blocking code its own dispatcher(s)
26. Java NIO and spray-client
Blocking I/O: One thread per socket
Non-blocking I/O: One thread, many sockets
No network I/O (web service client, database, etc) libraries use it!
Except spray-client...
Start writing Scala web service clients using spray-can!
Other protocols (TCP, SMTP, XMPP, various DBs, etc) can use
akka-io