Runtime architecture
Orleans presents a location-transparent grain reference, an abstraction introduced in the Orleans virtual actor research paper, but the runtime implements each call using several independently replaceable or failure-aware subsystems. The central invariant is that a grain identity is stable while its activation location is temporary.
Host composition
Section titled “Host composition”A silo is a .NET Generic Host with Orleans services registered through .NET dependency injection. SiloHostedService starts and stops Silo, which drives the ordered silo lifecycle. The default registration set composes:
MessageCenterfor network connections, routing, forwarding, gateways, and dispatch.MembershipTableManager,MembershipAgent,ClusterHealthMonitor, andClusterMembershipServicefor membership.LocalGrainDirectory,GrainLocator, andCachedGrainLocatorfor activation location.PlacementServiceand keyed placement directors for new activation selection.ActivationDirectory,Catalog,ActivationData, andActivationCollectorfor local activation ownership.InsideRuntimeClientfor invoking local targets and producing responses.DeploymentLoadPublisherand environment statistics for placement and overload decisions.
See DefaultSiloServices for the composition root and Silo plus its implementation for lifecycle orchestration.
An external client has no activation catalog or placement service. ClusterClient starts an OutsideRuntimeClient, discovers gateways, maintains gateway connections, and sends requests through a client MessageCenter. A silo also embeds a runtime client, but its InsideRuntimeClient can dispatch directly to local activations and system targets.
A request through the runtime
Section titled “A request through the runtime”- The source generator emits a proxy method and an invokable request type for each grain interface method.
- The proxy passes the invokable to
GrainReferenceRuntime. Outgoing call filters can inspect or replace the invocation. - The runtime creates a
Message, assigns its correlation identity and target grain, registers a response callback, and sends it throughMessageCenter. - A client sends through a gateway. A silo can route directly to the target silo when the activation address is known.
- The receiving
MessageCenterresolves the activation address. A cache hit can avoid a directory round trip. A stale address can be invalidated and rerouted. - If no activation exists, the directory and
PlacementServicecoordinate creation on a compatible silo. Catalogcreates anActivationData; activation runs before queued application requests are dispatched.ActivationDataplaces the request on the activation scheduler. Incoming call filters and the generated invoker execute the grain method.InsideRuntimeClientcreates a response or rejection. The response follows the original correlation identity to the waiting callback.
The relevant implementations are GrainReferenceRuntime, OutsideRuntimeClient, MessageCenter, Catalog, and InsideRuntimeClient.
System targets
Section titled “System targets”System targets are addressable runtime components which use Orleans messaging and single-threaded scheduling without virtual activation. The runtime constructs them at explicit silo addresses. Membership services, persistent stream pulling agents, and activation balancing protocols use system targets because they need the messaging and scheduling model but must not be location-transparent virtual actors.
Unlike a grain, a system target:
- has a concrete silo location;
- is created and registered by runtime code;
- is not activated by placement or grain-directory lookup; and
- participates in runtime lifecycle rather than application grain lifecycle.
Consistency boundaries
Section titled “Consistency boundaries”Orleans does not implement one global transaction across these subsystems. Each boundary has a narrower contract:
- The membership table serializes membership updates into monotonically ordered views.
- The directory coordinates a grain identity with an activation address and repairs stale registrations.
- The activation scheduler serializes synchronous work items for one activation.
- Messaging correlates a request with a response but cannot infer whether a timed-out request executed.
- Persistence and streams define their own durability and acknowledgement points.
Understanding those boundaries is essential when extending the runtime. A custom directory changes location consistency, not membership. A placement director chooses where a new activation starts, not how calls are scheduled. A stream adapter defines queue acknowledgement, not grain-call exactly-once semantics.
Public extension surfaces
Section titled “Public extension surfaces”Prefer supported extension points over replacing internal runtime types:
- IPlacementDirector and placement filters customize candidate selection.
- IGrainDirectory supplies a named grain directory.
- serializer codecs, copiers, activators, and converters extend wire handling.
- stream queue adapters, mappers, balancers, caches, and failure handlers extend persistent streams.
- IProviderBuilder<T> integrates configuration-driven providers.
- lifecycle participants order provider startup and shutdown.
Internal names and algorithms are not compatibility guarantees. Public APIs, analyzer warnings, and documented wire identities are the compatibility boundaries.
