Why akka




















How would it work on a single Akka Cluster? First of all, Akka Cluster requires seed nodes. Those are the initial contact points which other nodes will be joining. When you are deploying a microservice number 18, then which one is it going to join? We have seen scenarios where dedicated services were created, with a sole purpose of being seeds for other services. In such a scenario your services are tightly coupled, and nothing can be in practice deployed, when the special Seed Node service is down.

If you are using Kubernetes, Mesos or other similar systems, then Akka Management extensions allow to manage seeds discovery automatically for you. Each of the Akka Cluster node has a specific current state assigned. When the node is being intentionally shut down, then you make sure it notifies the cluster about that fact.

So what happens in case in which you shut down half of your microservices in the cluster? Well, it may consider this as a split brain. It may conclude it is a network partition and depending on the algorithm of a Split Brain Resolver the result may be that the remaining working part will get shut down, assuming that second part of the cluster is working and containing the majority. Be aware that all of the services in the cluster are tied by the cluster state, so you need to make sure that lifecycle related operations are properly executed.

Akka Cluster has a setting named Auto-Downing, making the unreachable nodes go automatically directly to status down. However it is not recommended to use it in the production environment especially when you are using Cluster Singleton, Sharding or Akka Persistence.

However, with single Akka Cluster it is not so simple. All nodes must be binary compatible! This concerns not only Akka versions in all of the services, but also Scala and Java versions if you are still using java serialization you shouldn't. Having the requirement of compatible Akka versions often leads to the creation of the common project. Many people consider sharing code between services as an anti-pattern.

As a result, threads are what really drive execution: In summary : Objects can only guarantee encapsulation protection of invariants in the face of single-threaded access, multi-thread execution almost always leads to corrupted internal state. Every invariant can be violated by having two contending threads in the same code segment. While locks seem to be the natural remedy to uphold encapsulation with multiple threads, in practice they are inefficient and easily lead to deadlocks in any application of real-world scale.

Locks work locally, attempts to make them distributed exist, but offer limited potential for scaling out. The illusion of shared memory on modern computer architectures Programming models of the 80''s conceptualize that writing to a variable means writing to a memory location directly which somewhat muddies the water that local variables might exist only in registers.

In summary : There is no real shared memory anymore, CPU cores pass chunks of data cache lines explicitly to each other just as computers on a network do. Inter-CPU communication and network communication have more in common than many realize.

Passing messages is the norm now be it across CPUs or networked computers. Instead of hiding the message passing aspect through variables marked as shared or using atomic data structures, a more disciplined and principled approach is to keep state local to a concurrent entity and propagate data or events between concurrent entities explicitly via messages.

The illusion of a call stack Today, we often take call stacks for granted. It will propagate to the exception handler of the worker thread completely ignoring who the actual "caller" was: This is a serious problem. In summary: To achieve any meaningful concurrency and performance on current systems, threads must delegate tasks among each other in an efficient way without blocking. Failures become part of the domain model. Concurrent systems with work delegation needs to handle service faults and have principled means to recover from them.

Even if loss does not happen, a response might be delayed arbitrarily due to previously enqueued tasks a long queue , delays caused by garbage collection, etc. How the actor model meets the needs of concurrent, distributed systems As described in the sections above, common programming practices cannot properly address the needs of modern concurrent and distributed systems. In particular, we would like to: Enforce encapsulation without resorting to locks.

Use the model of cooperative entities reacting to signals, changing state and sending signals to each other to drive the whole application forward. Stop worrying about an executing mechanism which is a mismatch to our world view. The actor model accomplishes all of these goals. The following topics describe how. Usage of message passing avoids locking and blocking Instead of calling methods, actors send messages to each other. In this way, actors actually achieve the execution we imagined for objects: An important difference of passing messages instead of calling methods is that messages have no return value.

This happens automatically without using locks: In summary, this is what happens when an actor receives a message: The actor adds the message to the end of a queue. If the actor was not scheduled for execution, it is marked as ready to execute. A hidden scheduler entity takes the actor and starts executing it. Actor picks the message from the front of the queue. Actor modifies internal state, sends messages to other actors. The actor is unscheduled. To accomplish this behavior, actors have: A Mailbox the queue where messages end up.

A Behavior the state of the actor, internal variables etc. Messages pieces of data representing a signal, similar to method calls and their parameters. An Execution Environment the machinery that takes actors that have messages to react to and invokes their message handling code. An Address more on this later. This is a very simple model and it solves the issues enumerated previously: Encapsulation is preserved by decoupling execution from signaling method calls transfer execution, message passing does not.

There is no need for locks. Modifying the internal state of an actor is only possible via messages, which are processed one at a time eliminating races when trying to keep invariants. There are no locks used anywhere, and senders are not blocked.

Millions of actors can be efficiently scheduled on a dozen of threads reaching the full potential of modern CPUs. Task delegation is the natural mode of operation for actors. State of actors is local and not shared, changes and data is propagated via messages, which maps to how modern memory hierarchy actually works. In many cases, this means transferring over only the cache lines that contain the data in the message while keeping local state and data cached at the original core.

Actors handle error situations gracefully Since we have no longer a shared call stack between actors that send messages to each other, we need to handle error situations differently. There are two kinds of errors we need to consider: The first case is when the delegated task on the target actor failed due to an error in the task typically some validation issue, like a non-existent user ID.

In this case, the service encapsulated by the target actor is intact, it is only the task that itself is erroneous. The service actor should reply to the sender with a message, presenting the error case.

There is nothing special here, errors are part of the domain and hence become ordinary messages. The second case is when a service itself encounters an internal fault. NET enforces that all actors are organized into a tree-like hierarchy, i. This is very similar how operating systems organize processes into a tree. Just like with processes, when an actor fails, its parent actor is notified and it can react to the failure.

Also, if the parent actor is stopped, all of its children are recursively stopped, too. This service is called supervision and it is central to Akka. By decomposing state into many discrete Actors, the model can introduce challenges for applications that require global consistency.

To address this problem, Akka uses Software Transactional Memory STM , which makes it possible to modify the state of many objects at once, reverting all changes if the transaction fails. Since the introduction of Akka, the project has attracted a tremendous community of users and contributors. In the past year, Akka has matured with a rich and cohesive set of modules that can be composed to solve a wide variety of business requirements.

Now, as part of the Typesafe Stack , we intend to take Akka to the next level with enterprise grade features and supporting commercial services. We have big plans for Akka. This is just the beginning. And we look forward to partnering with the rest of the team at Typesafe to write the next chapter in software development. Read the full report.



0コメント

  • 1000 / 1000