Thespian Actor Framework
repository·master·Indexed 18 days ago
https://github.com/thespianpy/thespianAn actor-based framework for Python providing distributed computing capabilities, including actor management, automatic scaling, and environment orchestration. Features include Actor Troupes for parallel operations, multi-system conventions for distributed communication, fault tolerance with atomic messaging, and dynamic capability-based deployment. Supports loadable sources for updating actor code without restarting the system.
What's inside Thespian
- Thespian is a framework implementing the Actor model for Python applications. It provides the infrastructure necessary for building systems composed of independent, communicating entities called Actors. It was originally developed at GoDaddy to manage large-scale server environments and has since been open-sourced for general use.
Avoid periodic failures in Actor-based applications
masterThe Act 2 example demonstrates a pattern to solve periodic failures (such as missing updates or unexpected actor creation) that occur during startup handshakes.
Instead of using non-deterministic delays (like
time.sleep()) or making actors ephemeral, this example uses a message-passing pattern:Include the destination address (e.g., the address of an
Analyzer) directly within the request message (e.g.,EncodeThis). This allows the sender to provide the routing information immediately. The system will automatically delay the message until the target actor is ready, ensuring a deterministic startup without manual synchronization.Reuse existing Actors using globalName
masterTo prevent the creation of an entirely new set of Actors every time an application is run, use aglobalNamewhen creating the primary entry point Actor (such as anAcceptor). By assigning a specificglobalName, Thespian can re-use the existing set of running Actors instead of spawning new processes.Understand Actor hierarchy and termination behavior
masterIn Thespian, killing a parent Actor causes all of its child Actors to be killed as well.
If you kill the primary entry point Actor (e.g., the
Acceptor), all downstream child processes (likeAnalyzerorEncoderactors) will also be terminated. Because theglobalNameis no longer associated with a running process, the next time the application is invoked, Thespian will create a completely new instance of the Actor hierarchy.Configure Multi-System Actor Environments with Capabilities
masterThespian supports multi-system configurations where multiple Actor Systems run independently (often on different network nodes). You can define specific capabilities for each system to control which Actors run where.
Actors can specify their requirements using the
@requireCapabilitysyntax. An Actor will only run in a system that possesses a matching set of capabilities. This allows for:- Targeted Deployment: Ensuring specific encoders (e.g., Morse, Base64, Rot13) run on systems equipped with the necessary hardware or software.
- Fault Tolerance and Failover: By creating systems with overlapping capabilities, if one system fails, Actors can be automatically recreated in another system that meets their requirements.
In this example setup, systems communicate via an administrator port. The first system started on port
1900acts as the convention leader.# Example of starting systems with specific capabilities $ python start.py 1900 $ python start.py 10000 "morse,Caesar cipher" $ python start.py 10101 "64bit encoder"Handle child actor failures with ChildActorExited messages
masterIn Thespian, when a child actor exits, its parent actor receives a
ChildActorExitedmessage. You can use this message to perform cleanup or state management, such as removing the exited child's address from a tracking dictionary. This allows the parent to detect the failure and restart the child when a new request arrives.Additionally, when an actor is being killed, it receives an
ActorExitRequestmessage. You can intercept this message within your actor to perform shutdown or cleanup operations before the actor terminates.Design for fault tolerance using atomic messaging
masterTo build resilient, self-healing Actor-based applications, favor atomic messaging.
Instead of relying on an Actor's internal state to hold partial information for a multi-step request, pass all the information required to process a request within a single message. This ensures that if an actor (like an
Analyzer) is killed and restarted, the new instance can immediately process subsequent requests using the information provided in the message, without needing to recover lost state.Use loadable sources for dynamic code updates
masterThespian supports a 'loadable source' feature that allows you to update running Actor code without restarting the Actor System. This is achieved by loading a ZIP file containing updated source code into a running system.
Workflow
- Create a source package: Package your updated Python sources into a
.zipfile. - Load the sources: Use a loading mechanism to inject the ZIP into a running Actor System. This returns a unique source hash.
- Instantiate Actors: When calling
createActor(), pass the returned source hash to ensure the Actor is instantiated from that specific version of the code.
Key Concepts
- Source Authority: To support dynamic loading, a special Actor must register itself as the
Source Authority. When new sources are loaded, they are passed to this Actor for validation (e.g., checking digital signatures) or decryption. Thespian only allows Actor creation from a source once the Source Authority has validated it. - Side-by-side Versions: Multiple versions of sources can exist in a system simultaneously. Old source hashes continue to work, allowing old Actors to finish processing requests while new requests are directed to new versions. This enables zero-downtime updates.
- Automatic Remote Distribution: If you load sources into one Actor System, those sources are automatically propagated to any remote Actor System that attempts to create an Actor using that specific source hash.
# Conceptual usage when creating an actor from a specific loaded source # The source_hash is obtained from the load operation actor_ref = system.createActor(MyActorClass, name='my_actor', sourceHash='a3ad084f02e92c6a2e3eb70e5d72a6c2')- Create a source package: Package your updated Python sources into a
How Thespian Multi-System Conventions work
masterMultiple Thespian systems can communicate as part of a "convention". In this architecture, a Convention Leader handles all registration, resulting in a star topology for the convention.
Convention management is handled entirely by Thespian, meaning it has little to no impact on standard Actor development. However, Actors can optionally participate in Convention-related events.
Manage Actor System Lifecycle and Capabilities
masterYou can manage the lifecycle of Actor Systems and their capabilities dynamically without restarting the entire application.
Starting Systems
Use
start.pywith the following arguments:port: The port number for the system's administrator.capabilities: A comma-separated list (no whitespace) of capabilities to assign to the system.
Stopping Systems
Use
stop.pyto shut down specific Actor Systems. By default, it targets port1900. You can pass additional port numbers to shut down multiple systems.Dynamic Capability Updates
You can add or remove capabilities from a running system using a utility like
chgcap.py. When a capability is removed, Thespian re-checks all running Actors in that system. If an Actor's@requireCapabilityspecification is no longer met by the system's new capability set, the Actor is automatically shut down.chgcap.pyusage:python chgcap.py <port> <+/-> <"capability name"># Start a system on port 10000 with specific capabilities $ python start.py 10000 "morse,Caesar cipher" # Add a capability to system 10101 $ python chgcap.py 10101 + morse # Remove a capability from system 10101 $ python chgcap.py 10101 - "64bit encoder" # Stop multiple systems $ python stop.py 1900 10000 10101Run the Multi-System Example
masterThe example consists of three main lifecycle scripts:
start.pyto initialize the Actor System,app.pyto execute the application logic, andstop.pyto clean up.When running these scripts, you can provide an optional first argument to specify the system base (e.g.,
multiprocTCPBaseormultiprocUDPBase).# 1. Start the Actor System (defaults to multiprocTCPBase) python start.py multiprocUDPBase # 2. Run the application (pass message via stdin) echo "Hello, World!" | python app.py multiprocUDPBase # 3. Stop the Actor System and all Actors python stop.py multiprocUDPBaseShutdown Actor Systems
masterWhen finished with your multi-system test, use
stop.pyto shut down the specified Actor Systems.$ python stop.py <port1> <port2> <port3>$ python stop.py 10101 10000 1900