Tutorial 3: Dienst-zu-Dienst-Kommunikation¶
Wichtig
Das Job-Feature von Snowpark Container Services befindet sich derzeit in der privaten Vorschau und unterliegt den Nutzungsbedingungen für Vorschau-Features unter https://snowflake.com/legal. Weitere Informationen dazu erhalten Sie bei Ihrem Snowflake-Ansprechpartner.
Einführung¶
In diesem Tutorial erstellen Sie einen Snowpark Container Services-Job, der mit dem Echo-Dienst kommuniziert, den Sie in Tutorial 1 erstellt haben. Wenn der Job ausgeführt wird, sendet er eine POST-Anforderung an die Echo-Dienst-URL (die Sie in der Jobspezifikation angeben) mit einer „Hello“-Zeichenfolge im Anforderungstext. Der Echo-Dienst gibt eine Antwort mit der Zeichenfolge „Bob said Hello“ (Bob sagte Hallo) im Antworttext zurück. Sie greifen auf die Protokolle des Jobcontainers zu, um zu überprüfen, ob die Kommunikation erfolgreich war.
Dieses Tutorial besteht aus zwei Teilen:
Teil 1: Job erstellen und testen. Sie laden den für dieses Tutorial bereitgestellten Code herunter und befolgen die schrittweise Anleitung:
Jobcode für dieses Tutorial herunterladen
Docker-Image für Snowpark Container Services erstellen und Image in Repository im eigenen Konto hochladen
Job-Spezifikationsdatei mit den Container-Konfigurationsinformationen für Snowflake im Stagingbereich bereitstellen. Neben dem Namen des Images, das zum Starten eines Containers verwendet werden soll, enthält die Spezifikationsdatei auch die Umgebungsvariable (
SERVICE_URL
) für die Echo-Dienst-URL. Der Anwendungscode liest diese Umgebungsvariable, um Anforderungen an den Echo-Dienst zu senden.Job ausführen. Mit dem Befehl EXECUTE SERVICE können Sie den Job ausführen, indem Sie die Spezifikationsdatei und den Computepool angeben, in dem Snowflake den Container ausführen kann. Und schließlich können Sie auf die Protokolle des Jobcontainers zugreifen, um zu überprüfen, ob die Kommunikation zwischen Job und Dienst erfolgreich war.
Teil 2: Erläuterungen zum Jobcode. Dieser Abschnitt bietet eine Übersicht zum Dienstcode und zeigt auf, wie die verschiedenen Komponenten zusammenarbeiten.
Voraussetzungen¶
Schließen Sie Tutorial 1 ab, und überprüfen Sie, ob der Echo-Dienst ausgeführt wird.
SELECT SYSTEM$GET_SERVICE_STATUS('echo_service', 10);
1: Dienstcode herunterladen¶
Zum Erstellen eines Jobs wird ein Code (eine Python-Anwendung) bereitgestellt.
Laden Sie die ZIP-Datei in ein Verzeichnis herunter.
Entpacken Sie den Inhalt, der ein Verzeichnis für jedes Tutorial enthält. Das Verzeichnis
Tutorial-3
enthält die folgenden Dateien:service_to_service.py
Dockerfile
service_to_service_spec.yaml
2: Image erstellen und hochladen¶
Erstellen Sie ein Image für die linux/amd64-Plattform, die von Snowpark Container Services unterstützt wird, und laden Sie das Image dann in das Image-Repository in Ihrem Konto hoch (siehe Grundlegende Einrichtung).
Sie benötigen Informationen zum Repository (die Repository-URL und den Hostnamen der Registry), bevor Sie das Image erstellen und hochladen können. Weitere Informationen dazu finden Sie unter Registry und Repositorys.
Informationen zum Repository abrufen
Um die Repository-URL zu erhalten, führen Sie den SQL-Befehl SHOW IMAGE REPOSITORIES aus.
SHOW IMAGE REPOSITORIES;
Die URL ist in der Spalte
repository_url
der Ausgabe enthalten. Siehe folgendes Beispiel:<orgname>-<acctname>.registry.snowflakecomputing.com/tutorial_db/data_schema/tutorial_repository
Der Hostname in der Repository-URL ist der Name des Registry-Hosts. Siehe folgendes Beispiel:
<orgname>-<acctname>.registry.snowflakecomputing.com
Image erstellen und in das Repository hochladen
Öffnen Sie ein Terminalfenster, und wechseln Sie in das Verzeichnis, das die entpackten Dateien enthält.
Um ein Docker-Image zu erstellen, führen Sie den folgenden Befehl
docker build
mithilfe der Docker-CLI aus. Beachten Sie, dass der Befehl das aktuelle Arbeitsverzeichnis (.) alsPATH
für die Dateien angibt, die für das Erstellen des Images verwendet werden sollen.docker build --rm --platform linux/amd64 -t <repository_url>/<image_name> .
Für
image_name
verwenden Sieservice_to_service:latest
:
Beispiel
docker build --rm --platform linux/amd64 -t myorg-myacct.registry.snowflakecomputing.com/tutorial_db/data_schema/tutorial_repository/service_to_service:latest .
Laden Sie das Image in das Repository in Ihrem Snowflake-Konto hoch. Damit Docker ein Image in Ihrem Namen in Ihr Repository hochladen kann, müssen Sie Docker zunächst mit Snowflake authentifizieren.
Um Docker bei der Snowflake-Registrierung zu authentifizieren, führen Sie den folgenden Befehl aus.
docker login <registry_hostname> -u <username>
Geben Sie dabei für
username
Ihren Snowflake-Benutzernamen an. Docker fordert Sie zur Eingabe Ihres Kennworts auf.
Führen Sie den folgenden Befehl aus, um das Image hochzuladen:
docker push <repository_url>/<image_name>
Beispiel
docker push myorg-myacct.registry.snowflakecomputing.com/tutorial_db/data_schema/tutorial_repository/service_to_service:latest
3: Spezifikationsdatei im Stagingbereich bereitstellen¶
Um Ihre Jobspezifikationsdatei (
service_to_service_spec.yaml
) in den Stagingbereich zu laden, verwenden Sie eine der folgenden Optionen:Die Snowsight-Weboberfläche. Eine Anleitung dazu finden Sie unter Auswahl eines internen Stagingbereichs für lokale Dateien.
Die SnowSQL-CLI. Führen Sie den folgenden PUT-Befehl aus:
PUT file://<absolute-path-to-spec.yaml> @tutorial_stage AUTO_COMPRESS=FALSE OVERWRITE=TRUE;
Der Befehl setzt OVERWRITE=TRUE, sodass Sie die Datei bei Bedarf erneut hochladen können (z. B. wenn Sie einen Fehler in Ihrer Spezifikationsdatei behoben haben). Wenn der PUT-Befehl erfolgreich ausgeführt wurde, werden Informationen zu der hochgeladenen Datei ausgegeben.
4: Job ausführen¶
Jetzt sind Sie bereit, den von Ihnen erstellen Snowflake-Job zu testen. Während der Job ausgeführt wird, erfasst Snowflake alle Daten, die Ihr Code im Container an die Standardausgabe oder den Standardfehler ausgibt, als Protokolleinträge. Sie können die Systemfunktion SYSTEM$GET_JOB_LOGS
verwenden, um auf die Protokolleinträge zuzugreifen. Weitere Informationen dazu finden Sie unter Snowpark Container Services: Zusätzliche Hinweise zu Diensten und Jobs.
Um einen Job zu starten, führen Sie den Befehl EXECUTE SERVICE aus:
EXECUTE SERVICE IN COMPUTE POOL tutorial_compute_pool FROM @tutorial_stage SPEC='service_to_service_spec.yaml';
Beachten Sie Folgendes:
FROM und SPEC geben den Namen des Stagingbereichs bzw. den Namen der Jobspezifikationsdatei an.
COMPUTE_POOL stellt die Computeressourcen bereit, auf denen Snowflake den Job ausführt.
Snowflake führt den in der Spezifikationsdatei angegebenen Container aus. Der Container liest den Wert der Umgebungsvariablen
SERVICE_URL
(http://echo-service:8000/echo
) und sendet eine Anforderung an den Echo-Dienst an Port 8000 im HTTP-Pfad/echo
.Snowflake startet den Job und gibt in der Ausgabe eine Job-ID zurück:
+------------------------------------------------------------------------+ | status | |------------------------------------------------------------------------| | Execution 01af7ee6-0001-cb52-0020-c5870077223a completed successfully. | +------------------------------------------------------------------------+
Beachten Sie, dass die Antwort eine von Snowflake zugewiesene Abfrage-Job-ID enthält.
(optional) Nach Beendigung des Jobs können Sie weitere Informationen zu dem ausgeführten Job abrufen. Dies ist nützlich für die Fehlersuche bei Fehlschlagen des Jobs.
Optional: Um die Job-ID des obigen EXECUTE SERVICE-Befehls in einer Sitzungsvariablen zu speichern, damit Sie später darauf verweisen können, führen Sie den folgenden Befehl aus:
SET job_id = last_query_id();
Beachten Sie, dass Sie die Job-ID unmittelbar nach seiner Erstellung erfassen müssen, da Sie sonst den falschen Wert erfassen.
Um den Jobstatus durch Aufrufen der Funktion SYSTEM$GET_JOB_STATUS zu ermitteln, verwenden Sie eine der folgenden Optionen:
Verwenden der von EXECUTE SERVICE zurückgegebenen Job-ID:
CALL SYSTEM$GET_JOB_STATUS('<job_id returned by EXECUTE SERVICE>');
Verwenden der Sitzungsvariable:
CALL SYSTEM$GET_JOB_STATUS($job_id);
Beispielausgabe:
[ { "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" } ]
Um die Jobprotokolle zu lesen, verwenden Sie eine der folgenden Optionen:
Verwenden Sie die von EXECUTE SERVICE zurückgegebene Abfrage-Job-ID:
CALL SYSTEM$GET_JOB_LOGS('<job_id returned by EXECUTE SERVICE>', 'main');
Verwenden Sie die Sitzungsvariable:
CALL SYSTEM$GET_JOB_LOGS($job_id, 'main');
main
ist der Name des Containers, aus dem Sie das Protokoll abrufen. Diesen Containernamen verwenden Sie in der Jobspezifikationsdatei zur Angabe des Containers.Beispielprotokoll:
+--------------------------------------------------------------------------------------------------------------------------+ | 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: Bereinigen¶
Snowflake erhebt Gebühren für die Computepool-Knoten, die für Ihr Konto aktiv sind. (Siehe Verwenden von Computepools). Um unerwünschte Gebühren zu vermeiden, stoppen Sie zunächst alle Dienste, die derzeit in einem Computepool ausgeführt werden. Anschließend können Sie den Computepool entweder anhalten (wenn Sie ihn später wieder verwenden möchten) oder ihn löschen.
Stoppen Sie alle Dienste und Jobs im Computepool.
ALTER COMPUTE POOL tutorial_compute_pool STOP ALL;
Löschen Sie den Computepool.
DROP COMPUTE POOL tutorial_compute_pool;
Sie können auch die Image-Registry (alle Images entfernen) und den internen Stagingbereich (Spezifikationen entfernen) bereinigen.
DROP IMAGE REPOSITORY tutorial_repository;
DROP STAGE tutorial_stage;
6: Erläuterungen zum Jobcode¶
In diesem Abschnitt werden die folgenden Themen behandelt:
Untersuchen der bereitgestellten Dateien: Untersuchen Sie die verschiedenen Codedateien, mit denen der Job implementiert wird.
Lokales Erstellen und Testen eines Images. Erfahren Sie, wie Sie das Docker-Image lokal testen, bevor Sie es in ein Repository in Ihrem Snowflake-Konto hochladen.
Untersuchen der bereitgestellten Dateien¶
Die heruntergeladene ZIP-Datei enthält die folgenden Dateien:
service_to_service.py
Dockerfile
service_to_service_spec.yaml
Dieser Abschnitt bietet eine Übersicht darüber, wie der Code den Job implementiert.
Datei „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)
Bei Ausführung des Jobs passiert Folgendes:
Snowflake verwendet den in der Spezifikationsdatei angegebenen Wert, um die Umgebungsvariable SERVICE_URL im Container festzulegen.
Der Code liest die Umgebungsvariable.
SERVICE_URL = os.getenv('SERVICE_URL', 'http://localhost:8080/echo').
Die Funktion
call_service()
verwendetSERVICE_URL
zur Kommunikation mit dem Echo-Dienst.
Datei „Dockerfile“¶
Diese Datei enthält alle Befehle, um ein Image mit Docker zu erstellen.
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"]
Datei „service_to_service_spec.yaml“ (Jobspezifikation)¶
Snowflake verwendet die von Ihnen in dieser Spezifikation angegebenen Informationen zur Konfiguration und Ausführung Ihres Dienstes.
spec:
container:
- name: main
image: /tutorial_db/data_schema/tutorial_repository/service_to_service:latest
env:
SERVICE_URL: "http://echo-service:8000/echo"
Diese Spezifikation stellt Informationen für Snowflake zum Konfigurieren und Ausführen Ihres Jobs bereit. Um mit dem Echo-Dienst zu kommunizieren, benötigt der Job Folgendes:
DNS-Name des Echo-Dienstes, an den Anforderungen gesendet werden.
HTTP-Port, der vom Echo-Dienst auf Anforderungen überwacht wird.
HTTP-Pfad, wo der Echo-Dienst die zu sendende Anforderung erwartet.
So erhalten Sie diese Informationen:
Um den DNS-Namen des Echo-Dienstes (Tutorial 1) zu erhalten, führen Sie den Befehl DESCRIBE SERVICE SQL aus:
DESCRIBE SERVICE echo_service;
Resultierender DNS-Name für den Echo-Dienst:
echo-service.data-schema.tutorial-db.snowflakecomputing.internal
Beachten Sie, dass Sie in diesem Tutorial den Job in demselben Datenbankschema (
data-schema
) erstellen, in dem auch der Echo-Dienst (Tutorial 1) erstellt wird. Daher benötigen Sie nur den „echo-service“-Teil des obigen DNS-Namens, um den Wert fürSERVICE_URL
zu konstruieren.Rufen Sie die Portnummer (8000), der vom Echo-Dienst auf Anforderungen überwacht wird, aus der Dienstspezifikationsdatei des Echo-Dienstes ab (Tutorial 1).
Erstellen Sie dann die obige Spezifikationsdatei (service_to_service_spec.yaml
). Zusätzlich zu den Pflichtfeldern containers.name
und containers.image
fügen Sie auch das optionale Feld containers.env
hinzu.
Lokales Erstellen und Testen eines Images¶
Sie können das Docker-Image lokal testen, bevor Sie es in ein Repository Ihres Snowflake-Kontos hochladen. Bei lokalen Tests wird Ihr Container eigenständig ausgeführt (er ist kein Job, der von Snowflake ausgeführt wird).
Bemerkung
Der für dieses Tutorial bereitgestellte Python-Code verwendet die requests
-Bibliothek, um Anfragen an einen anderen Snowpark Container Services-Dienst zu senden. Wenn Sie diese Bibliothek nicht installiert haben, führen Sie pip aus (zum Beispiel pip3 install requests
).
Führen Sie die folgenden Schritte aus, um das Docker-Image von Tutorial 3 zu testen:
Der Echo-Dienst muss aktiviert sein (Tutorial 1). Zum Starten des Echo-Dienstes aus Tutorial 1 führen Sie in einem Terminalfenster den folgenden Python-Befehl aus:
SERVER_PORT=8000 python3 echo_service.py
Öffnen Sie ein weiteres Terminalfenster, und führen Sie den Python-Code aus, der für dieses Tutorial bereitgestellt wurde:
SERVICE_URL=http://localhost:8000/echo python3 service_to_service.py
Beachten Sie, dass
SERVICE_URL
eine Umgebungsvariable ist. Für lokale Tests müssen Sie für diese Variable explizit einen Wert festlegen. Diese URL entspricht dem Port und dem HTTP-Pfad, die beim Starten des Echo-Dienstes explizit angegeben wurden.Wenn der Job ausgeführt wird, sendet er eine POST-Anforderung an den Echo-Dienst, der Port 8080 überwacht, mit der Zeichenfolge „Hello“ im Anforderungstext. Der Echo-Dienst gibt die Eingabe als Echo wieder zurück und antwortet mit „I said Hello“ (Ich sagte Hallo).
Beispielantwort:
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
Überprüfen Sie das Protokoll, um sicherzustellen, dass die Kommunikation zwischen den Diensten erfolgreich war.
Nächste Schritte¶
Nachdem Sie dieses Tutorial abgeschlossen haben, können Sie zu Erweiterte Tutorials zurückkehren, um weitere Themen zu erkunden.