고성능 외부 함수 설계하기

이 항목에서는 비동기 외부 함수 사용에 대한 정보를 포함한 외부 함수의 동시성, 안정성, 확장성에 대한 정보를 제공합니다.

이 항목의 내용:

비동기 원격 서비스와 동기 원격 서비스

원격 서비스는 동기 또는 비동기일 수 있습니다.

동기:

동기 원격 서비스에 대한 호출은 차단 호출입니다. 원격 서비스는 결과가 준비될 때까지 아무런 응답도 보내지 않습니다. 이 서비스는 폴링할 수 없습니다.

동기 코드는 비동기 코드보다 구현하기 쉽습니다.

비동기:

호출자가 결과를 기다리는 동안 비동기 원격 서비스를 폴링할 수 있습니다.

비동기로 처리하면 시간 제한에 대한 민감도가 감소합니다.

비동기 서비스에 대한 자세한 내용은 Microsoft의 비동기 요청-회신 패턴 에 대한 설명을 참조하십시오. (정보는 Microsoft Azure로 제한되지 않습니다.)

동기 원격 서비스는 HTTP POST 요청을 수신하고 요청을 처리하고 결과를 반환합니다. 데이터를 처리하는 데 걸리는 시간에 따라 요청 수신 시간과 결과 반환 시간 사이에 상당한 지연이 있을 수 있습니다.

비동기 원격 서비스는 HTTP POST 요청을 수신하고 요청이 수신되었다는 확인을 (보통 거의 즉시) 반환합니다. 그런 다음, 호출자(Snowflake)는 비동기 처리 상태를 확인하는 HTTP GET 요청(보통 각각의 요청 사이에 상당한 지연이 있음)을 하나 이상 발행하는 폴링 루프를 실행합니다. GET은 요청 본문에 어떤 데이터도 보내지 않지만, 원본 POST와 똑같은 헤더를 포함합니다.

비동기 원격 서비스는 원격 서비스가 프록시 서비스(예: Amazon API Gateway)와 같은 구성 요소에 내장된 시간 제한을 초과할 때 유용합니다.

원격 서비스가 반드시 순수하게 동기적이거나 순수하게 비동기적일 필요는 없습니다. 원격 서비스는 요청의 데이터양, 처리 중인 다른 요청의 수 등과 같은 요인에 따라, 다양한 시간에 동기 및 비동기로 작동할 수 있습니다.

Snowflake의 외부 함수 구현은 일반적으로 동기 및 비동기 서드 파티 함수 라이브러리와 호환됩니다.

아래 다이어그램에서는 동기 및 비동기 처리를 대조적으로 보여줍니다. 상위 경로는 동기적입니다. (하나 이상의 HTTP GET 요청을 포함한) 하위 경로는 비동기적입니다.

Illustration of the HTTP POST and GET requests for asynchronous external functions.

동기 및 비동기 외부 함수의 예를 보려면 Snowflake 샘플 함수 를 참조하십시오.

동기 원격 서비스

