Actors & Actor Systems as massively distributed scalability architecture

Volodymyr Pavlyshyn
9 min readMay 13, 2023

--

In my last article, we talk about monolith and alternatives to microservices.

One of the most significant disadvantages of monoliths is the scalability and limits of a single machine.

Let's take a look at the architecture that give an alternative way to build scalable and distributed systems. That applies to IoT, frontend apps, backend systems, and distributed world.

Actor Model of Computation

The Actor Model of Computation is a mathematical model of concurrent computation that treats “actors” as the universal primitives of concurrent computation. It was first proposed by Carl Hewitt, Peter Bishop, and Richard Steiger in 1973. Here are the main ideas:

  1. Actors: In the model, actors are computational entities that can make local decisions, create more actors, send more messages, and determine how to respond to the next message received. Actors can communicate with each other, but they do not share state. Instead, they influence each other’s state only through messages.
  2. Asynchronous Message Passing: Actors communicate through asynchronous message passing, meaning the sender doesn’t wait for the message to be received or processed. This enables high levels of concurrency, as actors can process their tasks without waiting for others.
  3. Concurrency and Decentralization: Each actor operates independently and concurrently, making decisions based on its local state and the messages it receives. This decentralization allows for highly distributed and parallel systems.
  4. Non-Shared State: Each actor has its private state, which is not accessible to other actors. This prevents data race conditions, making the model suitable for robust and safe concurrent programming.
  5. Mailboxes and Scheduling: Messages sent to an actor are stored in a mailbox until the actor can process them. The model doesn’t specify the scheduling policy, meaning it doesn’t define the order in which messages should be processed.
  6. Creation and Supervision of Actors: An actor can create other actors. In many actor-based systems, parent actors supervise their children, restarting or stopping them if they fail.

These principles allow the Actor Model to handle challenges of concurrent computation, like synchronization and race conditions, more efficiently. However, it’s also a high-level model, and real-world implementation often requires additional mechanisms, such as methods for locating actors and for managing system resources.

Simple Mental Model

The main power of actors is a simple mental and cognitive model that simplifies distributed and concurrent development under the same umbrella.

Actor can

  • Receive and process message
  • Send Message
  • Change an internal state and behavior based on the message
  • Create new Actors

Every actor could do one operation per cycle

Thats it !!!

References & Address != Actor

One more quite powerful concept for most actor systems — the actor is reachable via address. So you work not with instances of the actor but with actor addresses. This separation opens the possibility of creating distributed and semi-decentralized systems and gives abstraction that allows introducing of remote actors and the development a network of actors.

Remote Actors

This concept is a key part of distributed computing, and it’s essential for building scalable, resilient, and responsive systems.

  1. Location Transparency: This is the principle that an actor should be able to send a message to another actor without knowing or caring about its physical location (whether it’s on the same machine or a different one). This makes it easier to design systems because you can focus on the logic of interaction between actors without worrying about the details of network communication.
  2. Message Passing: Like local actors, remote actors communicate through asynchronous message passing. The system needs to ensure that messages can be serialized (converted into a format that can be transmitted over a network) and deserialized (converted back into a format that the receiving actor can understand).
  3. Network Errors: In a distributed system, network errors are a fact of life. The actor model needs to be extended with strategies for dealing with these errors. For example, if a message can’t be delivered because the network is down, should it be retried or discarded? Should the sender be notified of the failure?
  4. Distributed Supervision: In a distributed actor system, supervision (monitoring of child actors by their parents) can also be distributed. If a remote actor fails, its supervisor can decide whether to restart, replace, or stop it altogether.
  5. Routing and Location: In a distributed system, there needs to be a way to locate remote actors. This could be as simple as a registry of actor addresses or involve more complex routing logic.
  6. Security: Messages between remote actors need to be encrypted, and systems may need to authenticate actors to ensure they are who they say they are.

