MarginaliaSearch/code/common/service-discovery
Viktor Lofgren 746a865106 (client) Fix handling of channel refreshes
The previous code made an incorrect assumption that all routes refer to the same node, and would overwrite the route list on each update.  This lead to storms of closing and opening channels whenever an update was received.

The new code is correctly aware that we may talk to multiple nodes.
2024-02-20 14:14:09 +01:00
..
src (client) Fix handling of channel refreshes 2024-02-20 14:14:09 +01:00
build.gradle (refac) Zookeeper for service-discovery, kill service-client lib (WIP) 2024-02-20 11:41:14 +01:00
readme.md (refac) Zookeeper for service-discovery, kill service-client lib (WIP) 2024-02-20 11:41:14 +01:00

Service Discovery

Contains classes for helping services discover each other, and managing connections between them.

Service Registry

The service registry is a class that keeps track of the services that are currently running, and their connection information.

There are two implementations:

  • A simple implementation that effectively hard-codes the services. This is sufficient when running in docker, although loses some smart features. It is fundamentally incompatible with running the system bare-metal, and does not permit multiple instances of a service to run.

  • A more advanced implementation that is based on Zookeeper, which is a distributed coordination service. This implementation lets services register themselves and announce their liveness, and then discover each other. It supports multiple instances of a service running, and supports running the system bare-metal, where it will assign ports to the services from a range.

To be discoverable, the caller must first register their services:

// Register one or more services
registry.registerService(ApiSchema.GRPC,
                         ServiceId.Test,  
                         nodeId, 
                         instanceUUID, //must be unique to the runtime
                         "127.0.0.1"); // bind-address
// (+ any other services)

Then, the caller must announce their instance. Before this is done, the service is not discoverable.

registry.announceInstance(ServiceId.Test,
                          nodeId,
                          instanceUUID);

All of this is done automatically by the Service base class in the service module.

To discover a service, the caller can query the registry:

Set<InstanceAddress<?>> endpoints = registry.getEndpoints(ApiSchema.GRPC, ServiceId.Test, nodeId);

for (var endpoint : endpoints) {
    System.out.println(endpoint.getHost() + ":" + endpoint.getPort());
}

It's also possible to subscribe to changes in the registry, so that the caller can be notified when a service comes or goes, with registry.registerMonitor().

gRPC Channel Pool

From the GrpcChannelPoolFactory, two types of channel pools can be created that are aware of the service registry:

  • GrpcMultiNodeChannelPool - This pool permits 1-n style communication with partitioned services
  • GrpcSingleNodeChannelPool - This pool permits 1-1 style communication with non-partitioned services

The pools manage the lifecycle of the gRPC channels, and will permit the caller to access Stub interfaces for the services.

Central Classes

Service Registry

gRPC Channel Pool