사용자가 외부 함수를 호출하려면 먼저 개발자와 Snowflake 계정 관리자가 프록시 서비스에 액세스할 수 있도록 Snowflake를 구성해야 합니다. 일반적으로, 해당 단계는 대략적으로 아래에 표시된 순서대로 수행됩니다(위 다이어그램의 오른쪽에서 시작해 Snowflake를 향해 왼쪽으로 이동함).

  1. 개발자가 원격 서비스를 작성해야 하며, 해당 원격 서비스는 HTTPS 프록시 서비스를 통해 노출되어야 합니다. 예를 들어, 원격 서비스는 AWS Lambda에서 실행 중이고 Amazon API Gateway의 리소스를 통해 노출되는 Python 함수일 수 있습니다.

  2. Snowflake에서는 ACCOUNTADMIN이나 CREATE INTEGRATION 권한을 가진 역할이 Snowflake가 프록시 서비스와 통신할 수 있도록 하는 인증 정보를 포함한 《API 통합》 오브젝트를 만들어야 합니다. API 통합은 SQL 명령 CREATE API INTEGRATION 으로 생성됩니다.

  3. Snowflake 사용자는 SQL 명령 CREATE EXTERNAL FUNCTION 을 실행해야 합니다. 사용자는 API 통합에 대한 USAGE 권한이 있고 함수를 만들 충분한 권한을 가진 역할을 사용해야 합니다.

    참고

    CREATE EXTERNAL FUNCTION 명령은 《Snowflake 외부에서 실행》될 코드를 로딩한다는 의미에서는 외부 함수를 실제로 만드는 것은 아닙니다. 대신 CREATE EXTERNAL FUNCTION 명령은 Snowflake 외부에서 실행되는 코드를 간접적으로 참조하는 데이터베이스 오브젝트를 만듭니다. 더 정확하게는, CREATE EXTERNAL FUNCTION 명령은 다음을 포함하는 오브젝트를 만듭니다.

    • 릴레이 함수 역할을 하는 HTTPS 프록시 서비스에 있는 리소스의 URL.

    • 프록시 서비스에 대한 인증에 사용할 API 통합의 이름.

    • 원격 서비스의 사실상 별칭인 이름. 이 별칭은 SQL 명령에 사용됩니다(예: SELECT MyAliasForRemoteServiceXYZ(col1) ...;).

Snowflake의 별칭, HTTPS 프록시 서비스 리소스의 이름, 원격 서비스의 이름이 모두 다를 수 있습니다. (하지만 세 가지의 이름을 모두 똑같은 이름으로 사용하면 관리를 단순화할 수 있습니다.)

위에서 설명한 단계가 외부 함수를 실행하는 가장 일반적인 방법이지만, 몇 가지 변형이 허용됩니다. 예:

  • 원격 서비스가 체인의 마지막 단계가 아닐 수도 있습니다. 원격 서비스는 작업 중 일부분을 수행하도록 또 다른 원격 서비스를 호출할 수 있습니다.

  • 원격 서비스가 JSON 형식의 데이터를 받고 반환하지 않는 경우, HTTPS 프록시 서비스의 리소스(릴레이 함수)는 데이터를 JSON 형식에서 다른 형식으로 변환하고 반환된 데이터를 다시 JSON으로 변환할 수 있습니다.

  • Snowflake에서는 원격 서비스가 부작용이 없고 어떠한 상태 정보도 유지하지 않는 실제 함수(즉, 0개 이상의 입력 매개 변수를 허용하고 출력을 반환하는 코드 조각)로 작동할 것을 권장하지만, 반드시 필수적인 사항은 아닙니다. 원격 서비스는 예컨대 (데이터의 온도 판독 값과 같은) 값이 위험할 정도로 높을 경우 경고를 보내는 것과 같은 다른 작업을 수행할 수 있습니다. 드문 경우지만, 원격 서비스가 상태 정보(예: 발행된 전체 경고 수)를 유지할 수도 있습니다.

비동기 원격 서비스

비동기 원격 서비스는 원격 서비스가 프록시 서비스와 같은 구성 요소에 내장된 시간 제한을 초과할 때 유용합니다.

비동기 원격 서비스는 위에서 설명한 것과 똑같은 구성 요소(클라이언트, Snowflake, 프록시 서비스, 원격 서비스) 및 똑같은 일반 단계를 포함합니다. 하지만 HTTP 요청과 응답의 세부 사항은 다릅니다.

비동기 동작은 원격 서비스를 작성하는 사람과 Snowflake가 구현합니다. SQL 문은 동기 원격 서비스와 비동기 원격 서비스에 대해 모두 같습니다.

