Bibliothèque client Java permettant de communiquer avec un serveur de base de données via ses protocoles. L’implémentation actuelle ne prend en charge que l’interface HTTP.
La bibliothèque fournit sa propre API pour envoyer des requêtes à un serveur, ainsi que des outils pour travailler avec différents formats de données binaires (RowBinary* & Native*).
L’authentification par jeton d’accès nécessite de configurer le jeton d’accès en appelant L’authentification par certificat client SSL nécessite de définir le nom d’utilisateur, d’activer l’authentification SSL, de configurer un certificat client et une clé client en appelant respectivement
donnera la valeur L’application peut définir son propre en-tête HTTP ⚠️ Lorsque des options sont définies via la méthode Lorsque les options sont définies via la méthode ParamètresParamètresParamètresParamètresParamètresParamètresParamètresParamètresMéthodes de V2 Insertion de données au format TSV.
Configuration
- Maven Central (page du projet) : https://mvnrepository.com/artifact/com.clickhouse/client-v2
- Builds nocturnes (lien vers le dépôt) : https://central.sonatype.com/repository/maven-snapshots/
- Ancien dépôt Artifactory des builds nocturnes (lien vers le dépôt) : https://s01.oss.sonatype.org/content/repositories/snapshots/
- Maven
- Gradle (Kotlin)
- Gradle
Initialisation
L’objet Client est initialisé parcom.clickhouse.client.api.Client.Builder#build(). Chaque client possède son propre contexte et aucun objet n’est partagé entre eux.
Le Builder dispose de méthodes de configuration pour en simplifier la mise en œuvre.Exemple :showLineNumbers
Client est AutoCloseable et doit être fermé lorsqu’il n’est plus nécessaire.Authentification
L’authentification est configurée par client lors de la phase d’initialisation. Trois méthodes d’authentification sont prises en charge : par mot de passe, par jeton d’accès ou par certificat client SSL.L’authentification par mot de passe nécessite de renseigner le nom d’utilisateur et le mot de passe en appelantsetUsername(String) et setPassword(String) :showLineNumbers
setAccessToken(String) :showLineNumbers
setUsername(String), useSSLAuthentication(boolean), setClientCertificate(String) et setClientKey(String) :showLineNumbers
L’authentification SSL peut être difficile à dépanner en production, car de nombreuses erreurs provenant des bibliothèques SSL ne fournissent pas assez d’informations. Par exemple, si le certificat client et la clé ne correspondent pas, le serveur interrompra immédiatement la connexion (dans le cas de HTTP, cela se produira à l’étape d’établissement de la connexion, lorsqu’aucune requête HTTP n’est envoyée, donc aucune réponse n’est renvoyée).Veuillez utiliser des outils comme openssl pour vérifier les certificats et les clés :
- vérifier l’intégrité de la clé :
openssl rsa -in [key-file.key] -check -noout - vérifier que le certificat client a un CN correspondant pour un utilisateur :
- obtenir le CN à partir d’un certificat utilisateur -
openssl x509 -noout -subject -in [user.cert] - vérifier que la même valeur est définie dans la base de données
select name, auth_type, auth_params from system.users where auth_type = 'ssl_certificate'(la requête afficheraauth_paramsavec quelque chose comme{"common_names":["some_user"]})
- obtenir le CN à partir d’un certificat utilisateur -
Configuration
Tous les paramètres sont définis par des méthodes d’instance (aussi appelées méthodes de configuration) qui rendent explicites la portée et le contexte de chaque valeur. Les principaux paramètres de configuration sont définis dans une seule portée (client ou opération) et ne se substituent pas mutuellement.La configuration est définie lors de la création du client. Voircom.clickhouse.client.api.Client.Builder.Configuration du client
- Connexion & points de terminaison
- Authentification
- Délais d’expiration & nouvelle tentative
- Options de socket
- Compression
- SSL/Sécurité
- Proxy
- HTTP & en-têtes
- Paramètres du serveur
- Fuseau horaire
- Avancé
Identification du client
Le journal de requêtes contient deux champs permettant d’identifier l’application à l’origine d’une requête :client_name et http_user_agent. Le protocole TCP natif utilise
client_name pour identifier l’application. Le protocole HTTP utilise http_user_agent pour identifier l’application. Le builder client dispose de la méthode setClientName pour définir les valeurs correctes
pour les deux protocoles.
Le champ http_user_agent est défini selon le format standard de l’en-tête User-Agent : application-name[/version] [(operating-system; architecture; ...)].
Cet ensemble de valeurs est répété pour chaque couche : application, bibliothèque client, bibliothèque client HTTP. Ce qui est défini par la méthode setClientName apparaît en premier dans la liste.Par exemple :showLineNumbers
http_user_agent suivante :User-Agent pour s’identifier. Toutefois, la partie clickhouse-java-v2/0.9.6-SNAPSHOT sera ajoutée à la fin de l’en-tête.Identification des opérations
Le journal de requêtes dispose de deux autres champsquery_id et log_comment qui peuvent être utilisés pour identifier une opération et ajouter des informations supplémentaires au journal de requêtes.query_id est un identifiant unique d’une opération. Il peut être défini par l’application en appelant la méthode setQueryId de la classe QuerySettings.showLineNumbers
log_comment est un commentaire pouvant être ajouté au journal des requêtes. Il peut être défini par l’application en appelant la méthode logComment de la classe QuerySettings.showLineNumbers
Paramètres du serveur
Les paramètres côté serveur peuvent être définis au niveau du client une seule fois lors de sa création (voir la méthodeserverSetting du Builder) et au niveau de l’opération (voir serverSetting pour la classe de paramètres d’opération).showLineNumbers
setOption (que ce soit via Client.Builder ou la classe de paramètres d’opération), le nom des paramètres serveur doit être préfixé de clickhouse_setting_. La méthode com.clickhouse.client.api.ClientConfigProperties#serverSetting() peut s’avérer utile dans ce cas.En-tête HTTP personnalisé
Des en-têtes HTTP personnalisés peuvent être définis pour toutes les opérations (au niveau du client) ou pour une seule (au niveau de l’opération).showLineNumbers
setOption (que ce soit via Client.Builder ou la classe de paramètres d’opération), le nom du header personnalisé doit être préfixé de http_header_. La méthode com.clickhouse.client.api.ClientConfigProperties#httpHeader() peut s’avérer utile dans ce cas.Définitions courantes
ClickHouseFormat
Enum des formats pris en charge. Il inclut tous les formats supportés par ClickHouse.raw- l’utilisateur doit transcoder les données brutesfull- le client peut transcoder lui-même les données et accepte un flux de données brutes-- opération non prise en charge par ClickHouse pour ce format
API d’insertion
insert(String tableName, InputStream data, ClickHouseFormat format)
Accepte des données sous forme d’InputStream d’octets dans le format spécifié. data doit être encodé dans le format.SignaturestableName - un nom de table cible.data - un flux d’entrée de données encodées.format - le format dans lequel les données sont encodées.settings - paramètres de la requête.Valeur de retourFuture du type InsertResponse — résultat de l’opération et informations supplémentaires telles que les métriques côté serveur.ExemplesshowLineNumbers
insert(String tableName, List<?> data, InsertSettings settings)
Envoie une requête d’écriture vers la base de données. La liste des objets est convertie dans un format efficace, puis envoyée au serveur. La classe des éléments de la liste doit être enregistrée au préalable à l’aide de la méthoderegister(Class, TableSchema).SignaturestableName - nom de la table cible.data - objets DTO (Data Transfer Object) de la collection.settings - paramètres de la requête.Valeur de retourFuture du type InsertResponse — le résultat de l’opération et des informations supplémentaires telles que les métriques côté serveur.ExemplesshowLineNumbers
InsertSettings
Options de configuration pour les opérations d’insertion.Méthodes de configurationInsertResponse
Objet de réponse contenant le résultat de l’opération d’insertion. Il n’est disponible que si le client a reçu une réponse du serveur.Cet objet doit être fermé dès que possible pour libérer la connexion, car celle-ci ne peut pas être réutilisée tant que toutes les données de la réponse précédente n’ont pas été entièrement lues.
API de requête
query(String sqlQuery)
EnvoiesqlQuery tel quel. Le format de réponse est défini par les paramètres de la requête. QueryResponse contiendra une référence au flux de réponse qui doit être consommé par un lecteur pour le format pris en charge.SignaturessqlQuery - une instruction SQL unique. La requête est envoyée telle quelle au serveur.settings - paramètres de la requête.Valeur de retourFuture du type QueryResponse — un jeu de données résultant ainsi que des informations supplémentaires telles que les métriques côté serveur. L’objet Response doit être fermé après consommation du jeu de données.Exemplesquery(String sqlQuery, Map<String, Object> queryParams, QuerySettings settings)
EnvoiesqlQuery tel quel. Envoie également les paramètres de requête afin que le serveur puisse compiler l’expression SQL.SignaturessqlQuery - expression SQL avec des espaces réservés {}.queryParams - map de variables permettant de compléter l’expression SQL sur le serveur.settings - paramètres de la requête.Valeur de retourFuture du type QueryResponse — un jeu de données résultant ainsi que des informations supplémentaires telles que les métriques côté serveur. L’objet Response doit être fermé après consommation du jeu de données.ExemplesshowLineNumbers
queryAll(String sqlQuery)
Interroge des données au formatRowBinaryWithNamesAndTypes. Renvoie le résultat sous forme de collection. Les performances de lecture sont identiques à celles du lecteur, mais davantage de mémoire est nécessaire pour conserver l’intégralité du jeu de données.SignaturessqlQuery - expression SQL pour interroger des données depuis un serveur.Valeur de retourJeu de données complet représenté par une liste d’objets GenericRecord offrant un accès ligne par ligne aux données de résultat.ExemplesshowLineNumbers
QuerySettings
Options de configuration pour les opérations de requête.Méthodes de configurationQueryResponse
Objet de réponse contenant le résultat de l’exécution de la requête. Il n’est disponible que si le client a reçu une réponse du serveur.Cet objet doit être fermé dès que possible afin de libérer la connexion, car celle-ci ne peut pas être réutilisée tant que toutes les données de la réponse précédente n’ont pas été lues intégralement.
Exemples
- Le code d’exemple est disponible dans le dépôt
- Implémentation de référence du service Spring
API commune
getTableSchema(String table)
Récupère le schéma de la tabletable.Signaturestable - nom de la table pour laquelle les données de schéma doivent être récupérées.database - base de données dans laquelle la table cible est définie.Valeur de retourRenvoie un objet TableSchema contenant la liste des colonnes de la table.getTableSchemaFromQuery(String sql)
Récupère le schéma à partir d’une instruction SQL.Signaturessql - Instruction SQL “SELECT” dont le schéma doit être renvoyé.Valeur de retourRenvoie un objet TableSchema dont les colonnes correspondent à l’expression sql.TableSchema
register(Class<?> clazz, TableSchema schema)
Compile la couche de sérialisation et de désérialisation pour la classe Java à utiliser pour l’écriture et la lecture de données avecschema. La méthode crée un sérialiseur et un désérialiseur pour la paire getter/setter et la colonne correspondante.
La correspondance de colonne est déterminée en extrayant son nom à partir du nom de la méthode. Par exemple, getFirstName correspondra à la colonne first_name ou firstname.Signaturesclazz - Classe représentant le POJO utilisé pour lire/écrire des données.schema - Schéma de données à utiliser pour la mise en correspondance avec les propriétés POJO.ExemplesshowLineNumbers
Exemples d’utilisation
Le code des exemples complets est stocké dans un dossier ‘example` du dépôt :- client-v2 - principal ensemble d’exemples.
- demo-service - exemple d’utilisation du client dans une application Spring Boot.
- demo-kotlin-service - exemple d’utilisation du client dans une application Ktor (Kotlin).
Lecture des données
Il existe deux façons courantes de lire les données :- Méthode
query()qui renvoie un objetQueryResponsede bas niveau contenant unInputStreamavec les données. Généralement combinée àClickHouseBinaryFormatReaderpour les lectures en streaming, elle peut aussi être utilisée avec toute autre implémentation personnalisée de lecteur.QueryResponsedonne également accès aux métadonnées du jeu de résultats et aux métriques. - Méthode
queryAll()avec utilisation deGenericRecordpour un accès pratique aux lignes. Dans ce cas, l’intégralité du jeu de résultats est chargée en mémoire. - Méthode
queryRecords()qui renvoiecom.clickhouse.client.api.query.Records- un itérateur pour les objetsGenericRecord. Cette méthode repose sur une approche en streaming (aucune donnée n’est chargée en mémoire) et utiliseGenericRecordpour accéder aux données.
Lecture des Arrays
Méthodes deClickHouseBinaryFormatReadergetList(...)- lit n’importe quelArray(...)commeList<T>. Bon choix par défaut pour une lecture typée flexible. Prend en charge les tableaux imbriqués.getByteArray(...),getShortArray(...),getIntArray(...),getLongArray(...),getFloatArray(...),getDoubleArray(...),getBooleanArray(...)- idéal pour les tableaux 1D de valeurs compatibles avec les types primitifs.getStringArray(...)- pourArray(String)(et les valeurs d’enum représentées par leur nom).getObjectArray(...)- option générique pour tout type d’élément deArray(...), y compris les tableaux imbriqués. À utiliser pour lire des tableaux contenant des valeursNullableet des tableaux imbriqués.
GenericRecordgetList(...)- lit n’importe quelArray(...)en tant queList<T>. Bon choix par défaut pour une lecture à typage flexible. Prend en charge les tableaux imbriqués.getByteArray(...),getShortArray(...),getIntArray(...),getLongArray(...),getFloatArray(...),getDoubleArray(...),getBooleanArray(...)- idéal pour les tableaux 1D de valeurs compatibles avec les types primitifs.getStringArray(...)- pourArray(String)(et les valeurs d’enum représentées par leur nom).getObjectArray(...)- option générique pour tout type d’élément deArray(...), y compris les tableaux imbriqués. À utiliser pour lire des tableaux contenant des valeurs NULL et des tableaux imbriqués.
Guide de migration
L’ancien client (V1) utilisaitcom.clickhouse.client.ClickHouseClient#builder comme point de départ. Le nouveau client (V2) suit un pattern similaire avec com.clickhouse.client.api.Client.Builder. Les principales
différences sont :- aucun service loader n’est utilisé pour charger l’implémentation. Le
com.clickhouse.client.api.Clientsert de classe façade pour toutes sortes d’implémentations à l’avenir. - moins de sources de configuration : l’une est fournie au builder et l’autre via les paramètres d’opération (
QuerySettings,InsertSettings). La version précédente avait une configuration par nœud et chargeait les variables d’environnement dans certains cas.
Correspondance des paramètres de configuration
Il existe 3 classes enum liées à la configuration dans V1 :com.clickhouse.client.config.ClickHouseDefaults- paramètres de configuration à définir dans la plupart des cas d’utilisation, commeUSERetPASSWORD.com.clickhouse.client.config.ClickHouseClientOption- paramètres de configuration spécifiques au client, commeHEALTH_CHECK_INTERVAL.com.clickhouse.client.http.config.ClickHouseHttpOption- paramètres de configuration spécifiques à l’interface HTTP, commeRECEIVE_QUERY_PROGRESS.
com.clickhouse.client.config.ClickHouseDefaults#ASYNC et
com.clickhouse.client.config.ClickHouseClientOption#ASYNC ?). Le nouveau client V2 utilise com.clickhouse.client.api.Client.Builder comme dictionnaire unique de toutes les options de configuration possibles du client. La classe
com.clickhouse.client.api.ClientConfigProperties recense tous les noms de paramètres de configuration.Le tableau ci-dessous indique quelles options de l’ancienne version sont prises en charge par le nouveau client et leur nouvelle signification.Légende : ✔ = pris en charge, ✗ = supprimé- Connexion & authentification
- SSL et sécurité
- Options de socket
- Compression
- Proxy
- Délais d’expiration & tentatives de nouvelle exécution
- Fuseau horaire
- Buffers et performances
- Threads & traitement asynchrone
- HTTP & en-têtes
- Format & Requête
- Découverte des nœuds & équilibrage de charge
- Divers
Différences générales
- Client V2 utilise moins de classes propriétaires afin d’améliorer la portabilité. Par exemple, V2 fonctionne avec n’importe quelle implémentation de
java.io.InputStreampour envoyer des données à un serveur. - Le paramètre
asyncde Client V2 estoffpar défaut. Cela signifie qu’il n’y a pas de thread supplémentaire et que l’application garde davantage de contrôle sur le client. Ce paramètre doit êtreoffdans la majorité des cas d’utilisation. L’activation deasynccrée un thread distinct pour chaque requête. Cela n’a de sens que si vous utilisez un executor contrôlé par l’application (voircom.clickhouse.client.api.Client.Builder#setSharedOperationExecutor)
Écriture des données
- utilisez n’importe quelle implémentation de
java.io.InputStream. La V1com.clickhouse.data.ClickHouseInputStreamest prise en charge, mais n’est PAS recommandée. - une fois la fin du flux d’entrée détectée, elle est traitée comme telle. Auparavant, il fallait fermer le flux de sortie d’une requête.
- il n’y a qu’une seule méthode à appeler. Il n’est pas nécessaire de créer un objet de corps de requête supplémentaire.
- le flux du corps de la requête est fermé automatiquement une fois toutes les données copiées.
- une nouvelle API de bas niveau est disponible
com.clickhouse.client.api.Client#insert(java.lang.String, java.util.List<java.lang.String>, com.clickhouse.client.api.DataStreamWriter, com.clickhouse.data.ClickHouseFormat, com.clickhouse.client.api.insert.InsertSettings).com.clickhouse.client.api.DataStreamWriterest conçu pour implémenter une logique d’écriture de données personnalisée. Par exemple, pour lire des données depuis une file d’attente.
Lecture des données
- Les données sont lues au format
RowBinaryWithNamesAndTypespar défaut. À l’heure actuelle, seul ce format est pris en charge lorsqu’une liaison de données est nécessaire. - Les données peuvent être lues sous forme de collection d’enregistrements à l’aide de la méthode
List<GenericRecord> com.clickhouse.client.api.Client#queryAll(java.lang.String). Cette méthode lit les données en mémoire puis libère la connexion. Aucune gestion supplémentaire n’est nécessaire.GenericRecorddonne accès aux données et prend en charge certaines conversions.