Utiliser InfluxDB avec Java

Utiliser InfluxDB avec Java

1. Vue d'ensemble

InfluxDB is a high-performance store for time-series data. Il prend en charge l'insertion et l'interrogation en temps réel des données via un langage de requête de type SQL.

Dans cet article d’introduction, nous allons montrer comment se connecter à un serveur InfluxDb, créer une base de données, écrire des informations sur les séries chronologiques, puis interroger la base de données.

2. Installer

Pour nous connecter à la base de données, nous devons ajouter une entrée à notre fichierpom.xml:


    org.influxdb
    influxdb-java
    2.8

La dernière version de cette dépendance peut être trouvée surMaven Central.

Nous aurons également besoin d'une instance InfluxDB. Les instructions pourdownloading and installing a database se trouvent sur le site Web deInfluxData.

3. Connexion à un serveur

3.1. Créer une connexion

La création d'une connexion à la base de données nécessite de transmettre une URLString et des informations d'identification utilisateur à une fabrique de connexions:

InfluxDB influxDB = InfluxDBFactory.connect(databaseURL, userName, password);

3.2. Vérification de la connexion

Communications with the database are performed over a RESTful API, donc ils ne sont pas persistants.

L'API offre un service «ping» dédié pour confirmer que la connexion est fonctionnelle. Si la connexion est bonne, la réponse contient une version de la base de données. Sinon, il contient“unknown”.

Donc, après avoir créé une connexion, nous pouvons le vérifier en faisant:

Pong response = this.influxDB.ping();
if (response.getVersion().equalsIgnoreCase("unknown")) {
    log.error("Error pinging server.");
    return;
}

3.3. Création d'une base de données

La création d'une base de données InfluxDB est similaire à la création d'une base de données sur la plupart des plateformes. But we need to create at least one retention policy before using it.

A retention policy tells the database how long a piece of data should be stored. Les séries temporelles, telles que les statistiques du processeur ou de la mémoire, ont tendance à s'accumuler dans de grands ensembles de données.

Une stratégie typique pour contrôler la taille des bases de données de séries chronologiques estdownsampling. Les données «brutes» sont stockées à un taux élevé, résumées puis supprimées au bout d’un court laps de temps.

Retention policies simplify this by associating a piece of data with an expiration time. InfluxData a unin-depth explanation sur leur site.

Après avoir créé la base de données, nous ajouterons une règle unique nomméedefaultPolicy.. Elle conservera simplement les données pendant 30 jours:

influxDB.createDatabase("example");
influxDB.createRetentionPolicy(
  "defaultPolicy", "example", "30d", 1, true);

Pour créer une politique de rétention, nous aurons besoin d'unname, thedatabase, aninterval,areplication factor (qui devrait être 1 pour une base de données à instance unique), et unboolean indiquant qu'il s'agit d'une politique par défaut.

3.4. Définition d'un niveau de journalisation

En interne, l'API InfluxDB utiliseRetrofit et expose une interface à la fonction de journalisation de Retrofit, via unlogging interceptor.

Nous pouvons donc définir le niveau de journalisation en utilisant:

influxDB.setLogLevel(InfluxDB.LogLevel.BASIC);

Et maintenant, nous pouvons voir les messages lorsque nous ouvrons une connexion et lui envoyons un ping:

Dec 20, 2017 5:38:10 PM okhttp3.internal.platform.Platform log
INFO: --> GET http://127.0.0.1:8086/ping

Les niveaux disponibles sontBASIC,FULL,HEADERS etNONE.

4. Ajout et récupération de données

4.1. Points

Nous sommes maintenant prêts à commencer à insérer et à récupérer des données.

L'unité d'information de base dans InfluxDB est unPoint, qui est essentiellement un horodatage et une carte clé-valeur.

Jetons un coup d'œil à un point contenant les données d'utilisation de la mémoire:

Point point = Point.measurement("memory")
  .time(System.currentTimeMillis(), TimeUnit.MILLISECONDS)
  .addField("name", "server1")
  .addField("free", 4743656L)
  .addField("used", 1015096L)
  .addField("buffer", 1010467L)
  .build();

Nous avons créé une entrée contenant troisLongs comme statistiques de mémoire, un nom d'hôte et un horodatage.

Voyons comment l'ajouter à la base de données.

4.2. Rédaction de lots

Time series data tends to consist of many small points, and writing those records one at a time would be very inefficient. La méthode préférée consiste à collecter les enregistrements en lots.

L'API InfluxDB fournit un objetBatchPoint:

BatchPoints batchPoints = BatchPoints
  .database(dbName)
  .retentionPolicy("defaultPolicy")
  .build();

Point point1 = Point.measurement("memory")
  .time(System.currentTimeMillis(), TimeUnit.MILLISECONDS)
  .addField("name", "server1")
  .addField("free", 4743656L)
  .addField("used", 1015096L)
  .addField("buffer", 1010467L)
  .build();