Remote actors are key to many actor-based frameworks, such as Akka in the Scala programming language. They make building systems that scale across multiple machines possible, taking full advantage of modern multi-core and cloud-based environments.

OTP Erlang Actors

Here are the main architectural ideas in OTP:

  1. Processes: In Erlang, “process” is used instead of “actor”. Processes in Erlang are lightweight (not to be confused with OS-level processes) and do not share memory. They communicate by sending and receiving asynchronous messages, just like actors in the Actor Model.
  2. Supervision Trees: OTP introduces the concept of supervision trees, where processes are organized hierarchically. A supervisor process monitors their child's operations and can restart them if they fail. This creates a fault-tolerant system where errors can be isolated, and recovery can be managed systematically.
  3. Behaviours: OTP defines a set of standard “behaviours” (essentially design patterns) that most concurrent programs can follow. For example, a GenServer (Generic Server) is a module that implements a common pattern for a server process in a client-server relationship. Behaviors separate the generic part of the code (which is part of the behavior module) from the specific part (which is part of the callback module), making the code easier to understand and maintain.
  4. Applications: In OTP, an application is a component implementing some specific functionality, consisting of a collection of processes and supervision trees. Applications are packaged so they can be run and stopped as a unit and re-used in other systems. Applications can also be configured to start other applications as dependencies, allowing for the creation of complex, modular systems.
  5. Releases: A release in OTP is a packaged system version, including Erlang/OTP itself, all applications, and all configurations necessary to run the system. This makes deploying the system to a target machine easier since everything needed is included in the release.
  6. Hot Code Swapping: Erlang/OTP supports hot code swapping, meaning you can change the code of a running system without stopping it. This is extremely useful for systems that require high availability.
  7. Built-In Support for Distribution: Erlang/OTP has built-in support for distributed programming. Processes can communicate transparently, whether on the same machine or different devices.

These ideas form the foundation of Erlang/OTP’s architecture, making it a robust and powerful tool for building distributed, fault-tolerant systems.

Virtual Actors

In Erlang, actor has an instance, but some architectures go to a more interesting concept of Virtual actors.

One of the most resent Virtual actors frameworks is Orlean

Orleans is a framework developed by Microsoft Research that simplifies building distributed, high-scale computing applications in the cloud. It introduces the Virtual Actor Model, an approach that extends the traditional Actor Model with an automatic actor lifecycle.

Here are the main ideas of Orleans and the Virtual Actor Model:

  1. Virtual Actors: In Orleans, all actors, called grains, are “virtual”. This means they are always available, even if not in memory. The runtime automatically instantiates, activates, and deactivates grains as needed. This simplifies the programming model because developers do not need to worry about managing the lifecycle of actors.
  2. Grains: Grains are the fundamental units of computation and state in Orleans. They are similar to actors in the traditional Actor Model, but with the added benefits of the Virtual Actor Model. Each grain has a unique identity and encapsulates its own state and behavior.
  3. Single-threaded Execution: Each grain processes requests one at a time in a single-threaded manner. This removes the need for locks and simplifies concurrent programming. If a grain is busy processing a request, the Orleans runtime will automatically queue incoming requests.
  4. Automatic Distribution: Orleans automatically distributes grains across a cluster of machines. This enables applications to scale out easily and take advantage of the resources in a cloud environment.
  5. Persistence: Orleans provides built-in support for grain state persistence. Developers can choose when to write state back to storage, and Orleans handles the complexities of reading and writing state.
  6. Fault Tolerance: If a machine in the cluster fails, Orleans automatically re-activates the grains that were running on that machine on other machines. This provides a high level of resilience.
  7. Timers and Reminders: Orleans provides built-in support for timers (which call a grain method after a certain delay) and reminders (which call a grain method at specified intervals). This simplifies the process of performing periodic or delayed work.

The Orleans framework and the Virtual Actor Model are designed to simplify distributed system development, making it easier to build scalable, reliable, and maintained applications.

