Overview
Service Governance is Silky's core mechanism for ensuring microservice reliability. The framework applies multi-layer Polly resilience policies on both the client (caller) side and server (provider) side:
- Timeout control: Prevents slow services from blocking callers
- Retry mechanism: Automatically retries on transient failures
- Circuit breaker: Prevents cascading failures (avalanche effect)
- Fallback (Degradation): Returns default results when circuit is open or all retries fail
- Load balancing: Determines which instance receives each request
- Concurrency guard: Limits max concurrent requests per instance
All governance parameters are managed through GovernanceOptions, supporting three-tier configuration: global defaults, interface-level overrides, and method-level overrides.
GovernanceOptions — Governance Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
ShuntStrategy | ShuntStrategy | Polling | Load balancing strategy |
TimeoutMillSeconds | int | 5000 | Call timeout in milliseconds |
EnableCachingInterceptor | bool | true | Enable cache interception |
EnableCircuitBreaker | bool | true | Enable circuit breaker |
ExceptionsAllowedBeforeBreaking | int | 3 | Consecutive failures before opening circuit |
BreakerSeconds | int | 60 | Duration the circuit stays open (seconds) |
RetryTimes | int | 3 | Max retry attempts |
RetryIntervalMillSeconds | int | 50 | Retry wait interval (ms) |
MaxConcurrentHandlingCount | int | 50 | Max concurrent requests on this instance (0 = unlimited) |
AddressFuseSleepDurationSeconds | int | 60 | Wait time after marking an endpoint unhealthy (seconds) |
UnHealthAddressTimesAllowedBeforeRemoving | int | 3 | Times unhealthy before removing endpoint from service list |
Tips
ProhibitExtranet (disallow external HTTP access) cannot be set in appsettings.yml. It must be applied via [Governance] or [ProhibitExtranet] on the interface or method only.
Three-Tier Configuration Priority
Governance parameters apply in priority order (higher overrides lower):
Method-level [Governance] attribute
> Interface-level [Governance] attribute (inherited by all methods)
> Global defaults (appsettings.yml Governance section)
Global Defaults (Config File)
Governance:
TimeoutMillSeconds: 10000
RetryTimes: 0
EnableCircuitBreaker: false
Interface / Method Level Override ([Governance] Attribute)
[ServiceRoute]
[Governance(TimeoutMillSeconds = 3000, EnableCircuitBreaker = false)] // Interface level
public interface IOrderAppService
{
// Method level: overrides interface level
[Governance(TimeoutMillSeconds = 500, ShuntStrategy = ShuntStrategy.HashAlgorithm)]
Task<OrderDto> GetByIdAsync(long id);
// Uses interface-level settings (3000ms timeout)
Task<OrderDto> CreateAsync(CreateOrderInput input);
}
The ReConfiguration() method applies attributes over global defaults during ServiceEntry construction.
Circuit Breaker State Machine
┌──────────────────────────────────────────────────────────────────────┐
│ │
│ Consecutive failures < ExceptionsAllowedBeforeBreaking │
│ ┌─────────────────────┐ │
│ ┌─────────│ CLOSED │─────────┐ │
│ │ │ (normal operation) │ │ │
│ │ └─────────────────────┘ │ │
│ Success│ │ N consecutive │
│ (stays │ │ failures │
│ closed)│ ▼ │
│ │ ┌─────────────────────┐ │ │
│ └─────────│ OPEN │◀────────┘ │
│ │ (refuses requests) │ │
│ └──────────┬──────────┘ │
│ │ After BreakerSeconds │
│ ▼ │
│ ┌─────────────────────┐ │
│ │ HALF-OPEN │ │
│ │ (allows 1 test call)│ │
│ └──────────┬──────────┘ │
│ │ Test call succeeds → CLOSED │
│ │ Test call fails → OPEN │
└──────────────────────────────────────────────────────────────────────┘
Warning
Business exceptions (e.g., ValidationException, BusinessException) do not trigger the circuit breaker. Only non-business infrastructure exceptions (network timeout, connection refused, etc.) count toward the failure threshold.
Fallback Attribute
[Fallback] specifies a degradation implementation for a service entry:
[ServiceRoute]
public interface IOrderAppService
{
[Fallback(typeof(OrderFallbackService))]
Task<GetOrderOutput> GetByIdAsync(long id);
}
// Fallback class — must implement the same interface
public class OrderFallbackService : IOrderAppService
{
public Task<GetOrderOutput> GetByIdAsync(long id)
=> Task.FromResult(new GetOrderOutput { Status = "Service Unavailable" });
// Other methods return default/throw NotImplementedException
}
The fallback is invoked when Polly's circuit breaker is open or all retry attempts are exhausted.
Concurrency Guard (MaxConcurrentHandlingCount)
On the server side, Silky tracks active concurrent requests per instance using an atomic counter. When the count exceeds MaxConcurrentHandlingCount:
- Server throws
OverflowMaxServerHandleException - Client's overflow retry policy (
OverflowServerHandleFailoverPolicyProvider) catches it and retries on a different endpoint - If all endpoints are full, the exception propagates to the caller
Set MaxConcurrentHandlingCount = 0 to disable the limit.
