简体   繁体   中英

Akka actors and futures: Understanding by example

I'm trying to learn Akka actors and futures but after reading the docs at http://akka.io and doing http://doc.akka.io/docs/akka/2.0.2/intro/getting-started-first-java.html I'm still having some issues with understanding. I guess calculate the value of Pi is a thing a lot of people can relate too, but not me =). I have search around a bit but haven't found any examples that suits me. Therefore I thought that I would take some real-life code of mine and throw it in here and exchange it for an example of how to do this with Akka.

Ok so here we go:

I have an java play2 application where I need to take some data from my DB and index it in my elasticsearch instance.

  1. I call the DB and get the ids for the venues.

  2. I then split the list and create a couple of callable indextasks.

  3. After that I invoke all tasks where each task collects the venues for the assigned ids from the db.

  4. For each venue index it to the elasticsearch instance and make it searchable.

  5. Done.

Application.java:

public class Application extends Controller {

  private static final int VENUE_BATCH = 1000;
  private static int size;

  public static Result index() {

      List<Long> venueIds = DbService.getAllVenueIds();
      size = venueIds.size();
      Logger.info("Will index " + size + " items in total.");
      ExecutorService service = Executors.newFixedThreadPool(getRuntime().availableProcessors());
      int startIx = 0;
      Collection<Callable<Object>> indexTasks = new ArrayList<Callable<Object>>();
      do {
          int endIx = Math.min(startIx + VENUE_BATCH, size);
          List<Long> subList = venueIds.subList(startIx, endIx);
          VenueIndexTask indexTask = new VenueIndexTask(subList);
          indexTasks.add(indexTask);
      } while ((startIx += VENUE_BATCH) < size);

      Logger.info("Invoking all tasks!");
      try {
          service.invokeAll(indexTasks);
      } catch (InterruptedException e) {
          e.printStackTrace();
      }

      return ok(index.render("Done indexing."));
  } 
}

VenueTask:

public class VenueIndexTask implements Callable<Object> {

    private List<Long> idSubList;

    public VenueIndexTask(List<Long> idSubList){
        this.idSubList = idSubList;
        Logger.debug("Creating task which will index " + idSubList.size() + " items. " +
                "Range: " + rangeAsString() + ".");
    }

    @Override
    public Object call() throws Exception {
        List<Venue> venues = DbService.getVenuesForIds(idSubList);
        Logger.debug("Doing some indexing: "+venues.size());

        for(Venue venue : venues) {
            venue.index();
        }
        return null;
    }
    private String rangeAsString() {
        return "[" + idSubList.get(0) + "-" + idSubList.get(idSubList.size() - 1) + "]";
    }
}

Venue:

@IndexType(name = "venue")
public class Venue extends Index {

    private String name;

    // Find method static for request
    public static Finder<Venue> find = new Finder<Venue>(Venue.class);

    public Venue() {
    }

    public Venue(String id, String name) {
        super.id = id;
        this.name = name;
    }

    @Override
    public Map toIndex() {
        HashMap map = new HashMap();
        map.put("id", super.id);
        map.put("name", name);
        return map;
    }

    @Override
    public Indexable fromIndex(Map map) {
        if (map == null) {
            return this;
        }
        this.name = (String) map.get("name");
        return this;
    }
}

So all you Akka people out there go nuts! And please do as much as you can, propose cool futures functionality that could be used or any other knowledge/code that I could use to learn this stuff.

How I like to think of Akka (or any other message based systems) is to think like a conveyor belt, like in factories. A simplified way of thinking in Actors could be taking a pizza Order.

  • You, the hungry customer (Actor/Role) sends a order (A Message) to Pizza Shop

  • Customer service (Actor/Role) takes your order, gives you the order number (Future)

  • If you were impatient, you might've waited on the phone/internet/shop till you got your pizza (A synchronous/blocking transaction) otherwise you would be happy with the order number an check up on it later (non-blocking)

  • Customer service sends the message to the Chefs (Actor) under the supervision of Kitchen Manager (Actor). This is a very process heavy kitchen, with hierarchy. Akka likes that. See Supervision

  • Chef creates a new Pizza and attaches the details of the order (A new message) and passes that to the delivery boy (Actor) via the delivery manager (Supervisor Actor).

  • During this process, your order details haven't changed, that would be a nightmare. You would not be happy if you had pepperoni if you wanted plain cheese! All messages should be immutable! However, it may be that the message might be different for different actors. A delivery boy would expect a Pizza and the order details attached, the chef would expect an order. When a message needs to change, a new message is created.

  • Each actor is good at one role, how effective would it be if one guy had to do all the tasks? It may be that some actors out number others (eq 10 threads for Chefs, 2 for Delivery boys, 1 Customer Service).

  • Blocking behavior is a pain, imagine customer service is waiting for the chef and delivery boy before seeing the next customer?

Hopefully I've helped you a little, this is a huge topic and large change of mind. Good luck

Coursera currently runs a course on reactive programming which has the 3 last lectures on Akka and the actor model. This includes video lectures and homework (in Scala though not Java). While you are too late to receive the full certificate, you can still join the course and just check the last three weeks.

https://class.coursera.org/reactive-001/class

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM