日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

分布式多步驟事務(wù)

更新時(shí)間:

本文介紹了如何使用Serverless 工作流提供長(zhǎng)流程分布式事務(wù)保證,幫助用戶聚焦于自身業(yè)務(wù)邏輯。

簡(jiǎn)介

復(fù)雜的業(yè)務(wù)場(chǎng)景例如電商網(wǎng)站、酒店、航班預(yù)定這類涉及訂單管理的應(yīng)用通常要訪問多個(gè)遠(yuǎn)程服務(wù),并且對(duì)操作事務(wù)性語(yǔ)義(即所有步驟全部成功或全部失敗,不存在中間狀態(tài))有較高要求。在流量較小、數(shù)據(jù)存儲(chǔ)集中的應(yīng)用中,事務(wù)性可以通過關(guān)系型數(shù)據(jù)庫(kù)提供的ACID特性滿足。然而在大流量場(chǎng)景下,為了高可用和可擴(kuò)展性,業(yè)務(wù)通常選擇向微服務(wù)的分布式架構(gòu)方向演進(jìn)。在這樣的架構(gòu)中提供多步驟事務(wù)性的保證通常需要引入隊(duì)列和數(shù)據(jù)庫(kù)來持久化消息以及展現(xiàn)流程狀態(tài),這類系統(tǒng)的開發(fā)和運(yùn)維會(huì)給業(yè)務(wù)方帶來額外的成本和負(fù)擔(dān)。而使用Serverless 工作流提供長(zhǎng)流程分布式事務(wù)保證會(huì)幫您解決這些問題。

場(chǎng)景描述

假設(shè)某應(yīng)用為其用戶提供預(yù)定火車票、航班和酒店的功能,要求三個(gè)步驟保證事務(wù)性。該功能需要三個(gè)遠(yuǎn)程調(diào)用實(shí)現(xiàn)(例如預(yù)定火車票需要調(diào)用12306接口),如果三個(gè)調(diào)用都成功則該訂單成功。然而實(shí)際上任何一個(gè)遠(yuǎn)程調(diào)用都有可能會(huì)失敗,因此該應(yīng)用需要對(duì)不同的失敗場(chǎng)景做出相應(yīng)的補(bǔ)償邏輯,回退已完成操作。如下圖所示:

  • 如果預(yù)定火車票(BuyTrainTicket)成功,而預(yù)定航班(ReserveFlight)失敗,則需要取消已經(jīng)購(gòu)買的火車票(CancelTrainTicket),并告知您訂單失敗。
  • 如果預(yù)定火車票(BuyTrainTicket)和預(yù)定航班(ReserveFlight)均成功,但是預(yù)訂酒店(ReserveHotel)失敗,則需要取消已經(jīng)預(yù)定的航班(CancelFlight)和火車票(CancelTrainTicket),并告知您訂單失敗。
longtxn-saga_train_flight_hotel

Serverless 工作流實(shí)現(xiàn)

下文的示例將FC函數(shù)編排成一個(gè)Serverless 工作流流程從而實(shí)現(xiàn)了一個(gè)可靠的多步驟長(zhǎng)流程,該示例分為3步:

  1. 創(chuàng)建FC函數(shù)
  2. 創(chuàng)建流程
  3. 執(zhí)行并查看結(jié)果

步驟1:創(chuàng)建FC函數(shù)

本步驟是模擬場(chǎng)景案例中提示的三個(gè)操作即預(yù)訂火車票、預(yù)訂航班及預(yù)定酒店。

創(chuàng)建下面的Python2.7的函數(shù),關(guān)于創(chuàng)建的詳細(xì)步驟,請(qǐng)參見FC文檔,建議命名:
  • Service: fnf-demo
  • Function: Operation

Operation函數(shù)模擬各操作(例如預(yù)定航班、預(yù)定酒店)的實(shí)現(xiàn),根據(jù)輸入決定該操作執(zhí)行結(jié)果(成功或失敗)。

import json
import logging
import uuid

def handler(event, context):
  evt = json.loads(event)
  logger = logging.getLogger()
  id = uuid.uuid4()
  op = "operation"
  if 'operation' in evt:
    op = evt['operation']
    if op in evt:
      result = evt[op]
      if result == False:
        logger.info("%s failed" % op)
        exit()
  logger.info("%s succeeded, id %s" % (op, id))
  return '{"%s":"success", "%s_txnID": "%s"}' % (op, op, id)         

