Silky Microservice FrameworkSilky Microservice Framework
Home
Docs
Config
Source
github
gitee
  • 简体中文
  • English
Home
Docs
Config
Source
github
gitee
  • 简体中文
  • English
  • Startup

    • Silky Framework Source Code Analysis
    • Host Construction
    • Service Engine
    • Module System
    • Service & Service Entry Resolution
    • Service Registration
    • Dependency Injection Conventions
    • RPC Service Proxy
  • Runtime

    • Endpoints & Routing
    • Executor Dispatch System
    • Local Executor & Server-Side Filters
    • Remote Executor & RPC Call Chain
    • RPC Server Message Handling
    • Service Governance
    • Cache Interceptor
    • Distributed Transactions (TCC)
    • HTTP Gateway Pipeline
    • Filter Pipeline
    • Polly Resilience Pipeline
    • Endpoint Health Monitor

Overview

The Executor is the core dispatch component when a service entry is invoked. It decides whether the current request should be handled by the local instance or forwarded via RPC to another service instance.

ComponentInterfaceDefault ImplementationResponsibility
Unified entry pointIExecutorDefaultExecutorDispatches by ServiceEntry / ServiceEntryDescriptor
Local executorILocalExecutorDefaultLocalExecutorResolves local implementation, runs server filter pipeline + business method
Remote executorIRemoteExecutorDefaultRemoteExecutorBuilds RPC message, applies Polly policies, sends via DotNetty

IExecutor — Unified Dispatch Entry

DefaultExecutor routes calls to the correct execution path:

public class DefaultExecutor : IExecutor
{
    // When ServiceEntry is available (IsLocal flag already determined):
    public async Task<object> Execute(ServiceEntry serviceEntry, object[] parameters, string serviceKey = null)
    {
        // serviceEntry.Executor is a pre-built delegate that captures the local/remote decision
        return await serviceEntry.Executor(serviceKey, parameters).ConfigureAwait(false);
    }

    // When only ServiceEntryDescriptor is available (no local impl — always remote):
    public async Task<object> Execute(ServiceEntryDescriptor serviceEntryDescriptor,
        IDictionary<ParameterFrom, object> parameters, string serviceKey)
    {
        var remoteExecutor = EngineContext.Current.Resolve<IRemoteExecutor>();
        return await remoteExecutor.Execute(serviceEntryDescriptor, parameters, serviceKey).ConfigureAwait(false);
    }
}

ServiceEntry.Executor — Local/Remote Decision Delegate

ServiceEntry builds its Executor delegate at construction time:

// Inside ServiceEntry constructor
Executor = CreateExecutor();

private Func<string, object[], Task<object>> CreateExecutor()
{
    return IsLocal
        ? CreateLocalExecutor()   // local: delegates to ILocalExecutor
        : CreateRemoteExecutor(); // remote: delegates to IRemoteExecutor
}

IsLocal is true if the current assembly contains a non-abstract implementation class for the service interface. Once set at startup, it does not change at runtime.


Local Execution Path

ServiceEntry.Executor (IsLocal = true)
    │
    ▼
DefaultLocalExecutor.Execute()
    │  Resolve implementation instance (by serviceKey for multi-impl routing)
    │
    ▼
IServerLocalInvokerFactory.CreateInvoker()
    │  Build LocalInvoker with server filter chain
    │
    ▼
LocalInvoker.InvokeAsync()
    │  Run server filter pipeline → invoke business method
    │
    ▼
Return result

See Local Executor & Server-Side Filters for details.


Remote Execution Path

ServiceEntry.Executor (IsLocal = false)
    │
    ▼
DefaultRemoteExecutor.Execute()
    │  Build RemoteInvokeMessage
    │
    ▼
IInvokePolicyBuilder.Build()
    │  Compose Polly policy: Timeout → Retry → CircuitBreaker → Fallback
    │
    ▼
policy.ExecuteAsync( IRemoteCaller.InvokeAsync() )
    │  1. Find healthy endpoints for target service
    │  2. Select endpoint by load balancing strategy
    │  3. Get/reuse DotNetty TransportClient
    │  4. Run client filter pipeline
    │  5. Send RPC message, await response
    │
    ▼
Parse response, return result

See Remote Executor & RPC Call Chain for details.


IInvokeTemplate — Direct Cross-Service Calls

For scenarios where you only have a ServiceEntryDescriptor (not a full ServiceEntry), IInvokeTemplate provides a programmatic API for calling any service entry by ID:

var result = await _invokeTemplate.InvokeAsync<OrderDto>(
    serviceEntryId: "IOrderAppService.GetByIdAsync.id.GET",
    parameters: new Dictionary<ParameterFrom, object>
    {
        [ParameterFrom.Path] = new { id = 42 }
    });

This always routes through IRemoteExecutor.

Edit this page
Prev
Endpoints & Routing
Next
Local Executor & Server-Side Filters