Tutoriel 3 : communications de service à service¶
Important
La fonction de tâches Snowpark Container Services est actuellement disponible en avant-première privée et est soumise aux conditions d’utilisation de l’avant-première disponibles à https://snowflake.com/legal. Contactez votre représentant Snowflake pour plus d’informations.
Introduction¶
Dans ce tutoriel, vous créez une tâche Snowpark Container Services qui communique avec le service echo que vous avez créé dans le tutoriel 1. Lorsque la tâche s’exécute, elle envoie une requête POST à l’URL de service echo (que vous avez fournie dans la spécification de la tâche) avec une chaîne « Hello » dans le corps de la requête. Le service echo renvoie une réponse contenant la chaîne « Bob said Hello » dans le corps de la réponse. Vous accédez aux journaux du conteneur de tâches pour vérifier que les communications ont réussi.
Ce tutoriel comporte deux parties :
Partie 1 : Créer et tester une tâche. Vous téléchargez le code fourni pour ce tutoriel et suivez les instructions étape par étape :
Téléchargez le code de la tâche pour ce tutoriel.
Créez une image Docker pour Snowpark Container Services, et chargez l’image dans un référentiel de votre compte.
Mettez en zone de préparation le fichier de spécification, qui donne à Snowflake les informations de configuration du conteneur. En plus du nom de l’image à utiliser pour démarrer un conteneur, la spécification définit la variable d’environnement (
SERVICE_URL
) sur l’URL de service echo. Le code de l’application lit cette variable d’environnement pour envoyer des demandes au service echo.Exécutez la tâche. En utilisant la commande EXECUTE SERVICE, vous pouvez exécuter la tâche en fournissant le fichier de spécification et le pool de calcul où Snowflake peut exécuter le conteneur. Enfin, accédez aux journaux du conteneur de tâches pour vérifier que la communication entre la tâche et le service s’est déroulée correctement.
Partie 2 : comprendre le code de la tâche. Cette section donne une vue d’ensemble du code de service et met en évidence la façon dont les différentes composantes collaborent.
Conditions préalables¶
Effectuez le tutoriel 1 et vérifiez que le service echo fonctionne.
SELECT SYSTEM$GET_SERVICE_STATUS('echo_service', 10);
1 : Télécharger le code de service¶
Un code (une application Python) est fourni pour créer une tâche.
Téléchargez le fichier zip dans un répertoire.
Décompressez le contenu, qui comprend un répertoire pour chaque tutoriel. Le répertoire
Tutorial-3
contient les fichiers suivants :service_to_service.py
Dockerfile
service_to_service_spec.yaml
2 : Construire et charger une image¶
Construisez une image pour la plateforme linux/amd64 prise en charge par Snowpark Container Services, puis chargez l’image dans le référentiel d’images de votre compte (voir Configuration commune).
Vous aurez besoin d’informations sur le référentiel (l’URL du référentiel et le nom d’hôte du registre) avant de pouvoir construire et charger l’image. Pour plus d’informations, voir Registre et référentiels.
Obtenir des informations sur le référentiel
Pour obtenir l’URL du référentiel, exécutez la commande SQL SHOW IMAGE REPOSITORIES.
SHOW IMAGE REPOSITORIES;
La colonne
repository_url
de la sortie fournit l’URL. En voici un exemple :<orgname>-<acctname>.registry.snowflakecomputing.com/tutorial_db/data_schema/tutorial_repository
Le nom d’hôte dans l’URL du référentiel est le nom d’hôte du registre. En voici un exemple :
<orgname>-<acctname>.registry.snowflakecomputing.com
Construire l’image et la charger dans le référentiel
Ouvrez une fenêtre de terminal et accédez au répertoire contenant les fichiers que vous avez décompressés.
Pour créer une image Docker, exécutez la commande
docker build
suivante à l’aide de la CLI Docker. Notez que la commande spécifie le répertoire de travail actuel (.) commePATH
pour les fichiers à utiliser pour la construction de l’image.docker build --rm --platform linux/amd64 -t <repository_url>/<image_name> .
Pour
image_name
, utilisezservice_to_service:latest
.
Exemple
docker build --rm --platform linux/amd64 -t myorg-myacct.registry.snowflakecomputing.com/tutorial_db/data_schema/tutorial_repository/service_to_service:latest .
Chargez l’image dans le référentiel de votre compte Snowflake. Pour que Docker puisse charger une image en votre nom dans votre référentiel, vous devez d’abord authentifier Docker avec Snowflake.
Pour authentifier Docker auprès du registre Snowflake, exécutez la commande suivante.
docker login <registry_hostname> -u <username>
Pour
username
, indiquez votre nom d’utilisateur Snowflake. Docker vous demandera votre mot de passe.
Pour charger l’image, exécutez la commande suivante :
docker push <repository_url>/<image_name>
Exemple
docker push myorg-myacct.registry.snowflakecomputing.com/tutorial_db/data_schema/tutorial_repository/service_to_service:latest
3 : Mettre en zone de préparation le fichier de spécification¶
Pour charger votre fichier de spécification de tâche (
service_to_service_spec.yaml
) sur la zone de préparation, utilisez l’une des options suivantes :L’interface Web de Snowsight. Pour obtenir des instructions, voir Sélection d’une zone de préparation interne pour les fichiers locaux.
La CLI SnowSQL. Exécutez la commande PUT suivante :
PUT file://<absolute-path-to-spec.yaml> @tutorial_stage AUTO_COMPRESS=FALSE OVERWRITE=TRUE;
La commande définit OVERWRITE=TRUE afin que vous puissiez charger le fichier à nouveau, si nécessaire (par exemple, si vous avez corrigé une erreur dans votre fichier de spécification). Si la commande PUT est exécutée avec succès, les informations relatives au fichier chargé sont affichées.
4 : Exécuter la tâche¶
Vous êtes maintenant prêt à tester la tâche Snowflake que vous avez créée. Lorsque la tâche est exécutée, Snowflake collecte tout ce que votre code dans le conteneur envoie à la sortie standard ou à l’erreur standard en tant que journaux. Vous pouvez utiliser la fonction système SYSTEM$GET_JOB_LOGS
pour accéder aux journaux. Pour plus d’informations, voir Snowpark Container Services : considérations supplémentaires pour les services et les tâches.
Pour démarrer une tâche, exécutez la commande EXECUTE SERVICE :
EXECUTE SERVICE IN COMPUTE POOL tutorial_compute_pool FROM @tutorial_stage SPEC='service_to_service_spec.yaml';
Remarques :
FROM et SPEC indiquent le nom de la zone de préparation et le nom du fichier de spécification de la tâche.
COMPUTE_POOL fournit les ressources informatiques où Snowflake exécute la tâche.
Snowflake exécute le conteneur identifié dans le fichier de spécification. Le conteneur lit la valeur de la variable d’environnement
SERVICE_URL
(http://echo-service:8000/echo
) et envoie une requête au service echo sur le port 8000 au chemin HTTP/echo
.Snowflake démarre la tâche et renvoie un ID de tâche en sortie :
+------------------------------------------------------------------------+ | status | |------------------------------------------------------------------------| | Execution 01af7ee6-0001-cb52-0020-c5870077223a completed successfully. | +------------------------------------------------------------------------+
Notez que la réponse comprend un ID de tâche de requête attribué par Snowflake.
(facultatif) Une fois la tâche terminée, vous pouvez obtenir plus d’informations à son sujet. Ceci est utile pour déboguer l’échec d’une tâche.
Facultatif : pour capturer l’ID d’une tâche de la commande EXECUTE SERVICE précédente dans une variable de session afin de pouvoir y faire référence ultérieurement, exécutez la commande suivante :
SET job_id = last_query_id();
Notez que vous devez capturer l’ID de la tâche immédiatement après sa création, sinon vous capturerez une valeur erronée.
Pour obtenir le statut d’une tâche, utilisez l’une des options suivantes pour appeler la fonction SYSTEM$GET_JOB_STATUS :
En utilisant l’ID d’une tâche renvoyé par EXECUTE SERVICE :
CALL SYSTEM$GET_JOB_STATUS('<job_id returned by EXECUTE SERVICE>');
Utilisation de la variable de session :
CALL SYSTEM$GET_JOB_STATUS($job_id);
Exemple de sortie :
[ { "status":"DONE", "message":"Container finished", "containerName":"main", "instanceId":"0", "serviceName":"JOB_01ABD9E5000046DF00000E99000BC01E", "image":"myorg-myacct.registry.snowflakecomputing.com/tutorial_db/data_schema/tutorial_repository/service_to_service:latest", "restartCount":0, "startTime":"2023-01-01T00:00:00Z" } ]
Pour lire les journaux des tâches, utilisez l’une des options suivantes :
Utiliser l’ID de tâche d’une requête renvoyé par EXECUTE SERVICE :
CALL SYSTEM$GET_JOB_LOGS('<job_id returned by EXECUTE SERVICE>', 'main');
Utiliser la variable de session :
CALL SYSTEM$GET_JOB_LOGS($job_id, 'main');
main
est le nom du conteneur à partir duquel vous récupérez le journal. Vous définissez ce nom de conteneur pour le conteneur dans le fichier de spécification de la tâche.Exemple de journal :
+--------------------------------------------------------------------------------------------------------------------------+ | SYSTEM$GET_JOB_LOGS | |--------------------------------------------------------------------------------------------------------------------------| | service-to-service [2023-04-29 21:52:09,208] [INFO] Calling http://echo-service:8000/echo with input Hello | | service-to-service [2023-04-29 21:52:09,212] [INFO] Received response from http://echo-service:8000/echo: Bob said Hello | +--------------------------------------------------------------------------------------------------------------------------+
5 : Nettoyage¶
Snowflake facture les nœuds du pool de calcul qui sont actifs pour votre compte. (Voir Utilisation des pools de calcul). Pour éviter les frais non voulus, arrêtez d’abord tous les services en cours d’exécution sur un pool de calcul. Ensuite, suspendez le pool de calcul (si vous avez l’intention de le réutiliser plus tard) ou supprimez-le.
Arrêtez tous les services et toutes les tâches sur le pool de calcul.
ALTER COMPUTE POOL tutorial_compute_pool STOP ALL;
Supprimez le pool de calcul.
DROP COMPUTE POOL tutorial_compute_pool;
Vous pouvez également nettoyer le registre des images (supprimer toutes les images) et la zone de préparation interne (supprimer les spécifications).
DROP IMAGE REPOSITORY tutorial_repository;
DROP STAGE tutorial_stage;
6 : Vérification du code de tâche¶
Cette section couvre les sujets suivants :
Vérification des fichiers fournis : examinez les différents fichiers de code qui mettent en œuvre la tâche.
Construire et tester une image localement. Découvrez comment tester localement l’image Docker avant de la charger vers un référentiel dans votre compte Snowflake.
Vérification des fichiers fournis¶
Le fichier zip que vous avez téléchargé comprend les fichiers suivants :
service_to_service.py
Dockerfile
service_to_service_spec.yaml
Cette section donne un aperçu de la manière dont le code met en œuvre la tâche.
Fichier service_to_service.py¶
import json
import logging
import os
import requests
import sys
SERVICE_URL = os.getenv('SERVICE_URL', 'http://localhost:8080/echo')
ECHO_TEXT = 'Hello'
def get_logger(logger_name):
logger = logging.getLogger(logger_name)
logger.setLevel(logging.DEBUG)
handler = logging.StreamHandler(sys.stdout)
handler.setLevel(logging.DEBUG)
handler.setFormatter(
logging.Formatter(
'%(name)s [%(asctime)s] [%(levelname)s] %(message)s'))
logger.addHandler(handler)
return logger
logger = get_logger('service-to-service')
def call_service(service_url, echo_input):
logger.info(f'Calling {service_url} with input {echo_input}')
row_to_send = {"data": [[0, echo_input]]}
response = requests.post(url=service_url,
data=json.dumps(row_to_send),
headers={"Content-Type": "application/json"})
message = response.json()
if message is None or not message["data"]:
logger.error('Received empty response from service ' + service_url)
response_row = message["data"][0]
if len(response_row) != 2:
logger.error('Unexpected response format: ' + response_row)
echo_reponse = response_row[1]
logger.info(f'Received response from {service_url}: ' + echo_reponse)
if __name__ == '__main__':
call_service(SERVICE_URL, ECHO_TEXT)
Lorsque la tâche est exécutée :
Snowflake utilise la valeur fournie dans le fichier de spécification pour définir la variable d’environnement SERVICE_URL dans le conteneur.
Le code lit la variable d’environnement.
SERVICE_URL = os.getenv('SERVICE_URL', 'http://localhost:8080/echo').
La fonction
call_service()
utilise la fonctionSERVICE_URL
pour communiquer avec le service echo.
Dockerfile¶
Ce fichier contient toutes les commandes pour construire une image en utilisant Docker.
ARG BASE_IMAGE=python:3.10-slim-buster
FROM $BASE_IMAGE
COPY service_to_service.py ./
RUN pip install --upgrade pip && \
pip install requests
CMD ["python3", "service_to_service.py"]
Fichier service_to_service_spec.yaml (spécification de la tâche)¶
Snowflake utilise les informations que vous fournissez dans cette spécification pour configurer et faire fonctionner votre service.
spec:
container:
- name: main
image: /tutorial_db/data_schema/tutorial_repository/service_to_service:latest
env:
SERVICE_URL: "http://echo-service:8000/echo"
Cette spécification fournit des informations à Snowflake pour la configuration et l’exécution de votre tâche. Pour communiquer avec le service echo, la tâche a besoin des éléments suivants :
Nom DNS du service echo auquel envoyer les requêtes.
Port HTTP sur lequel le service echo écoute.
Chemin HTTP où le service echo s’attend à ce que la requête soit envoyée.
Pour obtenir ces informations :
Pour obtenir le nom DNS du service echo (tutoriel 1), exécutez la commande DESCRIBE SERVICE SQL :
DESCRIBE SERVICE echo_service;
Nom DNS résultant pour le service echo :
echo-service.data-schema.tutorial-db.snowflakecomputing.internal
Notez que, dans ce tutoriel, vous créez la tâche dans le même schéma de base de données (
data-schema
) où le service echo (tutoriel 1) est créé. Par conséquent, vous n’avez besoin que de la partie « echo-service » du nom DNS précédent pour construire laSERVICE_URL
.Obtenez le numéro de port (8000) où le service echo écoute à partir du fichier de spécification de service echo (tutoriel 1).
Vous créez ensuite le fichier de spécification précédent (service_to_service_spec.yaml
). Outre les champs obligatoires containers.name
et containers.image
, vous incluez également le champ containers.env
facultatif.
Construire et tester une image localement¶
Vous pouvez tester l’image Docker localement avant de la charger vers un référentiel dans votre compte Snowflake. Dans les tests locaux, votre conteneur fonctionne de manière autonome (il ne s’agit pas d’une tâche exécutée par Snowflake).
Note
Le code Python fourni pour ce tutoriel utilise la bibliothèque requests
pour envoyer des requêtes à un autre service Snowpark Containers. Si cette bibliothèque n’est pas installée, lancez pip (par exemple, pip3 install requests
).
Suivez les étapes suivantes pour tester l’image Docker du tutoriel 3 :
Il faut que le service echo fonctionne (tutoriel 1). Pour démarrer le service echo du tutoriel 1, dans une fenêtre de terminal, exécutez la commande Python suivante :
SERVER_PORT=8000 python3 echo_service.py
Ouvrez une autre fenêtre de terminal et exécutez le code Python fourni pour ce tutoriel :
SERVICE_URL=http://localhost:8000/echo python3 service_to_service.py
Notez que la
SERVICE_URL
est une variable d’environnement. Pour les tests locaux, vous devez définir explicitement cette variable. Cette URL correspond au port et au chemin HTTP explicitement spécifiés lorsque vous avez démarré le service echo.Lorsque la tâche est exécutée, elle envoie une requête POST au service echo écoutant sur le port 8080 avec la chaîne « Hello » dans le corps de la requête. Le service echo renvoie l’écho de l’entrée et renvoie une réponse, « I said Hello ».
Exemple de réponse :
service-to-service [2023-04-23 22:30:41,278] [INFO] Calling http://localhost:8000/echo with input Hello service-to-service [2023-04-23 22:30:41,287] [INFO] Received response from http://localhost:8000/echo: I said Hello
Examinez le journal pour vérifier que la communication de service à service a réussi.
Quelle est la prochaine étape ?¶
Maintenant que vous avez terminé ce tutoriel, vous pouvez retourner à Tutoriels avancés pour explorer d’autres sujets.