WASM Cloud

Wasm Cloud is a secure, distributed actor system built for cloud, edge, and IoT environments. It leverages webassembly’s security and portability features to create a new approach to building and deploying cloud-native applications.

Here are the main ideas:

  1. Actors: In Wasm Cloud, the main unit of computation is the actor, similar to the Actor Model of Computation. Each actor is a WebAssembly module that can handle multiple requests and maintain an internal state. The actor’s code is sandboxed and can only interact with the outside world through defined interfaces.
  2. Capabilities: Wasm Cloud uses capability-based security, which means that each actor can only access the resources (like a file system, a database, or an HTTP client) that it has been explicitly granted permission to. These resources are provided by capability providers, which are also WebAssembly modules.
  3. Contracts: Both actors and capability providers adhere to contracts defined as WebAssembly interface types (WIT). Contracts specify the types of requests and responses that can be exchanged between actors and capability providers.
  4. NATS: Wasm Cloud uses NATS, a high-performance messaging system, for communication between different parts of the system. This allows for a highly distributed, loosely coupled architecture.
  5. Portability and Scalability: Since all components are WebAssembly modules, they can be run anywhere that WebAssembly can be run, from tiny IoT devices to cloud servers. Wasm Cloud can dynamically scale actors and capability providers based on demand.
  6. Security: WebAssembly’s sandboxing features provide a high level of security. Each actor is isolated from others and can only communicate through defined interfaces. The capability-based security model further restricts what resources each actor can access.

So with WASM cloud, you could create polyglot actors that compiled to a wasm, and the team gets complete freedom on tools and implementation as same as deployment patterns.

Rust and Actors

The rust community has a lot of high-performance actor systems.

One more interesting actor scalable project

Actors for UI and Javascript

The powerful combination of Actors and statecharts. Model first approach

Server Less and Actors

Actor systems are more flexible as a Serverless lambda and have a more complex model with supervision, but we could see lambdas as some variant of actors.

Lambda functions can be seen as “actors” in a system. Still, it’s important to note that the Actor Model and serverless functions like AWS Lambda are different paradigms, and they solve different kinds of problems.

Here’s how you could think of Lambda functions as actors:

  1. Statelessness: Each invocation of a Lambda function is stateless, similar to how each actor processes one message at a time and changes its internal state. However, unlike actors, Lambda functions do not maintain their state between invocations. Any state that needs to persist between invocations would need to be stored in a separate service, like a database or a cache.
  2. Concurrency: Lambda functions can run concurrently, similar to how actors can process messages concurrently. Each instance of a Lambda function handles one event and runs independently of other models.
  3. Message Passing: Lambda functions are triggered by events, which can be seen as a form of message passing. The event data is passed as input to the Lambda function.
  4. Isolation: Each Lambda function is isolated from other functions. They do not share memory or CPU, similar to how actors do not share state.
  5. Asynchronicity: Lambda functions can be invoked asynchronously. The invoker sends a request and continues its work without waiting for a response.

However, remember that while there are similarities, Lambda functions, and actors are different and are used for different purposes. Lambda functions are generally used for stateless, short-lived tasks and are part of the broader serverless architecture paradigm. The Actor Model, on the other hand, is more often used for building concurrent, distributed, and fault-tolerant systems.

The future

I big fan of Alan Key idea of Software Internet and the Big Idea of small talk, where an Application is composed of actor-like objects that communicate via messages. This Interface and mental models empower Plato's idea that the whole has the same properties as parts and unlocks composability.

I am keen to see Actor Systems in the space of the globally interconnected decentralized mesh

References

--

--

Volodymyr Pavlyshyn
Volodymyr Pavlyshyn

Written by Volodymyr Pavlyshyn

I believe in SSI, web5 web3 and democratized open data.I make all magic happens! dream & make ideas real, read poetry, write code, cook, do mate, and love.

No responses yet