마이크로서비스 설정의 서비스 간 통신

Last reviewed 2023-09-20 UTC

이 문서는 마이크로서비스를 설계, 빌드, 배포하는 방법을 다룬 총 4부로 구성된 시리즈 중 세 번째 문서입니다. 이 시리즈에서는 마이크로서비스 아키텍처의 다양한 요소를 설명하며, 마이크로서비스 아키텍처 패턴의 이점과 단점 및 적용 방법이 포함되어 있습니다.

  1. 마이크로서비스 소개
  2. 모놀리식을 마이크로서비스로 리팩터링
  3. 마이크로서비스 설정의 서비스 간 통신(이 문서)
  4. 마이크로서비스 애플리케이션의 분산 추적

이 시리즈는 모놀리식 애플리케이션을 마이크로서비스 애플리케이션으로 리팩터링하는 마이그레이션을 설계 및 구현하는 애플리케이션 개발자 및 설계자를 대상으로 합니다.

이 문서에서는 비동기식 메시지와 마이크로서비스의 동기식 API 간의 장단점을 설명합니다. 이 문서에서는 모놀리식 애플리케이션의 분해 과정을 안내하고, 원래 애플리케이션의 동기식 요청을 새로운 마이크로서비스 기반 설정에서 비동기식 흐름으로 변환하는 방법을 보여줍니다. 이 변환에는 서비스 간 분산 트랜잭션 구현이 포함됩니다.

예시 애플리케이션

이 문서에서는 Online Boutique라는 전자상거래 애플리케이션을 사전 빌드했습니다. 이 애플리케이션은 상품 탐색, 장바구니에 제품 추가, 결제와 같은 기본 전자상거래 흐름을 구현합니다. 또한 이 애플리케이션은 사용자 선택을 기반으로 한 추천 및 광고를 제공합니다.

서비스의 논리적 분리

이 문서에서는 결제 서비스를 애플리케이션의 나머지 부분에서 격리합니다. 원래 Online Boutique 애플리케이션의 모든 흐름은 동기식입니다. 리팩터링된 애플리케이션에서는 결제 프로세스가 비동기 흐름으로 변환됩니다. 따라서 구매 요청을 받으면 즉시 처리하는 대신 '요청 접수 완료' 확인을 사용자에게 제공합니다. 백그라운드에서는 결제 서비스에 대한 비동기식 요청이 결제 프로세스로 트리거됩니다.

결제 데이터와 로직을 새 서비스로 이동하기 전에 결제 데이터와 로직을 모놀리식에서 격리해야 합니다. 모놀리식에서 결제 데이터와 로직을 격리하면 결제 서비스 경계(비즈니스 로직 또는 데이터)가 잘못되었을 때 동일한 코드베이스에서 코드를 더 쉽게 리팩터링할 수 있습니다.

이 문서에서 모놀리식 애플리케이션의 구성요소는 이미 모듈화되어 있으므로 서로 격리됩니다. 애플리케이션에 보다 긴밀한 상호 종속 항목이 있는 경우 비즈니스 로직을 격리하고 별도의 클래스 및 모듈을 만들어야 합니다. 또한 데이터베이스 종속 항목을 자체 테이블로 분리하고 별도의 저장소 클래스를 만들어야 합니다. 데이터베이스 종속 항목을 분리하면 분할 테이블 간에 외래 키 관계가 존재할 수 있습니다. 하지만 서비스를 모놀리식에서 완전히 분리하면 이러한 종속 항목 존재가 중지되고 서비스는 사전 정의된 API 또는 RPC 계약을 통해 배타적으로 상호작용합니다.

분산 트랜잭션 및 부분적 오류

서비스를 격리하고 모놀리식에서 분할하면 원래 모놀리식 시스템의 로컬 트랜잭션이 여러 서비스에 분산됩니다. 모놀리식 구현에서 결제 프로세스는 다음 다이어그램에 표시된 순서를 따릅니다.

결제 시퀀스는 여러 서비스에 배포됩니다.

그림 1. 모놀리식 구현의 결제 프로세스 시퀀스입니다.

