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

Concept

When a Silky microservice host starts, one of its most critical tasks is publishing its service metadata to the registry — so that other microservices in the cluster can discover it and establish RPC connections.

Silky models a service host as a Server object (also called a "service provider"):

PropertyDescription
HostNameEqual to the startup assembly name
EndpointsAll endpoints (RPC, HTTP, WebSocket) this host exposes
ServicesAll service descriptors this host implements

DefaultServerProvider

DefaultServerProvider (implements IServerProvider) assembles the Server descriptor:

public class DefaultServerProvider : IServerProvider
{
    private readonly IServer _server;
    private readonly IServiceManager _serviceManager;

    public DefaultServerProvider(IServiceManager serviceManager, ISerializer serializer)
    {
        _serviceManager = serviceManager;
        _server = new Server(EngineContext.Current.HostName);
    }

    // Called when the host supports DotNetty RPC
    public void AddRpcServices()
    {
        var rpcEndpoint = EndpointHelper.GetLocalRpcEndpoint(); // local IP + RPC port
        _server.Endpoints.Add(rpcEndpoint);

        var rpcServices = _serviceManager.GetLocalService(ServiceProtocol.Rpc);
        foreach (var rpcService in rpcServices)
        {
            _server.Services.Add(rpcService.ServiceDescriptor);
        }
    }

    // Called when the host exposes HTTP endpoints
    public void AddHttpServices()
    {
        var webEndpoint = RpcEndpointHelper.GetLocalWebEndpoint();
        _server.Endpoints.Add(webEndpoint);
    }

    // Called when the host exposes WebSocket endpoints
    public void AddWsServices()
    {
        var wsEndpoint = RpcEndpointHelper.GetWsEndpoint();
        _server.Endpoints.Add(wsEndpoint);

        var wsServices = _serviceManager.GetLocalService(ServiceProtocol.Ws);
        foreach (var wsService in wsServices)
        {
            _server.Services.Add(wsService.ServiceDescriptor);
        }
    }
}

Registration to the Registry

After DefaultServerProvider.GetServer() produces the complete ServerDescriptor, it is written to the registry (Zookeeper / Nacos / Consul) during module Initialize().

Distributed Lock Protection

To prevent multiple instances starting simultaneously and racing to write the same service route data, a distributed lock is acquired before writing:

// Pseudo-code of the registration process
using (await _distributedLock.AcquireAsync(lockKey, timeout))
{
    var existingDescriptor = await _registryClient.GetServerDescriptor(hostName);
    var merged = MergeOrReplace(existingDescriptor, newDescriptor);
    await _registryClient.SetServerDescriptor(merged);
}

Service Route Record Structure

The service route record written to the registry contains:

{
  "HostName": "OrderService",
  "Endpoints": [
    { "Host": "192.168.1.10", "Port": 2200, "ServiceProtocol": "Rpc" }
  ],
  "Services": [
    {
      "Id": "IOrderAppService",
      "ServiceEntries": [
        { "Id": "IOrderAppService.GetAsync.id.GET", "Router": "GET /api/order/{id}" }
      ]
    }
  ]
}

Route Synchronization

After initial registration, route information stays synchronized with the registry through:

  • Heartbeat: Periodic writes to the registry to refresh TTL (prevents stale entries)
  • Subscription: Each node subscribes to registry change events and updates its local in-memory route table on any change

This ensures that when a new microservice instance starts (or an instance dies), all other nodes in the cluster see the updated topology within seconds.

Edit this page
Prev
Service & Service Entry Resolution
Next
Dependency Injection Conventions