MarginaliaSearch/code/common/service-discovery/readme.md
Viktor Lofgren 0307c55f9f (refac) Zookeeper for service-discovery, kill service-client lib (WIP)
To avoid having to either hard-code or manually configure service addresses (possibly several dozen), and to reduce the project's dependency on docker to deal with routing and discovery, the option to use [Zookeeper](https://zookeeper.apache.org/) to manage services and discovery has been added.

A service registry interface was added, with a Zookeeper implementation and a basic implementation that only works on docker and hard-codes everything.

The last remaining REST service, the assistant-service, has been migrated to gRPC.

This also proved a good time to clear out primordial technical debt from the root of the codebase.  The 'service-client' library has been taken behind the barn and given a last farewell.  It's replaced by a small library for managing gRPC channels.

Since it's no longer used by anything, RxJava has been removed as a dependency from the project.

Although the current state seems reasonably stable, this is a work-in-progress commit.
2024-02-20 11:41:14 +01:00

87 lines
3.2 KiB
Markdown

# 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](https://zookeeper.apache.org/),
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:
```java
// 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.
```java
registry.announceInstance(ServiceId.Test,
nodeId,
instanceUUID);
```
All of this is done automatically by the `Service` base class
in the [service](../service/) module.
To discover a service, the caller can query the registry:
```java
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
* [ServiceRegistryIf](src/main/java/nu/marginalia/service/discovery/ServiceRegistryIf.java)
* [ZkServiceRegistry](src/main/java/nu/marginalia/service/discovery/ZkServiceRegistry.java)
* [FixedServiceRegistry](src/main/java/nu/marginalia/service/discovery/FixedServiceRegistry.java)
## gRPC Channel Pool
* [GrpcChannelPoolFactory](src/main/java/nu/marginalia/service/client/GrpcChannelPoolFactory.java)
* [GrpcMultiNodeChannelPool](src/main/java/nu/marginalia/service/client/GrpcMultiNodeChannelPool.java)
* [GrpcSingleNodeChannelPool](src/main/java/nu/marginalia/service/client/GrpcSingleNodeChannelPool.java)