martin anderson - threads v actors

14
LIGHTNING TALK REPLACING THREADS WITH ACTORS FOR CONCURRENT WEB APPLICATION SERVICE CALLS Martin Anderson LJC Open Conference 2011

Upload: bloodredsun

Post on 08-May-2015

1.410 views

Category:

Technology


4 download

DESCRIPTION

Slides from my lightning presentation from the London Java Community Open Conference Nov 2011

TRANSCRIPT

Page 1: Martin Anderson - threads v actors

LIGHTNING TALK REPLACING THREADS WITH ACTORS FOR CONCURRENT WEB APPLICATION SERVICE CALLS Martin Anderson LJC Open Conference 2011

Page 2: Martin Anderson - threads v actors

CONCURRENT SERVICE CALLS

•  Most web pages need data from multiple sources

•  Scatter/Gather approach to perform all the service calls in parallel then rendering the responses

2

Page 3: Martin Anderson - threads v actors

CONCURRENCY MODEL

dispatch service calls

controller’s job done

rendering starts early

3

Page 4: Martin Anderson - threads v actors

THREADS

•  Well understood (if not always well implemented!)

•  java.util.concurrent library eases the pain •  Resource usage?

4

Page 5: Martin Anderson - threads v actors

ACTORS

•  Been around since 1973 •  Erlang popularised usage •  Actor library for Java? Akka! •  Most strongly associated with Scala but

has a Java API

5

Page 6: Martin Anderson - threads v actors

USING AN EXECUTOR SERVICE IN A SERVLET

public void doGet(HttpServletRequest request, HttpServletResponse response) throws…{

List<MyServiceCallable> myServiceCallables = new ArrayList<MyServiceCallable>();

for (int ii = 0; ii < 10; ii++) { myServiceCallables.add(new MyServiceCallablle(remoteClient)); }

List<Future<String>> futures = executorService.invokeAll(myServiceCallables);

… for (Future future : futures) { writer.write( future.get() ); }

… }

6

Page 7: Martin Anderson - threads v actors

USING AKKA ACTORS IN A SERVLET

public void doGet(HttpServletRequest request, HttpServletResponse response) throws…{

Works works = new Works(); for (int ii = 0; ii < 10; ii++) {

works.add(new Work())); } masterActor.tell(works);

List<Future<String>> futures = works.getFutures();

… for (Future future : futures) { writer.write( future.get() ); }

… }

7

Page 8: Martin Anderson - threads v actors

SO WHAT’S IN AN ACTOR 1?

public class MasterActor extends UntypedActor { private ActorRef router; static class LoadBalancer extends UntypedLoadBalancer { private final InfiniteIterator<ActorRef> workers; public LoadBalancer(ActorRef[] workers) { this.workers =

new CyclicIterator<ActorRef>(asList(workers)); } public InfiniteIterator<ActorRef> seq() { return workers; } }

8

Page 9: Martin Anderson - threads v actors

SO WHAT’S IN AN ACTOR 2?

public MasterActor(final int numWorkers, final RemoteClient remoteClient) { // create an array of started workers final ActorRef[] workers = new ActorRef[numWorkers]; for (int i = 0; i < numWorkers; i++) { workers[i] = actorOf( new UntypedActorFactory() { public UntypedActor create() { return new WorkerActor(remoteClient); } }) .start(); } // wrap all the workers with a load-balancing router router = actorOf(new UntypedActorFactory() { public UntypedActor create() { return new LoadBalancer(workers); } }).start(); }

9

Page 10: Martin Anderson - threads v actors

SO WHAT’S IN AN ACTOR 3?

// message handler in MasterActor public void onReceive(Object message) { if (message instanceof Works) { for (Work work : ((Works) message).getAll()) { router.tell(work); } } }

10

Page 11: Martin Anderson - threads v actors

SO WHAT’S IN AN ACTOR 4?

public class WorkerActor extends UntypedActor { RemoteClient remoteClient; public WorkerActor(RemoteClient remoteClient) { this.remoteClient = remoteClient; } @Override public void onReceive(Object message) throws Exception { if (message instanceof Work) { Work work = (Work) message; remoteClient.execute(work); } } }

11

Page 12: Martin Anderson - threads v actors

SO WHAT’S IN OUR REMOTECLIENT?

public void execute(final Work work) throws IOException {

ContentExchange exchange = new ContentExchange() { protected void onResponseComplete() throws IOException {

super.onResponseComplete(); String responseContent = this.getResponseContent(); work.setFutureResponse(responseContent); } }; //set the method and the url exchange.setMethod("GET"); exchange.setURL(work.getUrl()); // start the exchange httpClient.send(exchange);

}

12

Page 13: Martin Anderson - threads v actors

SO WHY USE AKKA/ACTORS

•  More resource efficient for certain jobs •  Easier for mere mortals to reason with •  Nested supervisors can restart failed actors •  Supports STM if required

13

Page 14: Martin Anderson - threads v actors

THANK YOU

https://github.com/bloodredsun/ConcurrentWebAppExample

Email: [email protected] Twitter: @mdjanderson Blog: http://bloodredsun.com/ Betfair Blog: http://views.betfair.com/

14