자체 원격 서비스를 작성 중이고 Snowflake의 비동기 처리와 호환되도록 하려면 다음과 같이 동작하도록 원격 서비스를 작성하십시오.

  • 행의 특정한 배치 에 대해 HTTP POST를 처음 수신할 때, 원격 서비스는 HTTP 코드 202(《처리 중…》)를 반환합니다.

  • 원격 서비스가 POST 이후에 출력이 준비되기 전에 HTTP GET 요청을 받으면 HTTP 코드 202를 반환합니다.

  • 원격 서비스는 모든 출력 행을 생성한 후 똑같은 배치 ID로 그다음 HTTP GET 행을 기다린 다음에, HTTP 코드 200(《성공적인 완료…》)과 함께 수신된 행을 반환합니다.

간단히 말해, 수신된 각 배치에 대해 원격 서비스는 결과가 준비될 때까지 202를 반환하고, 그 이후 다음 GET이 결과와 HTTP 200을 수신합니다.

각 배치에 대해, Snowflake는 다음과 같이 비동기 원격 서비스와 함께 작동합니다.

  1. Snowflake가 고유한 배치 ID와 함께 처리할 데이터를 포함한 HTTP POST를 보냅니다.

  2. Snowflake는 HTTP 202 응답을 수신하면 다음 중 하나가 충족될 때까지 루프를 실행합니다.

    • Snowflake가 데이터와 HTTP 200을 수신할 때.

    • Snowflake의 내부 시간 제한에 도달할 때.

    • Snowflake가 오류(예: HTTP 응답 코드 5XX)를 수신할 때.

    루프의 각 반복에서, Snowflake는 지연된 다음 해당 HTTP POST의 배치 ID와 똑같은 배치 ID를 포함하는 HTTP GET을 실행하여 원격 서비스가 올바른 배치에 대한 정보를 반환할 수 있도록 합니다.

    루프 내부의 지연이 짧게 시작하지만, Snowflake의 시간 제한에 도달할 때까지 수신된 각 HTTP 202 응답에 대해 더 길어집니다.

  3. HTTP 200이 반환되기 전에 Snowflake의 시간 제한에 도달하면 Snowflake가 SQL 쿼리를 중단합니다.

    현재 Snowflake의 시간 제한은 10분(600초)이며 이를 사용자가 구성할 수 없습니다. 이 시간 제한은 앞으로 바뀔 수 있습니다.

참고

쿼리가 시간 제한에 걸리는 빈도는 부분적으로 원격 서비스의 확장성에 따라 다릅니다. 원격 서비스가 자주 시간 제한에 걸리는 경우 확장성 에 대한 설명도 참조하십시오.

확장성

원격 서비스, 프록시 서비스 그리고 Snowflake와 원격 서비스 간의 기타 모든 단계에서는 전송되는 피크 워크로드를 처리할 수 있어야 합니다.

일부 클라우드 플랫폼 공급자는 프록시 서비스와 원격 서비스에 대한 기본 사용 제한 또는 다른 할당량이 있어, 외부 함수 호출의 처리량을 제한할 수 있습니다.

Snowflake 웨어하우스 크기 가 클수록 요청이 전송되는 동시성이 증가할 수 있으며, 이런 동시성이 프록시 서비스의 할당량을 초과할 수 있습니다.

사용자는 쿼리 프로필의 Retries due to transient errors 값을 보고 (제한 또는 기타 오류로 인해) Snowflake가 쿼리에 대한 요청 일괄 처리 전송을 재시도해야 했던 횟수를 확인할 수 있습니다.

원격 서비스의 확장성

원격 서비스를 작성하는 개발자는 다음 사항을 고려해야 합니다.

  • 원격 서비스를 호출할 빈도.

  • 호출당 전송되는 행 수.

  • 각 행을 처리하는 데 필요한 리소스.

  • 호출 시간 분포(피크 대 평균).

