튜토리얼: REST API로 Named Channel 시작하기
튜토리얼: REST API로 Named Channel 시작하기
참고
가능하면 자동 배치와 더 간단한 통합의 이점을 얻기 위해 REST API 대신 Snowpipe Streaming SDK를 사용하세요. 환경에 SDK가 적합하지 않을 때 직접 REST를 사용하세요.
이 가이드는 Snowpipe Streaming REST API 와 SnowSQL로 생성된 JSON Web Token (JWT)을 사용해 Snowflake로 데이터를 스트리밍하는 방법을 보여줍니다. 순서가 보장되고 정확히 한 번 수집이 필요한 Named Channel REST 수집을 다룹니다.
더 간단한(대부분의 새 애플리케이션에 권장) Elastic Channel REST 경로는 튜토리얼: Elastic Channels 시작하기 (REST) 를 참고하세요.
출처: Snowflake 문서
본문
사전 요구 사항
시작하기 전에 다음 항목이 있는지 확인하세요.
Snowflake 사용자 및 객체:
키-쌍 인증으로 구성된 Snowflake 사용자. 다음 SQL 명령을 사용해 공용 키를 등록하세요.
ALTER USER MY_USER SET RSA_PUBLIC_KEY='<your-public-key>';
스트리밍 수집을 위한 Snowflake 데이터베이스, 스키마, 대상 테이블. 다음 SQL 명령을 사용하고 MY_DATABASE, MY_SCHEMA, MY_TABLE 같은 자리 표시자를 원하는 이름으로 바꿔 만들 수 있습니다.
-- Create Database and Schema
CREATE OR REPLACE DATABASE MY_DATABASE;
CREATE OR REPLACE SCHEMA MY_SCHEMA;
-- Create Target Table
CREATE OR REPLACE TABLE MY_TABLE (
id NUMBER,
c1 NUMBER,
ts STRING
);
ACCOUNT_IDENTIFIER:
ACCOUNT_IDENTIFIER에는 조직 내 계정 이름을 사용하는 Format 1 — 예: myorg-account123 — 을 권장합니다. 형식에 대한 자세한 내용은 계정 식별자 를 참고하세요.
설치된 도구:
curl: HTTP 요청용.jq: JSON 응답 파싱용.SnowSQL: Snowflake의 명령줄 클라이언트로 명령 실행용.
생성된 JWT:
SnowSQL을 사용해 JWT를 생성하세요.
snowsql --private-key-path rsa_key.p8 --generate-jwt \
-a \
-u MY_USER
주의
JWT를 안전하게 저장하세요. 로그나 스크립트에 노출하지 마세요.
사전 요구 사항 및 설정
다음 단계는 Named Channel REST 수집에 필요한 환경 변수, ingest 호스트, 샘플 행을 구성합니다.
1단계: 환경 변수 설정
Snowflake 계정과 스트리밍 작업에 필요한 환경 변수를 설정하세요. PIPE 변수가 테이블과 연결된 기본 스트리밍 파이프를 대상으로 한다는 점에 유의하세요.
# Paste the JWT token obtained from SnowSQL
export JWT_TOKEN="PASTE_YOUR_JWT_TOKEN_HERE"
# Configure your Snowflake account and resources:
export ACCOUNT="" # For example, ab12345
export USER="MY_USER"
export DB="MY_DATABASE"
export SCHEMA="MY_SCHEMA"
export TABLE="MY_TABLE"
# Replace ACCOUNT with your Account URL Host to form the control plane host:
export CONTROL_HOST="${ACCOUNT}.snowflakecomputing.com"
2단계: ingest 호스트 발견 및 구성
Snowpipe Streaming REST는 두 개의 호스트 이름을 사용합니다: Snowflake 계정 엔드포인트(CONTROL_HOST)와 GET /v2/streaming/hostname이 반환하는 계정 특정 ingest 엔드포인트(INGEST_HOST).
AWS PrivateLink, Azure Private Link, Google Cloud Private Service Connect를 사용한다면 CONTROL_HOST를 SYSTEM$GET_PRIVATELINK_CONFIG 가 반환하는 privatelink-account-url 값의 호스트 이름으로 설정하세요. https://나 후행 슬래시를 포함하지 마세요.
중요
Snowflake 계정 이름에 밑줄이 포함된 경우(예: MY_ACCOUNT), 알려진 문제로 수집 서비스를 호출할 때 내부 오류가 발생할 수 있습니다.
scoped token을 생성하기 전에 INGEST_HOST의 모든 밑줄을 대시로 바꿔야 합니다. 이 변환된 형식(대시 포함)이 이후의 모든 REST API 호출에서 — scoped token 생성 자체를 포함해 — 사용되어야 합니다.
예를 들어 반환된 호스트 이름이 my_account.region.ingest.snowflakecomputing.com이라면 이후 모든 REST API 호출에서 my-account.region.ingest.snowflakecomputing.com으로 바꿔야 합니다.
ingest 호스트는 데이터를 스트리밍하는 엔드포인트입니다. JWT를 사용해 ingest 호스트를 발견하세요.
export INGEST_HOST=$(curl -sS -X GET \
-H "Authorization: Bearer ***" \
-H "X-Snowflake-Authorization-Token-Type: KEYPAIR_JWT" \
"https://${CONTROL_HOST}/v2/streaming/hostname")
echo "Ingest Host: $INGEST_HOST"
ingest 호스트용 프라이빗 DNS 구성
프라이빗 연결을 사용한다면 반환된 ingest 호스트 이름도 Snowflake 프라이빗 엔드포인트를 통해 해석되어야 합니다. ingest 호스트 이름은 Snowflake 계정 호스트 이름과 별개이며 SYSTEM$GET_PRIVATELINK_CONFIG 또는 SYSTEM$ALLOWLIST_PRIVATELINK 에 나타나지 않을 수 있습니다.
정확히 정규화된 INGEST_HOST 값에 대한 프라이빗 DNS 레코드를 만들고 계정 호스트 이름이 사용하는 동일한 기존 Snowflake 프라이빗 엔드포인트로 라우팅하세요.
- AWS에서 기존 Snowflake VPC 엔드포인트 리전 DNS 이름을 대상으로 Route 53 프라이빗 호스팅 영역
CNAME(또는 적절한 alias)을 만드세요. - Azure 에서 프라이빗 DNS 구성을 사용해 ingest 호스트 이름을 기존 Snowflake 프라이빗 엔드포인트 IP 주소로 해석하세요.
- Google Cloud 에서 ingest 호스트 이름을 기존 Private Service Connect 엔드포인트로 해석하세요.
ingest 호스트 이름에 대해 두 번째 Snowflake 프라이빗 엔드포인트를 만들 필요는 없습니다.
스트리밍 요청을 보내는 동일한 VM, 컨테이너, pod, connector 워커 또는 온프레미스 런타임에서 DNS와 TLS를 검증하세요. TLS SNI (Server Name Indication) 및 HTTP 라우팅을 위해 INGEST_HOST를 요청 호스트 이름으로 유지하세요. 프라이빗 엔드포인트 IP 주소로 바꾸거나 TLS 검증을 비활성화하지 마세요.
ingest 호스트에서 작업을 승인하기 위해 scoped token을 얻으세요.
export SCOPED_TOKEN=$(curl -sS -X POST "https://$CONTROL_HOST/oauth/token" \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H "Authorization: Bearer ***" \
-d "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&scope=${INGEST_HOST}")
echo "Scoped Token obtained for ingest host"
3단계: 샘플 행 생성
newline-delimited JSON (NDJSON) 형식으로 배치를 만드세요.
export NOW_TS=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
cat <<EOF > rows.ndjson
{"id":1,"c1":$RANDOM,"ts":"$NOW_TS"}
EOF
Named Channel 열고 사용하기
순서 또는 정확히 한 번 복구가 필요할 때 Named Channel을 사용하세요. 사전 요구 사항 및 설정 의 1~3단계를 완료한 다음 Named Channel 변수를 설정하세요.
export PIPE="MY_TABLE-STREAMING"
export CHANNEL="MY_CHANNEL"
4단계: Named Channel 열기
curl -sS -X PUT \
-H "Authorization: Bearer ***" \
-H "Content-Type: application/json" \
"https://${INGEST_HOST}/v2/streaming/databases/$DB/schemas/$SCHEMA/pipes/$PIPE/channels/$CHANNEL" \
-d '{"offset_token":"0"}' | tee open_resp.json | jq .
5단계: offset 및 continuation token으로 행 추가
open 작업이 반환한 continuation token과 애플리케이션 관리 소스 offset을 사용하세요.
export CONT_TOKEN=$(jq -r '.next_continuation_token' open_resp.json)
export OFFSET_TOKEN="1"
curl -sS -X POST \
-H "Authorization: Bearer ***" \
-H "Content-Type: application/x-ndjson" \
"https://${INGEST_HOST}/v2/streaming/data/databases/$DB/schemas/$SCHEMA/pipes/$PIPE/channels/$CHANNEL/rows?continuationToken=$CONT_TOKEN&startOffsetToken=$OFFSET_TOKEN&endOffsetToken=$OFFSET_TOKEN" \
--data-binary @rows.ndjson | tee append_resp.json | jq .
각 append 응답의 next_continuation_token을 다음 append 요청에서 사용하세요.
6단계: 커밋된 진행 상황 검증
curl -sS -X POST \
-H "Authorization: Bearer ***" \
-H "Content-Type: application/json" \
"https://${INGEST_HOST}/v2/streaming/databases/$DB/schemas/$SCHEMA/pipes/$PIPE:bulk-channel-status" \
-d "{\"channel_names\":[\"$CHANNEL\"]}" | jq ".channel_statuses.\"$CHANNEL\""
소스 offset을 전진시키기 전에 last_committed_offset_token이 1이 될 때까지 기다리세요.
7단계: 데이터 검증
last_committed_offset_token이 전진한 후 대상 테이블을 쿼리하세요.
SELECT * FROM MY_DATABASE.MY_SCHEMA.MY_TABLE ORDER BY id;
(선택) 8단계: 정리
rm -f rows.ndjson open_resp.json append_resp.json
unset JWT_TOKEN SCOPED_TOKEN ACCOUNT USER DB SCHEMA TABLE PIPE CHANNEL CONTROL_HOST INGEST_HOST NOW_TS CONT_TOKEN OFFSET_TOKEN
문제 해결
- HTTP 401 (권한 없음): JWT 토큰이 유효하고 만료되지 않았는지 확인하세요. 필요하면 다시 생성하세요.
- HTTP 404 (찾을 수 없음): 데이터베이스, 스키마, 테이블 또는 파이프 이름의 철자가 정확하고 Snowflake 계정에 존재하는지 다시 확인하세요.
- HTTP 429 (요청이 너무 많음): 재시도 지연에 무작위 변동(jitter)을 가한 지수 백오프로 재시도하세요. 고정된 예약 요청률을 가정하지 마세요.
- Ingest 호스트 없음: 제어 플레인 호스트 URL이 정확하고 접근 가능한지 확인하세요.
프라이빗 연결 문제 해결
CONTROL_HOST가 해석되지 않음:privatelink-account-url을 사용했는지, 프라이빗 DNS 영역이 애플리케이션 런타임에 연결되거나 포워딩되는지 확인하세요.Get Hostname은 성공하지만INGEST_HOST가 해석되지 않음: 반환된 ingest 호스트 이름을 프라이빗 DNS에 추가하고 기존 Snowflake 프라이빗 엔드포인트를 통해 라우팅하세요.- DNS가 커넥터 밖에서는 작동하지만 내부에서는 실패: 커넥터 컨테이너나 관리형 런타임에서 테스트하고, DNS 변경 후 음수 DNS 응답을 캐시하는 장기 실행 워커를 재시작하세요.
- TLS 호스트 이름 불일치: 반환된 ingest 호스트 이름을 URL 호스트 이름으로 유지하세요. 원시 프라이빗 엔드포인트 IP 주소에 연결하거나 TLS SNI 또는 HTTP
Host헤더를 다시 쓰지 마세요.