Libraries¶
Drove is written in Java. We provide a few libraries that can be used to integrate with a Drove cluster.
Setup¶
Setup the drove version
<properties>
<!--other properties-->
<drove.version>1.30</drove.version>
</properties>
Checking the latest version
Latest version can be checked at the github packages page here
All libraries are located in sub packages of the top level package com.phonepe.drove
.
Java Version Compatibility
Using Drove libraries would need Java versions 17+.
Drove Model¶
The model library for the classes used in request and response. It has dependency on jackson
and dropwizard-validation
.
Dependency¶
<dependency>
<groupId>com.phonepe.drove</groupId>
<artifactId>drove-models</artifactId>
<version>${drove.version}</version>
</dependency>
Drove Client¶
We provide a client library that can be used to connect to a Drove cluster. The cluster accepts controller endpoints as parameter (among other things) and automatically tracks the leader controller. If a single controller endpoint is provided, this functionality is turned off.
Please note that the client does not provide specific functions corresponding to different api calls from the controller, it acts as a simple endpoint discovery mechanism for drove cluster. Please refer to API section for details on individual apis.
Transport¶
The transport layer in the client is used to actually make HTTP calls to the Drove server. A new transport can be used by implementing the get()
, post()
, put()
and delete()
methods in the DroveHttpTransport
interface.
By default Drove client uses Java internal HTTP client as a trivial transport implementation. We also provide an Apache Http Components based implementation.
Tip
Do not use the default transport in production. Please use the HTTP Components based transport or your custom ones.
Dependencies¶
<dependency>
<groupId>com.phonepe.drove</groupId>
<artifactId>drove-client</artifactId>
<version>${drove.version}</version>
</dependency>
<dependency>
<groupId>com.phonepe.drove</groupId>
<artifactId>drove-client-httpcomponent-transport</artifactId>
<version>${drove.version}</version>
</dependency>
Sample code¶
public class DroveCluster implements AutoCloseable {
@Getter
private final DroveClient droveClient;
public DroveCluster() {
final var config = new DroveConfig()
.setEndpoints(List.of("http://controller1:4000,http://controller2:4000"));
this.droveClient = new DroveClient(config,
List.of(new BasicAuthDecorator("guest", "guest")),
new DroveHttpComponentsTransport(config.getCluster()));
}
@Override
public void close() throws Exception {
this.droveClient.close();
}
}
RequestDecorator
This interface can be implemented to augment requests with special headers like for example Authorization, as well as for other stuff like adding content type etc etc.
Drove Event Listener¶
This library provides callbacks that can be used to listen and react to events happening on the Drove cluster.
Dependencies¶
<!--Include Drove client-->
<dependency>
<groupId>com.phonepe.drove</groupId>
<artifactId>drove-events-client</artifactId>
<version>${drove.version}</version>
</dependency>
Sample Code¶
final var droveClient = ... //build your java transport, client here
//Create and setup your object mapper
final var mapper = new ObjectMapper();
mapper.registerModule(new ParameterNamesModule());
mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
mapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS);
final var listener = new DroveRemoteEventListener(droveClient, //Create listener
mapper,
new DroveEventPollingOffsetInMemoryStore(),
Duration.ofSeconds(1));
listener.onEventReceived() //Connect signal handlers
.connect(events -> {
log.info("Remote Events: {}", events);
});
listener.start(); //Start listening
//Once done close the listener
listener.close();
Event Types
Please check the com.phonepe.drove.models.events
package for the different event types and classes.
Event Polling Offset Store
The event poller library uses polling to find new events based on an offset. The event polling offset store is used to store and retrieve this offset. The DroveEventPollingOffsetInMemoryStore
default store stores this information in-memory. Implement DroveEventPollingOffsetStore
to a more permanent storage if you want this to be more permanent.
Drove Hazelcast Cluster Discovery¶
Drove provides an implementation of the Hazelcast discovery SPI so that containers deployed on a drove cluster can discover each other. This client uses the token injected by drove in the DROVE_APP_INSTANCE_AUTH_TOKEN
environment variable to get sibling information from the controller.
Dependencies¶
<!--Include Drove client-->
<!--Include Hazelcast-->
<dependency>
<groupId>com.phonepe.drove</groupId>
<artifactId>drove-events-client</artifactId>
<version>${drove.version}</version>
</dependency>
Sample Code¶
//Setup hazelcast
Config config = new Config();
// Enable discovery
config.setProperty("hazelcast.discovery.enabled", "true");
config.setProperty("hazelcast.discovery.public.ip.enabled", "true");
config.setProperty("hazelcast.socket.client.bind.any", "true");
config.setProperty("hazelcast.socket.bind.any", "false");
//Setup networking
NetworkConfig networkConfig = config.getNetworkConfig();
networkConfig.getInterfaces().addInterface("0.0.0.0").setEnabled(true);
networkConfig.setPort(port); //Port is the port exposed on the container for hazelcast clustering
// Setup Drove discovery
JoinConfig joinConfig = networkConfig.getJoin();
DiscoveryConfig discoveryConfig = joinConfig.getDiscoveryConfig();
DiscoveryStrategyConfig discoveryStrategyConfig =
new DiscoveryStrategyConfig(new DroveDiscoveryStrategyFactory());
discoveryStrategyConfig.addProperty("drove-endpoint", "http://controller1:4000,http://controller2:4000"); //Controller endpoints
discoveryStrategyConfig.addProperty("port-name", "hazelcast"); // Name of the hazelcast port defined in Application spec
discoveryStrategyConfig.addProperty("transport", "com.phonepe.drove.client.transport.httpcomponent.DroveHttpComponentsTransport");
discoveryStrategyConfig.addProperty("cluster-by-app-name", true); //Cluster container across multiple app versions
discoveryConfig.addDiscoveryStrategyConfig(discoveryStrategyConfig);
//Create hazelcast node
val node = Hazelcast.newHazelcastInstance(config);
//Once connected, node.getCluster() will be non null
Peer discovery modes
By default the containers will only discover and connect to containers from the same application id. If you need to connect to containers from all versions of the same application please set the cluster-by-app-name
property to true
as in the above example.
Drove Apache Ignite Discovery¶
Drove provides an implementation of the apache ignite discovery so that containers deployed on a drove cluster can discover each other. This client uses the token injected by drove in the DROVE_APP_INSTANCE_AUTH_TOKEN
environment variable to get sibling information from the controller.
Dependencies¶
<!--Include Drove client-->
<!--Include apache ignite-->
<dependency>
<groupId>com.phonepe.drove</groupId>
<artifactId>drove-ignite-discovery</artifactId>
<version>${drove.version}</version>
</dependency>
Sample Code¶
//Setup ignite
IgniteConfigProvider igniteConfigProvider = new IgniteConfigProvider();
IgniteConfiguration igniteConfiguration = igniteConfigProvider.provideIgniteConfiguration(DroveIgniteConfig.builder()
.communicationPortName("igniteComm") // Communication port name
.droveEndpoint("http://controller1:4000,http://controller2:4000") //Controller endpoints
.useAppNameForDiscovery(true) //Cluster container across multiple app versions
.discoveryPortName("igniteDiscovery") // Discovery port name
.build());
// Start ignite
Ignite ignite = Ignition.start(configuration);
Peer discovery modes
By default the containers will only discover and connect to containers from the same application id. If you need to connect to containers from all versions of the same application please set the cluster-by-app-name
property to true
as in the above example.