그림 1에서 애플리케이션이 구매주문서를 수신하면 결제 컨트롤러는 결제 서비스 및 주문 서비스를 호출하여 각각 결제를 처리하고 주문을 저장합니다. 단계가 실패하면 데이터베이스 트랜잭션이 롤백될 수 있습니다. 주문 요청이 주문 테이블에 성공적으로 저장되었지만 결제가 실패하는 시나리오 예시를 가정해 보겠습니다. 이 시나리오에서는 전체 트랜잭션이 롤백되고 항목이 주문 테이블에서 삭제됩니다.

자체 서비스로 결제를 분리한 후 수정된 결제 흐름은 다음 다이어그램과 유사합니다.

결제 프로세스는 여러 서비스와 데이터베이스에 걸쳐 있습니다.

그림 2. 결제가 자체 서비스로 분리된 후의 결제 프로세스 시퀀스입니다.

그림 2에서 트랜잭션은 이제 여러 서비스와 해당 데이터베이스를 포괄하므로 분산 트랜잭션입니다. 주문 요청을 받으면 결제 컨트롤러는 주문 세부정보를 로컬 데이터베이스에 저장하고 다른 서비스를 호출하여 주문을 완료합니다. 결제 서비스와 같은 이러한 서비스는 자체 로컬 데이터베이스를 사용하여 주문에 대한 세부정보를 저장할 수 있습니다.

모놀리식 애플리케이션에서 데이터베이스 시스템은 로컬 트랜잭션이 원자적인지 확인합니다. 그러나 기본적으로 각 서비스에 대해 별도의 데이터베이스가 있는 마이크로서비스 기반 시스템에는 여러 데이터베이스에 걸쳐 있는 전역 트랜잭션 코디네이터가 없습니다. 트랜잭션이 중앙에서 조정되지 않으므로 결제 처리에 실패해도 주문 서비스에서 커밋된 변경사항이 롤백되지 않습니다. 따라서 시스템의 일관성이 없습니다.

다음 패턴은 분산 트랜잭션을 처리하는 데 흔히 사용됩니다.

  • 2단계 커밋 프로토콜(2PC): 합의 프로토콜의 일부이며 2PC가 분산 트랜잭션의 커밋과 원자성, 일관성, 격리, 내구성(ACID) 보장을 유지합니다. 프로토콜은 준비커밋 단계로 나뉩니다. 트랜잭션은 모든 참여자가 투표한 경우에만 커밋됩니다. 참여자가 합의에 도달하지 못하면 전체 트랜잭션이 롤백됩니다.
  • Saga: Saga 패턴은 분산 트랜잭션을 구성하는 각 마이크로서비스 내에서 로컬 트랜잭션을 실행하는 것으로 구성됩니다. 이벤트는 성공하거나 실패한 작업이 끝날 때마다 트리거됩니다. 분산 트랜잭션과 관련된 모든 마이크로서비스가 이러한 이벤트를 구독합니다. 다음 마이크로서비스는 성공 이벤트를 수신하면 작업을 실행합니다. 오류가 발생하면 이전의 마이크로서비스가 보정 작업을 완료하여 변경사항을 실행취소합니다. Saga는 모든 단계가 완료될 때 모든 작업이 성공하거나 작업을 보정하여 모든 작업을 실행 취소하도록 함으로써 시스템에 대한 일관된 보기를 제공합니다.

장기 트랜잭션에는 Saga를 사용하는 것이 좋습니다. 마이크로서비스 기반 애플리케이션에서는 서비스 간 호출 및 타사 시스템과의 통신이 필요합니다. 따라서 eventual consistency를 고려하여 설계하는 것이 가장 좋습니다. 이는 복구 가능한 오류를 다시 시도하고 복구 불가능한 오류를 수정하는 보정 이벤트를 노출합니다.

Saga를 구현하는 방법에는 여러 가지가 있습니다. 예를 들어 Apache Airflow, Apache Camel 또는 Conductor와 같은 작업과 워크플로 엔진을 사용할 수 있습니다. Kafka, RabbitMQ 또는 ActiveMQ 기반 시스템을 사용해서 자체 이벤트 핸들러를 작성할 수도 있습니다.

