GCP Workflows를 해봤어요.
25737 단어 GoGCPMicro Servicesworkflowstech
TL;DR
Workflows
서버 없는 워크플로우를 사용하여 Google Cloud 및 HTTP 기반 API 서비스를 직접 수행합니다.
Workflows를 사용하면 yaml의 정의에 따라 절차에 따라 API를 적절하게 호출할 수 있기 때문에 아래의 블로그를 참고하여 Workflows를 시도해 보겠습니다.
Micor Services에 시달리는 일
Micor 서비스에서 곤란한 일 중 하나는 거래를 관리하는 것이다.
EC 사이트의 상품 주문 처리를 예로 들면 대략적인 주문 처리 중
monolith 서비스라면 하나의 DB 거래를 통해 원자 처리를 할 수도 있다.만약 재고 통제 후 결산 처리가 실패한다면 함께 롤백을 해서 취소할 수 있습니다.
그러나 만약에 마이크로소프트를 사용하고 주문서를 관리하는order 서비스, 재고를 관리하는stock 서비스, 결제를 관리하는payment 서비스를 사용한다면 저는 자주 분리되어 실시되고 싶습니다.
이 경우 재고 억제 후 결제 처리에 실패했을 때 재고 억제 처리가 완료됐다고 가정해 단순히 롤백을 할 수 없다.또한 결제 실패는 가retry의 임시 오류나 네트워크 문제로 인해 콜의 한 쪽이 오류,timeout 등이지만 콜의 서비스 한 쪽은 정상적으로 처리를 마쳤다.상황따라서 幂 등성을 보장하는 API 실현과 적당한 retry 등이 필요하다.
Workflows로 해결
Workflows를 사용하여 상술한 주문 처리를 처리해 보십시오.
제각기
있는 경우 프로세스는 다음과 같습니다
미리 준비하다
샘플의 코드는 다음과 같다.
샘플 코드에 기초하여 준비
gcloud services enable run.googleapis.com workflows.googleapis.com cloudbuild.googleapis.com
PROJECT_ID=XXXXXXX make build_services
// gcloud builds submit --tag gcr.io/$(PROJECT_ID)/order-service services/order
PROJECT_ID=XXXXXXX make deploy_services
// gcloud run deploy stock-service \
// --image gcr.io/$(PROJECT_ID)/stock-service \
// --platform=managed --region=us-central1 \
// --no-allow-unauthenticated
SERVICE_ACCOUNT_NAME="cloud-run-invoker"
SERVICE_ACCOUNT_EMAIL=${SERVICE_ACCOUNT_NAME}@${PROJECT_ID}.iam.gserviceaccount.com
gcloud iam service-accounts create $SERVICE_ACCOUNT_NAME \
--display-name "Cloud Run Invoker"
SERVICE_NAME="order-service"
gcloud run services add-iam-policy-binding $SERVICE_NAME \
--member=serviceAccount:$SERVICE_ACCOUNT_EMAIL \
--role=roles/run.invoker \
--platform=managed --region=us-central1
gcloud run services add-iam-policy-binding $SERVICE_NAME \
--member=serviceAccount:$SERVICE_ACCOUNT_EMAIL \
--role=roles/run.viewer \
--platform=managed --region=us-central1
※同様のことをSERVICE_NAME=stock-service, payment-serviceに書き換えて実行
위의 워크플로우.yml.template를 기반으로 개별 서비스의 URL을 덮어씁니다.yml 만들기
먼저 각 서비스 URL을 가져옵니다.
SERVICE_NAME="order-service"
ORDER_SERVICE_URL=$(gcloud run services list --platform managed \
--format="table[no-heading](URL)" --filter="SERVICE:${SERVICE_NAME}")
여분의 부분을 생략한yaml은 다음과 같다.main:
params: [args]
steps:
- reserveStock:
call: http.post
args:
url: https://STOCK_SERVICE_URL/reserve
body:
"unit": ${args.unit}
auth:
type: OIDC
result: reserveStockResult
- switchByReserveStock:
switch:
- condition: ${reserveStockResult.body.status == "reserved"}
next: authorizePayment
next: voidOrder
- authorizePayment:
call: http.post
args:
url: https://PAYMENT_SERVICE_URL/authorize
body:
"price": ${args.price}
auth:
type: OIDC
result: authorizePaymentResult
- switchByAuthorizePayment:
switch:
- condition: ${authorizePaymentResult.body.status == "authorized"}
next: updateOrder
next: cancelReservedStock
- updateOrder:
call: http.post
args:
url: https://ORDER_SERVICE_URL/update
auth:
type: OIDC
result: updateOrderResult
next: finish
- cancelReservedStock:
call: http.post
args:
url: https://STOCK_SERVICE_URL/cancelReserve
auth:
type: OIDC
result: cancelReservedStockResult
next: voidOrder
- voidOrder:
call: http.post
args:
url: https://ORDER_SERVICE_URL/void
auth:
type: OIDC
result: voidOrderResult
next: finish
- finish:
return: ${reserveStockResult.body}
상기 작업을 수행할 때https://STOCK_SERVICE_URL/reserve
을 실행하고 파라미터의 unit 부분을 실행하여 재고 처리를 억제한다.결과는 reserveStockResult에 저장PROJECT_ID=XXXXXXX SERVICE_ACCOUNT=XXXXXXX make deploy_workflow
// gcloud workflows deploy workflow-test \
// --source=workflow.yml \
// --service-account=$(SERVICE_ACCOUNT)
deploy가 성공하면 GCP의 홈페이지에서 프로세스를 도형적으로 볼 수 있다이렇게 준비하면 완성!
실제로 실행해 보도록 하겠습니다.
workflow는order 서비스
/create
에서 호출됩니다.일단 정상적인 상황을 실행해 보도록 하겠습니다.
curl -X POST -H "Authorization: Bearer $(gcloud auth print-identity-token)" \
-H "Content-Type: application/json" \
-d '{"unit":20, "price":100}' \
-s https://ORDER-SERVICE-URL/create | jq .
실행 후 로그 확인주문 접수 -> 재고 관리 -> 결산 처리 -> 주문 업데이트를 순차적으로 수행
다음은 재고가 부족한 리퀘스트를 만들어 보세요.
curl -X POST -H "Authorization: Bearer $(gcloud auth print-identity-token)" \![](https://storage.googleapis.com/zenn-user-upload/sm3y7x8ip27zn2tkra2t0rn79m24)
-H "Content-Type: application/json" \
-d '{"unit":999, "price":100}' \
-s https://ORDER-SERVICE-URL/create | jq .
주문 수리 -> 재고 부족-> 주문 취소 순서대로 집행다음 재고는 OK인데 결제에 실패한 리퀘스트를 해보세요.
curl -X POST -H "Authorization: Bearer $(gcloud auth print-identity-token)" \![](https://storage.googleapis.com/zenn-user-upload/sm3y7x8ip27zn2tkra2t0rn79m24)
-H "Content-Type: application/json" \
-d '{"unit":5, "price":9999999}' \
-s https://ORDER-SERVICE-URL/create | jq .
주문 접수-> 재고 억제-> 결산 처리-> 잔액 부족-> 억제된 재고 취소-> 주문 취소 순서대로 집행얼마나 쉬운지...^^
다시 해봐요.
Micro 서비스가 불안정한 경우 주기성을 시도할 수 있도록 워크플로우에서 일정 횟수를 지정하십시오 (retry의 API에 멱이 있는 경우)
main:
params: [args]
steps:
- reserveStock:
try:
call: http.post
args:
url: https://STOCK_SERVICE_URL/reserve
body:
"unit": ${args.unit}
"unstable": ${args.unstable}
auth:
type: OIDC
timeout: 10
result: reserveStockResult
retry:
predicate: ${custom_predicate}
max_retries: 10
backoff:
initial_delay: 1
max_delay: 30
multiplier: 2
custom_predicate:
params: [e]
steps:
- what_to_repeat:
switch:
- condition: ${e.code == 500}
return: True
- otherwise:
return: False
는 위에서 말한 바와 같이 지정try
,retry
을 통해retry를 진행할 수 있다.이 경우 httpstatus=500의 경우retry를 진행합니다.매개 변수에
unstable=true
를 지정하면 일정 확률로 되돌아온다InternalServerError
.아래와 같이 리퀘스트를 하면 error가 리트리에 걸릴 확률이 있을 것입니다.
curl -X POST -H "Authorization: Bearer $(gcloud auth print-identity-token)" \
-H "Content-Type: application/json" \
-d '{"unit":20, "price":100, "unstable":true}' \
-s https://ORDER-SERVICE-URL/create | jq .
로그 확인stock service is unstable
2회 발생 후 재고 억제에 성공했다.payment service is unstable
3회 발생 후 결제 처리에 성공하면 주문서가 확정된 기록을 확인할 수 있습니다.또 그렇게 쉬운데...^^
총결산
우리는 마이크로 서비스 간의 거래를 가정하고 GCP의Workflows를 시도했다.지금까지 이런 처리를 할 때 응용 프로그램은state 관리를 함께 해야 했지만 Workflows를 사용하면 같은 일을 할 수 있다.
pros
신경 쓰이는 일
참고 자료
Reference
이 문제에 관하여(GCP Workflows를 해봤어요.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/ogataka50/articles/fde9633be02080텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)