Skip to content

Concepts

This page presents the concepts used in Stork. When using Stork in a managed environment, such as Quarkus, all these concepts are hidden, as you only configure the lookup and selection. However, when using the programmatic API, you will use these concepts directly.

concepts

Process overview

When using the programmatic API of Stork, you:

  1. Retrieve the singleton Stork instance. This instance is configured with the set of Service it manages.
  2. Retrieve the Service you want to use. Each Service is associated with a name.
  3. Retrieve the ServiceInstance which will provide the metadata to access the actual service.

concepts

Behind the scenes, Stork will handle the service lookup and selection.

Note

The service lookup and selection are asynchronous operations. Thus, the API returns instances of Uni.

Stork

io.smallrye.stork.Stork is the entry-point of the API. The Stork instance is a singleton. It needs to be initialized once (when the application starts) and shutdown when the application stops:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
package examples;

import io.smallrye.stork.Stork;

public class StorkEntryPointExample {

    public static void main(String[] args) {
        Stork.initialize();
        Stork stork = Stork.getInstance();
        // ...
        Stork.shutdown();
    }

}

During the initialization, Stork looks for io.smallrye.stork.config.ConfigProvider SPI provider and retrieves the list of managed services:

  • A service is identified by a name.
  • A service has a service discovery configuration indicating how Stork will look for service instances
  • A service can have a load-balancer configuration indicating how Stork can select the most appropriate instance.

Service

A io.smallrye.stork.Service is the structure representing a service used by the application. Services are pre-configured with their name, service discovery, and optionally, their load-balancer. You retrieve a Service using the Stork#getService(String name) method.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
package examples;

import io.smallrye.stork.Service;
import io.smallrye.stork.Stork;

public class StorkServiceExample {

    public static void main(String[] args) {
        Stork.initialize();
        Stork stork = Stork.getInstance();

        Service service = stork.getService("my-service");

        // ...
        Stork.shutdown();
    }

}

The Service lets you retrieve the list of ServiceInstance, or select a single one, when a load-balancer is configured.

Service Instance

The io.smallrye.stork.ServiceInstance represents an actual instance of the service. It provides the metadata to configure a client to interact with that specific instance of service.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package examples;

import io.smallrye.stork.Service;
import io.smallrye.stork.ServiceInstance;
import io.smallrye.stork.Stork;

import java.time.Duration;
import java.util.List;

public class StorkServiceLookupExample {

    public static void main(String[] args) {
        Stork.initialize();
        Stork stork = Stork.getInstance();

        Service service = stork.getService("my-service");
        List<ServiceInstance> instances = service.getServiceInstances()
                .await().atMost(Duration.ofSeconds(5));

        // ...
        Stork.shutdown();
    }

}

The service selection is a two-steps process:

  1. Service lookup - using the service discovery
  2. Service selection - using the load balancer
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package examples;

import io.smallrye.stork.Service;
import io.smallrye.stork.ServiceInstance;
import io.smallrye.stork.Stork;

import java.time.Duration;

public class StorkServiceSelectionExample {

    public static void main(String[] args) {
        Stork.initialize();
        Stork stork = Stork.getInstance();

        Service service = stork.getService("my-service");
        ServiceInstance instance = service.selectServiceInstance()
                .await().atMost(Duration.ofSeconds(5));

        System.out.println(instance.getHost() + ":" + instance.getPort());

        // ...
        Stork.shutdown();
    }

}

Service Discovery

The io.smallrye.stork.ServiceDiscovery represents a service discovery mechanism, such as DNS, Consul, or Eureka.

You can implement a custom service discovery for Stork by implementing the ServiceDiscoveryProvider interface and register it with the Service Provider Interface (SPI) mechanism.

Please note that the ServiceDiscovery implementation must be non-blocking.

Load Balancer

The io.smallrye.stork.LoadBalancer represents a load-balancer strategy, such as round-robin.

To implement a custom load balancer for Stork, implement the LoadBalancerProvider interface and register it with the Service Provider Interface (SPI) mechanism.

Please note that the LoadBalancer implementation, similarly to ServiceDiscovery must be non-blocking.