步驟2:創(chuàng)建流程

使用Serverless工作流控制臺(tái)創(chuàng)建下面的流程。

  1. 配置流程RAM角色
    {
        "Statement": [
            {
                "Action": "sts:AssumeRole",
                "Effect": "Allow",
                "Principal": {
                    "Service": [
                        "fnf.aliyuncs.com"
                    ]
                }
            }
        ],
        "Version": "1"
    }                               
  2. 流程定義
    version: v1
    type: flow
    steps:
      - type: task
        resourceArn: acs:fc:{region}:{accountID}:services/fnf-demo/functions/Operation
        name: BuyTrainTicket
        inputMappings:
        - target: operation
          source: buy_train_ticket
        - target: buy_train_ticket
          source: $input.buy_train_ticket_result
        catch: 
        - errors:
          - FC.Unknown
          goto: OrderFailed
      - type: task
        resourceArn: acs:fc:{region}:{accountID}:services/fnf-demo/functions/Operation
        name: ReserveFlight
        inputMappings:
        - target: operation
          source: reserve_flight
        - target: reserve_flight
          source: $input.reserve_flight_result
        catch:  # 捕獲ReserveFlight task拋出的FC.Unknown錯(cuò)誤,跳轉(zhuǎn)到CancelTrainTicket。
        - errors:
          - FC.Unknown
          goto: CancelTrainTicket
      - type: task
        resourceArn: acs:fc:{region}:{accountID}:services/fnf-demo/functions/Operation
        name: ReserveHotel
        inputMappings:
        - target: operation
          source: reserve_hotel
        - target: reserve_hotel
          source: $input.reserve_hotel_result
        retry:  # 對(duì)FC.Unknown類型的錯(cuò)誤最多指數(shù)退避重試3次,初始間隔1s,后續(xù)間隔=上次間隔*2。
        - errors:
          - FC.Unknown
          intervalSeconds: 1
          maxAttempts: 3
          multiplier: 2
        catch:  # 捕獲ReserveHotel task拋出的FC.Unknown錯(cuò)誤,跳轉(zhuǎn)到CancelFlight。
          - errors:
            - FC.Unknown
            goto: CancelFlight
      - type: succeed
        name: OrderSucceeded
      - type: task
        resourceArn: acs:fc:{region}:{accountID}:services/fnf-demo/functions/Operation
        name: CancelFlight
        inputMappings:
        - target: operation
          source: cancel_flight
        - target: reserve_flight_txnID
          source: $local.reserve_flight_txnID
      - type: task
        resourceArn: acs:fc:{region}:{accountID}:services/fnf-demo/functions/Operation
        name: CancelTrainTicket
        inputMappings:
        - target: operation
          source: cancel_train_ticket
        - target: reserve_flight_txnID
          source: $local.reserve_flight_txnID
      - type: fail
        name: OrderFailed                              

步驟3:執(zhí)行并查看結(jié)果

在控制臺(tái)上對(duì)創(chuàng)建好的流程(Flow)開始一個(gè)新的執(zhí)行(Execution)。StartExecution API要求傳入JSON格式的輸入。下面的JSON對(duì)象可以模擬每個(gè)步驟的成功或失敗(例如"reserve_hotel_result":"fail"代表模擬預(yù)定酒店這步失敗)。StartExecution是一個(gè)異步API,調(diào)用結(jié)束后,Serverless 工作流會(huì)返回一個(gè)執(zhí)行名字用來查詢流程執(zhí)行狀態(tài)。

{
  "buy_train_ticket_result":"success",
  "reserve_flight_result":"success",
  "reserve_hotel_result":"fail"
}                       

流程執(zhí)行開始后,在Serverless 工作流控制臺(tái)可以查看流程的執(zhí)行過程和結(jié)果。從步驟信息頁(yè)簽?zāi)梢钥吹剑捎?span data-tag="ph" id="codeph-lt9-s10-wb0" class="ph">"reserve_hotel_result":"fail"ReserveHotel函數(shù)調(diào)用失敗,Serverless 工作流按照流程定義,依次取消航班(CancelFlight)、取消火車票(CancelTrainTicket)。Serverless 工作流每個(gè)步驟轉(zhuǎn)換有持久化的保證,因此網(wǎng)絡(luò)中斷或進(jìn)程崩潰等失敗場(chǎng)景不會(huì)影響流程事務(wù)性的保證。

