Date post: | 08-May-2015 |
Category: |
Technology |
Upload: | bloodredsun |
View: | 1,411 times |
Download: | 4 times |
LIGHTNING TALK REPLACING THREADS WITH ACTORS FOR CONCURRENT WEB APPLICATION SERVICE CALLS Martin Anderson LJC Open Conference 2011
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
CONCURRENCY MODEL
dispatch service calls
controller’s job done
rendering starts early
3
THREADS
• Well understood (if not always well implemented!)
• java.util.concurrent library eases the pain • Resource usage?
4
ACTORS
• Been around since 1973 • Erlang popularised usage • Actor library for Java? Akka! • Most strongly associated with Scala but
has a Java API
5
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
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
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
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
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
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
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
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
THANK YOU
https://github.com/bloodredsun/ConcurrentWebAppExample
Email: [email protected] Twitter: @mdjanderson Blog: http://bloodredsun.com/ Betfair Blog: http://views.betfair.com/
14