Online Boutique 애플리케이션은 결제 서비스를 사용하여 결제, 배송, 이메일 알림 서비스를 조정합니다. 결제 서비스는 비즈니스 및 주문 워크플로도 처리합니다. 자체 워크플로 엔진을 빌드하는 대신 Zeebe와 같은 타사 구성요소를 사용해도 됩니다. Zeebe는 UI 기반 모델러를 제공합니다. 애플리케이션의 요구사항에 따라 마이크로서비스 조정자를 신중하게 평가하는 것이 좋습니다. 이러한 선택은 마이크로서비스를 실행하고 확장하는 데 중요합니다.

리팩터링된 애플리케이션

리팩터링된 애플리케이션에서 분산 트랜잭션을 사용 설정하기 위해 결제 서비스가 결제, 배송, 이메일 서비스 간의 통신을 처리합니다. 일반 비즈니스 프로세스 모델 및 표기법(BPMN) 워크플로는 다음 흐름을 사용합니다.

리팩터링된 애플리케이션의 트랜잭션은 BPMN 워크플로를 따릅니다.

그림 3. 일반적인 마이크로서비스의 분산 트랜잭션을 보장하는 데 도움이 되는 주문 워크플로

위의 다이어그램은 다음 워크플로를 보여줍니다.

  • 프런트엔드 서비스가 주문 요청을 수신한 후 다음을 수행합니다.
    • 주문 서비스를 장바구니 서비스로 보냅니다. 그러면 장바구니 서비스는 주문 세부정보(Redis)를 저장합니다.
    • 결제 페이지로 리디렉션됩니다. 결제 서비스가 장바구니 서비스에서 주문을 가져오고 주문 상태를 Pending으로 설정하며 고객에게 결제를 요청합니다.
    • 사용자가 결제했는지 확인합니다. 확인되면 결제 서비스에서 이메일 서비스에 확인 이메일을 생성하여 고객에게 전송합니다.
  • 그러면 결제 서비스가 요청을 처리합니다.
    • 결제 요청이 성공하면 결제 서비스가 주문 상태를 Complete로 업데이트합니다.
    • 결제 요청이 실패하면 결제 서비스가 보완 트랜잭션을 시작합니다.
      • 결제 요청이 취소됩니다.
      • 결제 서비스가 주문 상태를 Failed로 변경합니다.
    • 결제 서비스를 사용할 수 없는 경우 N초 후에 요청 시간이 초과되고 결제 서비스가 보정 트랜잭션을 시작합니다.
    • 결제 서비스가 주문 상태를 Failed로 변경합니다.

목표

  • GKE(Google Kubernetes Engine)에 모놀리식 Online Boutique 애플리케이션 배포하기
  • 모놀리식 결제 흐름을 검증하기
  • 리팩터링된 모놀리식 애플리케이션의 마이크로서비스 버전 배포
  • 새 결제 흐름이 작동하는지 확인하기
  • 실패한 경우 분산 트랜잭션 및 보정 작업이 작동하는지 확인하기

비용

이 문서에서는 비용이 청구될 수 있는 다음과 같은 Google Cloud 구성요소를 사용합니다.

프로젝트 사용량을 기준으로 예상 비용을 산출하려면 가격 계산기를 사용하세요. Google Cloud를 처음 사용하는 사용자는 무료 체험판을 사용할 수 있습니다.

이 문서를 마치면 만든 리소스를 삭제하여 비용이 계속 청구되지 않도록 할 수 있습니다. 자세한 내용은 삭제를 참조하세요.

시작하기 전에

  1. Google Cloud Console의 프로젝트 선택기 페이지에서 Google Cloud 프로젝트를 선택하거나 만듭니다.

    프로젝트 선택기로 이동

  2. Google Cloud 프로젝트에 결제가 사용 설정되어 있는지 확인합니다.

  3. Google Cloud 콘솔에서 Cloud Shell을 활성화합니다.

    Cloud Shell 활성화

    Google Cloud 콘솔 하단에서 Cloud Shell 세션이 시작되고 명령줄 프롬프트가 표시됩니다. Cloud Shell은 Google Cloud CLI가 사전 설치된 셸 환경으로, 현재 프로젝트의 값이 이미 설정되어 있습니다. 세션이 초기화되는 데 몇 초 정도 걸릴 수 있습니다.

  4. Compute Engine, Google Kubernetes Engine, Cloud SQL, Artifact Analysis, Container Registry에 API를 사용 설정합니다.

     gcloud services enable \
         compute.googleapis.com \
         sql-component.googleapis.com \
         servicenetworking.googleapis.com\
         container.googleapis.com \
         containeranalysis.googleapis.com \
         containerregistry.googleapis.com \
         sqladmin.googleapis.com
    
  5. 다음 환경 변수를 내보냅니다.

    export PROJECT=$(gcloud config get-value project)
    export CLUSTER=$PROJECT-gke
    export REGION="us-central1"
    