Screen Shot 2019-06-26 at 12.14.50 PM

流程執(zhí)行會(huì)產(chǎn)生執(zhí)行歷史事件(event),這些事件可以通過控制臺(tái)、SDK或CLI調(diào)用GetExecutionHistory API查詢。

Screen Shot 2019-06-26 at 12.17.26 PM

錯(cuò)誤處理和重試

  1. 上面示例中的預(yù)定航班、預(yù)定酒店等遠(yuǎn)程調(diào)用都有可能受到網(wǎng)絡(luò)或服務(wù)錯(cuò)誤等原因?qū)е抡{(diào)用失敗,而增加對(duì)瞬時(shí)錯(cuò)誤的重試可以提高訂單流程成功率。Serverless 工作流在任務(wù)(Task)類型的步驟(Step)自帶重試功能,如預(yù)定酒店這個(gè)步驟用下面的寫法可以實(shí)現(xiàn)對(duì)FC.Unknown類型的錯(cuò)誤指數(shù)退避。假設(shè)重試到達(dá)最大次數(shù)后ReserveHotel都無法成功,按照該步驟中catch的定義,ReserveHotel函數(shù)拋出的FC.Unknown錯(cuò)誤會(huì)被捕獲并將跳轉(zhuǎn)到CancelFlight執(zhí)行定義好的補(bǔ)償邏輯。
      - type: task
        resourceArn: acs:fc:{region}:{accountID}:services/fnf-demo/functions/Operation
        name: ReserveHotel
        inputMappings:
        - target: operation
          source: reserve_hotel
        retry:  # 對(duì)FC.Unknown類型的錯(cuò)誤最多指數(shù)退避重試3次,初始間隔1s,后續(xù)間隔=上次間隔*2。
        - errors:
          - FC.Unknown
          intervalSeconds: 1
          maxAttempts: 3
          multiplier: 2
        catch: # 捕獲ReserveHotel task拋出的FC.Unknown錯(cuò)誤,跳轉(zhuǎn)到CancelFlight。
          - errors:
            - FC.Unknown
            goto: CancelFlight           
  2. 下圖可以看到加入重試之后預(yù)訂酒店(ReserveHotel)任務(wù)執(zhí)行了多次直到最大重試數(shù)。Screen Shot 2019-06-26 at 12.19.55 PM

步驟間的數(shù)據(jù)傳遞

  1. 預(yù)定酒店失敗后需要取消航班和火車票,這兩部分別需要用到預(yù)定航班和預(yù)定火車票返回的交易ID(txnID),下面的inputMapping對(duì)象描述了如何將之前步驟產(chǎn)生的輸出傳入CancelFlight這個(gè)步驟中。
      - type: task
        resourceArn: acs:fc:{region}:{accountID}:services/fnf-demo/functions/Operation
        name: CancelFlight
        inputMappings:
        - target: operation
          source: cancel_flight
        - target: reserve_flight_txnID
          source: $local.reserve_flight_txnID
                        
  2. 流程執(zhí)行各步驟結(jié)束的輸出都會(huì)被放在StepExited事件詳情(EventDetail)的local對(duì)象中。
      {  
         "input":{
            "operation":"reserve_hotel",
            "reserve_hotel_result":"fail"
         },
         "local":{
            "buy_train_ticket":"success",
            "buy_train_ticket_txnID":"d37412b3-bb68-4d04-9d90-c8c15643d45e",
            "reserve_flight_result":"success",
            "reserve_flight_txnID":"024caecf-cfa3-43a6-b561-9b6fe0571b55"
         },
         "resourceArn":"acs:fc:{region}:{accountID}:services/fnf-demo/functions/Operation",
         "cause":"{\"errorMessage\":\"Process exited unexpectedly before completing request (duration: 12ms, maxMemoryUsage: 9.18MB)\"}",
         "error":"FC.Unknown",
         "retryCount":3,
         "goto":"CancelFlight"
      }         
  3. 結(jié)合上面的EventDetailinputMappings的映射之后,傳入到CancelFlight步驟的輸入變成如下JSON對(duì)象,這樣CancelFlight函數(shù)的輸入會(huì)包含reserve_flight_txnID字段。
      "input":{
        "operation":"cancel_flight",
        "reserve_flight_txnID":"024caecf-cfa3-43a6-b561-9b6fe0571b55"
      }