호출자가 소수의 개발자와 시험자에서 전체 조직으로 바뀌면서 시간이 지남에 따라 용량을 늘려야 할 수 있습니다. 여러 조직에서 원격 서비스를 사용하는 경우 조직 수가 늘어남에 따라 용량을 늘려야 할 수도 있습니다. 더 나아가, 조직의 수와 다양성이 증가함에 따라 워크로드의 규모와 타이밍을 예측하기 더 어려워질 수 있습니다.

원격 서비스 공급자는 피크 워크로드를 처리하기에 충분한 용량을 제공할 책임이 있습니다. 다양한 기술을 사용하여 서비스를 확장할 수 있습니다. 원격 서비스 작성자가 원격 서비스를 관리하는 경우에는 작성자가 피크를 다루기에 충분한 용량으로 서비스를 명시적으로 프로비저닝해야 할 수 있습니다. 또는 작성자가 AWS Lambda와 같이, 호스팅된 자동 크기 조정/탄력적 서비스를 사용하기로 결정할 수도 있습니다.

원격 서비스는 과부하 시 HTTP 응답 코드 429를 반환해야 합니다. Snowflake는 HTTP 429를 확인하면 행 전송 속도를 다시 줄이고 성공적으로 처리되지 않은 행 배치 전송을 다시 시도합니다.

확장성 문제 해결에 대한 자세한 내용은 확장성 및 성능 문제 해결하기 를 참조하십시오.

시스템이 일반적으로 과부하되기 때문이 아니라, 각 개별 호출에 오랜 시간이 걸려서 원격 서비스 호출이 시간 초과되는 경우에는 비동기 원격 서비스 빌드 방법에 대한 설명을 참조하십시오.

프록시 서비스의 확장성

프록시 서비스도 확장 가능해야 합니다. 다행히도, 주요 클라우드 공급자가 제공하는 프록시 서비스는 일반적으로 확장 가능합니다.

하지만 Amazon API Gateway와 Azure API Management를 포함한 일부 프록시 서비스는 기본 사용량 제한이 있습니다. 요청 속도가 제한을 초과하면 이러한 프록시 서비스가 요청을 제한합니다. 필요한 경우 AWS 또는 Azure에 프록시 서비스의 할당량을 늘리도록 요청해야 할 수 있습니다.

외부 함수를 개발하거나 관리하는 사용자는 다음과 같은 플랫폼별 정보를 기억해야 합니다.

Amazon API Gateway

Amazon API Gateway는 그 자체가 사용자의 워크로드에 맞게 자동 크기 조정되는 관리 AWS 서비스입니다. 사용자는 다양한 API Gateway의 제한 사항 에 대해 잘 알고 있어야 합니다.

원격 서비스를 확장하는 데 도움이 되도록 Amazon API Gateway를 구성할 수 있습니다. 특히, API Gateway는 필요한 경우 원격 서비스의 부하를 줄이기 위해 요청의 캐싱 및/또는 제한을 활성화하도록 구성할 수 있습니다.

제한은 시간 제한과 재시도에 영향을 줄 수 있으므로, 사용자는 Snowflake가 시간 제한과 재시도를 처리하는 방식에 대한 정보를 검토할 수도 있습니다.

Azure API Management Service

Azure API Management의 경우 제한은 서비스에 대해 선택한 SKU에 따라 다릅니다. 제한 사항은 Azure 구독 서비스 제한 사항 의 API Management 제한 사항 섹션에 설명되어 있습니다.

제한은 시간 제한과 재시도에 영향을 줄 수 있으므로, 사용자는 Snowflake가 시간 제한과 재시도를 처리하는 방식에 대한 정보를 검토할 수도 있습니다.

확장성 및 성능 문제 해결하기

  • QUERY_HISTORY , QUERY_HISTORY_BY_* 함수를 사용해 성능 특성을 관찰하고 성능 문제를 디버그하는 데 도움을 줍니다.

  • 쿼리 프로필 페이지 를 사용하여 요청당 평균 대기 시간을 확인합니다.

  • 쿼리 프로필 페이지 를 사용하여 원격 서비스가 행마다 정확히 한 번만 전달된다고 가정하지 않기 라는 제목의 섹션에 나열된 오류를 포함하여 일시적 오류로 인해 요청을 재시도한 횟수를 확인합니다.

  • 원격 서비스 리소스 사용량을 모니터링하여 부하에 맞게 확장할 방법을 확인하고 원격 서비스가 피크 부하를 처리하기에 충분한 용량이 갖도록 합니다.

  • Amazon API Gateway 또는 원격 서비스에서 로깅을 활용하여 요청별 세부 정보를 얻습니다.

  • Snowflake가 원격 서비스에 요청을 보낼 때 사용하는 동시성을 제어합니다. 자세한 내용은 동시성 을 참조하십시오.

  • 과부하가 걸릴 때 원격 서비스에서 HTTP 응답 코드 429를 반환합니다. 대기 시간이 늘어날 때까지 기다리지 말고, 가능한 한 빨리 이 코드를 반환하십시오.

  • 프록시 서비스 시간 제한을 고려하십시오. 예를 들어, 2020년 7월 현재 Amazon API Gateway의 제한 시간은 30초입니다. 원격 서비스의 과부하를 비롯한 다양한 요인으로 인해 시간 제한을 초과할 수 있습니다.

Snowflake는 적당한 시간 내에 일시적 오류/시간 제한을 재시도하려고 하지만, 서비스가 계속 과부하되고 재시도에 성공하지 못하면 결국 쿼리가 중단됩니다.

동시성

리소스 요구 사항은 행이 여러 호출에 걸쳐 분산되는 방식에 따라 다릅니다(각각 몇 개의 행이 있는 다수의 병렬 호출과 전체 행 수가 같은 한 번의 호출). 큰 용량을 지원하는 시스템이 반드시 높은 동시성을 지원하는 것은 아니며, 그 반대의 경우도 마찬가지입니다. 필요한 피크 동시성뿐 아니라 최대의 적당한 개별 워크로드를 추정하고, 두 가지 유형의 피크를 모두 처리하기에 충분한 리소스를 제공해야 합니다.

더욱이, 동시성 추정에서는 Snowflake가 외부 함수 호출을 병렬화할 수 있다는 점을 고려해야 합니다. 단일 사용자의 단일 쿼리로 인해 원격 서비스에 대해 여러 호출이 동시에 발생할 수 있습니다. 다음을 비롯한 여러 요인이 Snowflake에서 프록시 서비스 또는 원격 서비스로의 동시 호출 개수에 영향을 미칩니다.

  • 외부 함수로 쿼리를 실행 중인 동시 사용자 수.

  • 각 사용자의 쿼리 크기.

  • 가상 웨어하우스의 컴퓨팅 리소스 양(즉, 웨어하우스 크기).

  • 웨어하우스 개수.

외부 함수에 부작용 이 있는 경우 동시성을 적절하게 처리하는 것이 특히 복잡할 수 있습니다. 결과는 사용자의 행을 처리하는 순서에 따라 달라질 수 있습니다. (Snowflake는 부작용이 있는 원격 서비스를 작성하거나 사용하지 않는 것이 좋습니다.)

신뢰성

원격 서비스가 실행되는 위치에 따라 다음을 고려해야 할 수 있습니다.

  • 신뢰성.

  • 오류 처리.

  • 디버깅.

  • 업그레이드(원격 서비스가 새로운 기능을 추가하거나 버그 수정이 필요한 경우).

원격 서비스가 상태 비저장이 아닌 경우 실패 후 복구를 고려해야 할 수도 있습니다. (Snowflake에서는 원격 서비스를 상태 비저장으로 할 것을 강력히 권장합니다.)

시간 제한 및 재시도에 대한 자세한 내용은 시간 제한 오류에 대한 설명원격 서비스가 행마다 정확히 한 번만 전달된다고 가정하지 않기 를 참조하십시오.