전자상거래 모놀리식 배포

이 섹션에서는 GKE 클러스터에 모놀리식 Online Boutique 애플리케이션을 배포합니다. 이 애플리케이션은 Cloud SQL을 관계형 데이터베이스로 사용합니다. 다음 다이어그램은 모놀리식 애플리케이션 아키텍처를 보여줍니다.

애플리케이션은 모놀리식 아키텍처를 사용합니다.

그림 4. 클라이언트는 GKE 클러스터의 애플리케이션에 연결하고 애플리케이션은 Cloud SQL 데이터베이스에 연결합니다.

애플리케이션을 배포하려면 다음 단계를 완료합니다.

  1. GitHub 저장소를 클론합니다.

    git clone https://github.com/GoogleCloudPlatform/monolith-to-microservices-example
    
  2. Terraform 변수 매니페스트 파일에서 PROJECT_ID 자리표시자를 바꿉니다.

    cd monolith-to-microservices-example/setup && \
    sed -i -e "s/\[PROJECT_ID\]/$PROJECT/g" terraform.tfvars
    
  3. Terraform 스크립트를 실행하여 인프라 설정을 완료하고 인프라를 배포합니다. Terraform에 대한 자세한 내용은 Google Cloud에서 Terraform 시작하기를 참조하세요.

    terraform init && terraform apply -auto-approve
    

    Terraform 스크립트가 다음을 만듭니다.

    • 이름이 PROJECT_ID-vpc인 VPC 네트워크
    • 이름이 PROJECT_ID-gke인 GKE 클러스터
    • 이름이 PROJECT_ID-mysql인 Cloud SQL 인스턴스
      • 애플리케이션에서 사용하는 ecommerce라는 데이터베이스
      • 비밀번호가 password로 설정된 사용자 root

    Terraform 스크립트를 수정하여 비밀번호를 자동 생성할 수 있습니다. 이 설정에서는 프로덕션에서 사용하면 안 되는 간단한 예시를 사용합니다.

    인프라 프로비저닝에는 최대 10분이 걸릴 수 있습니다. 스크립트가 성공하면 출력은 다음과 같이 표시됩니다.

    ...
    
    Apply complete! Resources: 8 added, 0 changed, 0 destroyed.
    
    Outputs:
    
    kubernetes_cluster_name = PROJECT_ID-gke
    sql_database_name = PROJECT_ID-mysql
    vpc_name = PROJECT_ID-vpc
    
  4. 클러스터에 연결하고 monolith라는 네임스페이스를 만듭니다. GKE 클러스터의 자체 네임스페이스에 애플리케이션을 배포합니다.

    gcloud container clusters get-credentials $CLUSTER \
       --region $REGION \
       --project $PROJECT && \
       kubectl create ns monolith
    
  5. GKE에서 실행되는 애플리케이션은 Kubernetes 보안 비밀을 사용하여 Cloud SQL 데이터베이스에 액세스합니다. 데이터베이스에 사용자 인증 정보를 사용하는 보안 비밀을 만듭니다.

    kubectl create secret generic dbsecret \
      --from-literal=username=root \
      --from-literal=password=password -n monolith
    
  6. 모놀리식 이미지를 빌드하고 이를 Container Registry에 업로드합니다.

    cd ~/monolith
    gcloud builds submit --tag gcr.io/$PROJECT_ID/ecomm
    
  7. deploy.yaml 파일의 참조를 새로 만든 Docker 이미지로 업데이트합니다.

    cd ~/monolith
    sed -i -e "s/\[PROJECT_ID\]/$PROJECT/g" deploy.yaml
    
  8. 배포 매니페스트 파일의 자리표시자를 바꾼 다음 애플리케이션을 배포합니다.

    cd .. && \
    DB_IP=$(gcloud sql instances describe $PROJECT-mysql | grep "ipAddress:" | tail -1 | awk -F ":" '{print $NF}')
    
    sed -i -e "s/\[DB_IP\]/$DB_IP/g" monolith/deploy.yaml
    kubectl apply -f monolith/deploy.yaml
    
  9. 배포 상태를 확인합니다.

    kubectl rollout status deployment/ecomm -n monolith
    

    출력은 다음과 같이 표시됩니다.

    Waiting for deployment "ecomm" rollout to finish: 0 of 1 updated replicas are available...
    deployment "ecomm" successfully rolled out
    
  10. 배포된 애플리케이션의 IP 주소를 가져옵니다.

    kubectl get svc ecomm -n monolith \
            -o jsonpath="{.status.loadBalancer.ingress[*].ip}" -w
    

    부하 분산기 IP 주소가 게시될 때까지 기다립니다. 명령어를 종료하려면 Ctrl+C를 누르세요. 부하 분산기 IP 주소를 확인한 후 URL http://IP_ADDRESS에서 애플리케이션에 액세스합니다. 부하 분산기가 정상 상태가 되고 트래픽 전달이 시작되는 데 다소 시간이 걸릴 수 있습니다.