Point point2 = Point.measurement("memory")
  .time(System.currentTimeMillis() - 100, TimeUnit.MILLISECONDS)
  .addField("name", "server1")
  .addField("free", 4743696L)
  .addField("used", 1016096L)
  .addField("buffer", 1008467L)
  .build();

batchPoints.point(point1);
batchPoints.point(point2);
influxDB.write(batchPoints);

Nous créons unBatchPoint puis y ajoutonsPoints. Nous avons défini l'horodatage de notre deuxième entrée sur 100 millisecondes dans le passé, car les horodatages constituent un index principal. Si nous envoyons deux points avec le même horodatage, un seul sera conservé.

Notez que nous devons associerBatchPoints à une base de données et à une politique de rétention.

4.3. Écrire un à la fois

Le traitement par lots peut s'avérer peu pratique pour certains cas d'utilisation.

Activons le mode batch avec un seul appel à une connexion InfluxDB:

influxDB.enableBatch(100, 200, TimeUnit.MILLISECONDS);

Nous avons activé le traitement par lots de 100 pour insertion dans le serveur ou envoi de ce qu'il contient toutes les 200 millisecondes.

Lorsque le mode de traitement par lots est activé, nous pouvons toujours en écrire un à la fois. Cependant, une configuration supplémentaire est requise:

influxDB.setRetentionPolicy("defaultPolicy");
influxDB.setDatabase(dbName);

De plus, nous pouvons maintenant écrire des points individuels et ils sont collectés par lots par un fil de fond:

influxDB.write(point);

Before we enqueue individual points, we need to set a database (similaire à la commandeuse en SQL)and set a default retention policy. Par conséquent, si nous souhaitons profiter du sous-échantillonnage avec plusieurs politiques de rétention, la création de lots est la voie à suivre.

Le mode Batch utilise un pool de threads séparé. C'est donc une bonne idée de le désactiver lorsqu'il n'est plus nécessaire:

influxDB.disableBatch();

La fermeture de la connexion entraînera également la fermeture du pool de threads:

influxDB.close();

4.4. Mappage des résultats de la requête

Les requêtes renvoient unQueryResult, que nous pouvons mapper aux POJO.

Avant d'examiner la syntaxe de la requête, créons une classe contenant nos statistiques de mémoire:

@Measurement(name = "memory")
public class MemoryPoint {

    @Column(name = "time")
    private Instant time;

    @Column(name = "name")
    private String name;

    @Column(name = "free")
    private Long free;

    @Column(name = "used")
    private Long used;

    @Column(name = "buffer")
    private Long buffer;
}

La classe est annotée avec@Measurement(name = “memory”), correspondant auxPoint.measurement(“memory”) que nous avons utilisés pour créer nosPoints.

Pour chaque champ de nosQueryResult, nous ajoutons l'annotation@Column(name = “XXX”) avec le nom du champ correspondant.

QueryResults sont mappés à des POJO avec unInfluxDBResultMapper.

4.5. Interroger InfluxDB

Utilisons donc notre POJO avec les points que nous avons ajoutés à la base de données dans notre lot à deux points:

QueryResult queryResult = connection
  .performQuery("Select * from memory", "example");

InfluxDBResultMapper resultMapper = new InfluxDBResultMapper();
List memoryPointList = resultMapper
  .toPOJO(queryResult, MemoryPoint.class);

assertEquals(2, memoryPointList.size());
assertTrue(4743696L == memoryPointList.get(0).getFree());

La requête illustre comment notre mesure nomméememory est stockée sous la forme d'une table dePoints à partir de laquelle nous pouvonsselect.

InfluxDBResultMapper accepte une référence àMemoryPoint.class avec lesQueryResult et renvoie une liste de points.

Après avoir mappé les résultats, nous vérifions que nous en avons reçu deux en vérifiant la longueur desList que nous avons reçus de la requête. Nous examinons ensuite la première entrée de la liste et voyons la taille de la mémoire libre du deuxième point inséré. The default ordering of query results from InfluxDB is ascending by timestamp.

Changeons cela:

queryResult = connection.performQuery(
  "Select * from memory order by time desc", "example");
memoryPointList = resultMapper
  .toPOJO(queryResult, MemoryPoint.class);

assertEquals(2, memoryPointList.size());
assertTrue(4743656L == memoryPointList.get(0).getFree());

L'ajout deorder by time desc inverse l'ordre de nos résultats.

Les requêtes InfluxDB sont très similaires à SQL. Il existe un guide de référence completon their site.

5. Conclusion

Nous nous sommes connectés à un serveur InfluxDB, avons créé une base de données avec une politique de rétention, puis inséré et récupéré des données sur le serveur.

Le code source complet des exemples estover on GitHub.