DOCX

Make it easier concurrent and fault-tolerant Akka sample tutorial

By Marjorie Cruz,2015-07-17 22:19
30 views 0
Make it easier concurrent and fault-tolerant Akka sample tutorial

    Make it easier: concurrent and fault-tolerant Akka sample

    tutorial

    To write concurrent programs is difficult.Programmers have to deal with threads, locks, and race conditions, etc., this process is very easy to get wrong, and will cause the program code difficult to read, testing and maintenance.

    So, a lot of people don't tend to use multithreaded programming.Instead, they use a single threaded process (translator note: contains only one thread process), dependent on external services (such as database, queue, etc.) needed for processing concurrent or asynchronous operations.Although this method is feasible in some cases, but there are many other things won't work.Many real-time systems, such as trade or bank business application, or real-time games - wait for a single thread process is complete is luxury (they need immediate answer!).Some of the other system of very high demand for computing or resources, if without introducing parallel mechanism in the process will take a long time (in some cases can reach a few hours or days).

    A common method of single thread (for example, inNode.jsEvent-based, widely used) is used in a non-blocking mode (Event - -based, NON - Blocking lot, lot of also have translation custom).Although this method can avoid the context switch, lock and block, can really improve performance, but still cannot solve the concurrent use of multiple processors (need to start and the coordination of multiple independent processors).

    So, does this mean that in order to build a concurrent program, in addition to go deep into the threads, locks, and have no other choice than a race condition?

    Thank Akka framework, it provides us with a choice.This tutorial introduces the Akka example and study how it can help and simplify the realization of the distributed concurrent applications.

    Akka framework is what

    This article introduces the Akka and study how it can help and simplify the implementation of distributed concurrent application.

    AkkaIs the JVM (JAVA virtual machine, similarly hereinafter) platform to build high concurrency, distributed and fault-tolerant application toolkit and runtime.Akka withThe Scala languageWritten, at the same time provides the Scala and JAVA development interface.

    Akka processing method based on concurrentActor (no idiomatic translation, this paper use the original word) model.In system based on the Actor, all things are the Actor, as if in object-oriented design all things are objects.But there is one important difference between - particularly relevant to our discussion - that is the Actor model is a model of concurrent

    design and architecture, and the object-oriented model is not.A little bit more specific, in Scala Actor system, actors interact with each other and share information but not the interaction in order to make the default.Mechanism of sharing information between the Actor and a task is messaging.

    Create and thread scheduling, receiving and distribution of messages and handles all the complexity, race conditions and synchronization are delegated to the framework, the framework of process corresponding to said to be transparent.

    Akka in multiple between the Actor and the system set up a hierarchy (Layer), as a result, the Actor only needs to process the message.Create and thread scheduling, receiving and distribution of messages and handles all the complexity, race conditions and synchronization are delegated to the framework, the framework of process corresponding to said to be transparent.

    The Actor strictly abide by theReactive statement.Responsive application goal is to satisfy the following one or more conditions instead of the traditional multi-threading application:

    ; Event driven.With the Actor, the code can perform non-blocking asynchronous request is

    processed and exclusive operation.

    ; Scalability.In Akka, adding nodes without modifying code is possible, thank you for messaging

    and local Transparency (Location Transparency).

    ; High elasticity.Any application will encounter errors and failure at some point in time.Akka

    "regulation" (fault tolerance) strategy for the realization of the self-healing system provides the

    convenience.

    ; The response type.Today's high performance and quick response applications require quick

    feedback to the customer, so for incident response need to be very timely.Akka non-blocking,

    based on message strategy can help to achieve this goal.

    Akka actors of is what

    The Actor is essentially receives the message and take action to handle the message object.It is decoupled from the source, only responsible for the correct identification to receive the message type, and take appropriate action.

    After receiving a message, an Actor may take the following one or more actions:

    ; To perform some operation itself (for example to calculate, persistent data, invoke external Web

    services, etc.)

    ; The message or forward the message to another Actor

    ; Instantiate a new Actor and forward the message to it

    Or, if the Actor thinks fit, can be completely ignored the news (that is, it may choose not to response).

    In order to realize an Actor. We need to inherit Akka actors. The Actor the Trait (generally translated as "features", translation has some disputes, in this paper, we retain the original word) and implement the Receive method.When a message is sent to the Actor, it's the Receive method (Akka) call.Typical implementation including the use of Pattern Matching (Pattern Matching) to identify the message type and respond, see the following Akka example:

    import akka.actor.Actor

    import akka.actor.Props

    import akka.event.Logging

    class MyActor extends Actor {

     def receive = {

     case value: String => doSomething(value)

     case _ => println("received unknown message")

     }

    }

    Pattern matching is a relatively refined processing messages technology, compared based on the realization of the callback, tend to produce "cleaner" and the code is easier to browse.For example, consider a simplified version of the HTTP request/response.

    First, we use the JavaScript callback based way implementation:

    route(url, function(request){

     var query = buildQuery(request);

     dbCall(query, function(dbResponse){

     var wsRequest = buildWebServiceRequest(dbResponse);

     wsCall(wsRequest, function(wsResponse) {

     sendReply(wsResponse);

     });

     });

    });