모놀리식 결제 흐름 검증

이 섹션에서는 결제 흐름을 검증하기 위한 테스트 주문을 만듭니다.

  1. 이전 섹션의 http://IP_ADDRESS에 기록한 URL로 이동합니다.
  2. 애플리케이션 홈페이지에 표시되는 아무 제품이나 선택한 다음 장바구니에 추가를 클릭합니다.
  3. 테스트 구매를 만들려면 주문하기를 클릭합니다.
  4. 결제가 완료되면 주문 확인 창이 나타나고 주문 확인 ID가 표시됩니다.
  5. 주문 세부정보를 보려면 데이터베이스에 연결합니다.

    gcloud sql connect $PROJECT-mysql --user=root
    

    또한 다른 지원되는 방법을 사용하여 데이터베이스에 연결할 수 있습니다. 메시지가 표시되면 비밀번호를 password로 입력합니다.

  6. 저장된 주문 세부정보를 보려면 다음 명령어를 실행합니다.

    select cart_id from ecommerce.cart;
    
  7. 출력은 다음과 같이 표시됩니다.

    +--------------------------------------+
    | cart_id                              |
    +--------------------------------------+
    | 7cb9ab11-d268-477f-bf4d-4913d64c5b27 |
    +--------------------------------------+
    

마이크로서비스 기반 전자상거래 애플리케이션 배포

이 섹션에서는 리팩터링된 애플리케이션을 배포합니다. 이 문서에서는 프런트엔드 및 결제 서비스의 분리에만 중점을 둡니다. 이 시리즈의 다음 문서인 마이크로서비스 애플리케이션의 분산 추적에서는 추천 및 광고 서비스와 같이 모놀리식에서 분리할 수 있는 다른 서비스를 설명합니다. 결제 서비스는 프런트엔드 및 결제 서비스 간의 분산 트랜잭션을 처리하고 다음 다이어그램과 같이 GKE 클러스터에 Kubernetes 서비스로 배포됩니다.

프런트엔드와 결제 서비스가 모놀리식에서 분리됩니다.

그림 5. 결제 서비스는 장바구니, 결제, 이메일 서비스 간의 트랜잭션을 조정합니다.

마이크로서비스 배포

이 섹션에서는 앞에서 프로비저닝한 인프라를 사용하여 마이크로서비스를 자체 네임스페이스 microservice에 배포합니다.

  1. 다음 요구사항을 충족해야 합니다.

    • Google Cloud 프로젝트
    • gcloud, git, kubectl을 사용하는 셸 환경
  2. Cloud Shell에서 마이클서비스 저장소를 클론합니다.

    git clone https://github.com/GoogleCloudPlatform/microservices-demo
    cd microservices-demo/
    
  3. Google Cloud 프로젝트 및 리전을 설정하고 GKE API가 사용 설정되었는지 확인합니다.

    export PROJECT_ID=PROJECT_ID
    export REGION=us-central1
    gcloud services enable container.googleapis.com \
    --project=${PROJECT_ID}
    

    Google Cloud 프로젝트의 ID로 바꿉니다.

  4. GKE 클러스터를 만들고 사용자 인증 정보를 가져옵니다.

    gcloud container clusters create-auto online-boutique \
        --project=${PROJECT_ID} --region=${REGION}
    

    클러스터를 만드는 데 몇 분 정도 걸릴 수 있습니다.

  5. 클러스터에 마이크로서비스를 배포합니다.

    kubectl apply -f ./release/kubernetes-manifests.yaml
    
  6. 포드가 준비될 때까지 기다립니다.

    kubectl get pods
    

    몇 분 후 포드가 Running 상태로 표시됩니다.

  7. 프런트엔드의 외부 IP 주소를 사용하여 브라우저에서 웹 프런트엔드에 액세스합니다.

    kubectl get service frontend-external | awk '{print $4}'
    

    웹브라우저에서 http://EXTERNAL_IP를 방문하여 Online Boutique 인스턴스에 액세스합니다.

새 결제 흐름 검증

  1. 결제 프로세스 흐름을 확인하려면 이전 섹션인 모놀리식 결제 흐름 검증에 설명된 대로 제품을 선택하고 주문합니다.
  2. 주문 결제를 완료하면 확인 창에 확인 ID가 표시되지 않습니다. 대신 확인 창에서 확인 세부정보를 보려면 이메일을 확인해야 합니다.
  3. 주문이 수신되었는지, 결제 서비스가 결제를 처리했는지, 주문 세부정보가 업데이트되었는지 확인하려면 다음 명령어를 실행합니다.

    kubectl logs -f deploy/checkoutservice --tail=100
    

    출력은 다음과 같이 표시됩니다.

    [...]
    {"message":"[PlaceOrder] user_id=\"98828e7a-b2b3-47ce-a663-c2b1019774a3\" user_currency=\"CAD\"","severity":"info","timestamp":"2023-08-10T04:19:20.498893921Z"}
    {"message":"payment went through (transaction_id: f0b4a592-026f-4b4a-9892-ce86d2711aed)","severity":"info","timestamp":"2023-08-10T04:19:20.528338189Z"}
    {"message":"order confirmation email sent to \"someone@example.com\"","severity":"info","timestamp":"2023-08-10T04:19:20.540275988Z"}
    

    로그를 종료하려면 Ctrl+C를 누릅니다.

  4. 결제가 완료되었는지 확인합니다.

    kubectl logs -f deploy/paymentservice -n --tail=100
    

    출력은 다음과 같이 표시됩니다.

    [...]
    {"severity":"info","time":1691641282208,"pid":1,"hostname":"paymentservice-65cc7795f6-r5m8r","name":"paymentservice-charge","message":"Transaction processed: visa ending 0454     Amount: CAD119.30128260"}
    {"severity":"info","time":1691641300051,"pid":1,"hostname":"paymentservice-65cc7795f6-r5m8r","name":"paymentservice-server","message":"PaymentService#Charge invoked with request {\"amount\":{\"currency_code\":\"USD\",\"units\":\"137\",\"nanos\":850000000},\"credit_card\":{\"credit_card_number\":\"4432-8015-6152-0454\",\"credit_card_cvv\":672,\"credit_card_expiration_year\":2039,\"credit_card_expiration_month\":1}}"}
    

    로그를 종료하려면 Ctrl+C를 누릅니다.

  5. 주문 확인 이메일이 전송되는지 확인합니다.

    kubectl logs -f deploy/emailservice -n --tail=100
    

    출력은 다음과 같이 표시됩니다.

    [...]
    {"timestamp": 1691642217.5026057, "severity": "INFO", "name": "emailservice-server", "message": "A request to send order confirmation email to kalani@examplepetstore.com has been received."}
    

    각 마이크로서비스의 로그 메시지는 결제, 결제, 이메일 서비스 간의 분산 트랜잭션이 성공적으로 완료되었음을 나타냅니다.

분산 트랜잭션의 보정 작업 검증