Now, we put it and the realization of the based on pattern matching compare:

msg match {

     case HttpRequest(request) => {

     val query = buildQuery(request)

     dbCall(query)

     }

     case DbResponse(dbResponse) => {

     var wsRequest = buildWebServiceRequest(dbResponse);

     wsCall(dbResponse)

     }

     case WsResponse(wsResponse) => sendReply(wsResponse)

    }

    Although based on callback JavaScript code is more compact, but it is more difficult to read and browse.Based on pattern matching, by contrast, the code for the need to consider what kind of situation, each situation is how to deal with writing more clear.

    The Actor system

    The problem of a complicated constantly break down into smaller subproblems is usually a reliable technology to solve the problem.This method is especially effective for computer science (andSingle responsibility principle), because it is easy to produce clean and modular code, generate little or no redundancy, and it is relatively easy to maintain.

    In based on the design of the Actor, the use of this technology will help Actor logical organization into a hierarchical structure, also is the so-calledThe Actor system.The Actor system provides a basic framework, using this system can interact between actors.

    Inside the Akka, the only way in which and the Actor communication is through ActorRef.ActorRef represents a reference of the Actor, can prevent other objects directly access or operate the Actor inside information and status.Messages can be through a ActorRef one of the following grammar agreement sent to an Actor:

    -!(" inform ") - send a message and return immediately

    -?(" request ") - send a message and return a Future object, representing a possible response

    Each Actor has an inbox, used to receive email messages.Inbox has a variety of way can choose, the default implementation is first in first out (FIFO) queue.

    When dealing with multiple messages, an Actor contain multiple instance variables to keep fit.Akka run every instance Actor in his own lightweight threads, and ensure to deal with only one message at a time.As a result, developers don't have to worry about synchronization or race conditions, and the condition that each Actor can be keep in a reliable way.

    Akka Actor in the API provides useful information for each of the actors perform tasks needed:

    ; Sender: the current processing the message sender an ActorRef references

    ; Context: the Actor run contextual information and methods (including, for example, instantiate a

    new method of Actor ActorOf)

    ; SupervisionStrategy: define strategy used to recover from errors

    ; The self: the Actor's own ActorRef references

    Akka run every instance Actor in his own lightweight threads, and ensure to deal with only one message at a time.As a result, developers don't have to worry about synchronization or race conditions, and the condition that each Actor can be keep in a reliable way.

    In order to set up these tutorials, let's consider a simple example: statistics the number of words in a text file.

    In order to achieve the purpose of demonstration Akka example, we put the problem is decomposed into two subtasks;Namely (1) statistics of the number of words in a row "children" tasks, and (2) summary of these special words quantity, get file "father" of the total task.

    Father the Actor will be loaded from a file each line, and then commissioned a child Actor to calculate the number of words a row.When the Actor is completed, it will get results with message sent back to the parent of the Actor.Father Actor will receive each line () words amount of news and maintain a the whole word file of the total number of counters, after completion of the counter will be returned to the caller.

    (note that the following offer Akka tutorial example just to teaching purpose, so did not take into consideration all the boundary conditions, performance optimization, etc. At the same time, complete can be compiled version of the code examples can be found in the GIST) Let's first look at a subclass StringCounterActor example implementation:

    case class ProcessStringMsg(string: String)

    case class StringProcessedMsg(words: Integer)

    class StringCounterActor extends Actor {

     def receive = {

     case ProcessStringMsg(string) => {

     val wordsInLine = string.split(" ").length

     sender ! StringProcessedMsg(wordsInLine)

     }

     case _ => println("Error: message not recognized")

     }

    }

    The Actor has a very simple mission: to receive ProcessStringMsg messages (including

    a line of text), calculating the number of words in the line of text, and the results through a

    StringProcessedMsg message is returned to the sender.Please note that we have achieved our

    classes, use!StringProcessedMsg word (" inform ") method (issued a message and return

    immediately).

    Ok, now let's focus on the parent WordCounterActor class: case class StartProcessFileMsg()

     class WordCounterActor(filename: String) extends Actor {

     private var running = false

     private var totalLines = 0

     private var linesProcessed = 0

     private var result = 0

     private var fileSender: Option[ActorRef] = None

     def receive = {

     case StartProcessFileMsg() => {

     if (running) {

     // println just used for example purposes;

     // Akka logger should be used instead

     println("Warning: duplicate start message received")

     } else {

     running = true

     fileSender = Some(sender) // save reference to process invoker

     import scala.io.Source._

     fromFile(filename).getLines.foreach { line =>

     context.actorOf(Props[StringCounterActor]) ! ProcessStringMsg(line)

     totalLines += 1

     }

     }

     }

     case StringProcessedMsg(words) => {

     result += words

     linesProcessed += 1

     if (linesProcessed == totalLines) {

     fileSender.map(_ ! result) // provide result to process invoker

     }

     }

     case _ => println("message not recognized!")

     }

     }

    There are many details, we come to author investigates (note the discussion the referenced line number based on the above code sample).

    First of all, please pay attention to deal with the structure of the file name are passed to the WordCounterActor method (line 3).This means that the Actor will only be used to deal with a separate file.By avoiding the reset state variables (running, totalLines, linesProcessed and result) also simplify the coding of developers, because the instance is only used once (that is a separate file), and then thrown away.

    Next, we see WordCounterActor dealt with two types of messages:

    ; StartProcessFileMsg (line 12)

    o WordCounterActor in FileSender instance variables (note that this is an Option [ActorRef]

    rather than an Option [Actor]) to keep a reference of the sender.When dealing with the

    final StringProcessedMsg (received from a StringCounterActor subclass, as described

    below), in order to access and response, after the ActorRef is required.

    o Then WordCounterActor read the file, after every row in the file is loaded, it will create a

    StringCounterActor, need to process the message containing the text line will be passed to

    it (line 21-24).

    o From the initial startup WordCounterActor external Actor receives the message

    o After receiving this message, WordCounterActor first checks if it received a duplicate

    request

    o If the request is repeated, then WordCounterActor generates a warning, then don't do

    something else (line 16)

    o If this is not a repeat request:

    ; StringProcessedMsg (line 27)

    o When processing is complete lines, assigned to it from StringCounterActor receives the

    message

    o After the receipt of this message, WordCounterActor will increase the file of the line

    counter, if all the rows processed (that is, when totalLines equals linesProcessed), it will

    send the final result to the original FileSender line (28-31).

    Again, it is important to note that in Akka, the Actor is the only mechanism of communication between messaging.News is only thing that is Shared between the Actor and because multiple actors may be concurrent access to the same message, so to avoid a race condition and unpredictable behavior, message immutability is very important.

    Because Case Class is immutable by default and can be seamless integration and pattern matching, so in Case the Class in the form of a message, it is very common.(in Scala Case Class is normal Class, the only difference is through the pattern matching provides can be recursively decomposed mechanism).

    Let's run through the whole application example code to end this case. object Sample extends App {

     import akka.util.Timeout

     import scala.concurrent.duration._

     import akka.pattern.ask

     import akka.dispatch.ExecutionContexts._

     implicit val ec = global

     override def main(args: Array[String]) {

     val system = ActorSystem("System")

     val actor = system.actorOf(Props(new WordCounterActor(args(0))))

     implicit val timeout = Timeout(25 seconds)

     val future = actor ? StartProcessFileMsg()

     future.map { result =>

     println("Total number of words " + result)

     system.shutdown

     }

     }

    }

    Please note that here?Method is how to send a message.In this way, the caller can use the returnedFutureObject, when completed can print out the final results and eventually stop by the Actor system exit the program.

    Akka fault tolerant strategy and regulators

    Every Actor in the Actor system, are descendants of the regulators.If the Actor when processing messages fail, it will suspend themselves and their children and send a message to its regulators, usually in the form of exceptions.

    Inside the Akka, regulators strategy is to define your system fault tolerant behavior of the main and direct mechanism.

    Inside the Akka, a regulator for children from passing up abnormal response and handling strategy known as regulators.Regulators strategyIs to define your system fault tolerant behavior of the main and direct mechanism.

    There is an error when a message indicating reached a regulator, it will take one of the following actions:

    ; Restore children (and their descendants), maintain internal state.When there is no child's state

    destroyed by mistake, you can continue to work normally, you can use this strategy.

    ; Restart the children (and their descendants) to remove internal state.This strategy application

    scenarios and the first one is just the opposite.If a child's status has been destroyed by mistake, in

    the Future before it can be used to reset its internal state.

    ; Permanently stop the children (and their descendants).This strategy can be used in the following

    scenario: error conditions can not be fixed, but does not affect the execution of the operation, these

    operations can be in the child does not exist under the condition of complete failure.

    ; Stopped and spread up his mistakes.Applicable scenario: when regulators don't know how to

    handle errors, the error is passed to their supervisors.

Report this document

For any questions or suggestions please email
cust-service@docsford.com