이 섹션에서는 고객이 주문하고 결제 서비스가 다운되는 시나리오를 시뮬레이션합니다.

  1. 서비스를 사용할 수 없는 상황을 시뮬레이션하려면 결제 배포와 서비스를 삭제합니다.

    kubectl delete deploy paymentservice && \
    kubectl delete svc paymentservice
    
  2. 애플리케이션에 다시 액세스하여 결제 흐름을 완료합니다. 이 예시에서 결제 서비스가 응답하지 않으면 요청 시간이 초과되고 보정 작업이 트리거됩니다.

  3. UI 프런트엔드에서 주문하기 버튼을 클릭합니다. 다음과 유사한 결과가 출력됩니다.

    HTTP Status: 500 Internal Server Error
    rpc error: code = Internal desc = failed to charge card: could not charge the card: rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing: dial tcp: lookup paymentservice on 34.118.224.10:53: no such host"
    failed to complete the order
    main.(*frontendServer).placeOrderHandler
        /src/handlers.go:360
    
  4. 프런트엔드 서비스 로그를 검토합니다.

    kubectl logs -f deploy/frontend --tail=100
    

    다음과 유사한 결과가 출력됩니다.

    [...]
    {"error":"failed to complete the order: rpc error: code = Internal desc = failed to charge card: could not charge the card: rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing: dial tcp: lookup paymentservice on 34.118.224.10:53: no such host\"","http.req.id":"0a4cb058-ee9b-470a-9bb1-3a965636022e","http.req.method":"POST","http.req.path":"/cart/checkout","message":"request error","session":"96c94881-a435-4490-9801-c788dc400cc1","severity":"error","timestamp":"2023-08-11T18:25:47.127294259Z"}
    
  5. 결제 서비스 로그를 검토합니다.

    kubectl logs -f deploy/frontend --tail=100
    

    다음과 유사한 결과가 출력됩니다.

    [...]
    {"message":"[PlaceOrder] user_id=\"96c94881-a435-4490-9801-c788dc400cc1\" user_currency=\"USD\"","severity":"info","timestamp":"2023-08-11T18:25:46.947901041Z"}
    {"message":"[PlaceOrder] user_id=\"96c94881-a435-4490-9801-c788dc400cc1\" user_currency=\"USD\"","severity":"info","timestamp":"2023-08-11T19:54:21.796343643Z"}
    

    알림 전송을 위한 이메일 서비스에 대한 후속 호출은 없다는 점에 유의하세요. payment went through (transaction_id: 06f0083f-fa47-4d91-8258-6d61edfab1ca)와 같은 트랜잭션 로그는 없습니다.

  6. 이메일 서비스 로그를 검토합니다.

    kubectl logs -f deploy/emailservice --tail=100
    

    이메일 서비스에서 실패한 트랜잭션에 대해 생성된 로그 항목이 없습니다.

조정자로서 서비스 호출이 실패하면 결제 서비스가 오류 상태를 반환하고 결제 프로세스를 종료합니다.

삭제

이 튜토리얼에서 사용된 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 리소스가 포함된 프로젝트를 삭제하거나 프로젝트를 유지하고 개별 리소스를 삭제하세요.

이 시리즈의 다음 문서인 마이크로서비스 애플리케이션의 분산 추적 단계를 완료하려면 프로젝트와 리소스를 삭제하지 말고 다시 사용하면 됩니다.

프로젝트 삭제

  1. Google Cloud 콘솔에서 리소스 관리 페이지로 이동합니다.

    리소스 관리로 이동

  2. 프로젝트 목록에서 삭제할 프로젝트를 선택하고 삭제를 클릭합니다.
  3. 대화상자에서 프로젝트 ID를 입력한 후 종료를 클릭하여 프로젝트를 삭제합니다.

리소스 삭제

이 문서에서 사용한 Google Cloud 프로젝트를 유지하려면 개별 리소스를 삭제합니다.

  1. Cloud Shell에서 다음 명령어를 실행합니다.

    cd setup && terraform destroy -auto-approve
    
  2. Google Cloud CLI를 사용하여 마이크로서비스 클러스터를 삭제하려면 다음 명령어를 실행하세요.

    gcloud container clusters delete online-boutique \
        --location $REGION
    

다음 단계