中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Serverless怎么將配置化思想復用到平臺系統中

發布時間:2021-12-16 12:00:07 來源:億速云 閱讀:173 作者:柒染 欄目:云計算

這期內容當中小編將會給大家帶來有關Serverless怎么將配置化思想復用到平臺系統中,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

什么是 Serverless

Serverless 由兩部分組成,Server 和 Less。

  • 前者可以理解為其解決方案范圍處在服務端;

  • 后者可以譯為少量的;

組合起來就是較少服務端干預的服務端解決方案。

與 Serverless 相對的是 Serverfull,比較下對應的概念可能更便于理解。

Serverfull 時代,研發交付流程一般有三個角色:RD,PM,QA。

RD 根據 PM 的 PRD 進行功能開發,交付到 QA 進行測試,測試完成之后發布到服務器。由運維人員規劃服務器規格、數量、機房部署、節點擴縮容等,這種更多由人力處理的時代就是 Serverfull 時代。

之后進入了 DevOps 時代。這個時代運維自己開發一套運維控制臺,可以讓研發同學在控制臺上自己進行服務觀測、數據查詢、運維處理等,運維同學的工作輕松了不少,這個階段主要釋放了運維同學的人力。

而到了 Serverless 時代,這套運維控制臺能力越來越豐富,可以實現按配置的自動擴縮容、性能監控、DevOps 流水線等,同時侵入到研發流程側,比如自動發布流水線、編譯打包、代碼質量監測、灰度發布、彈性擴縮等流程基本不需要人力處理了,這就是 Serverless 時代。

Serverless 怎么用

相信你有過這樣的經歷,在一個 Web 界面上,左側寫代碼,右側展示執行效果。

  • 寫的是代碼塊,代碼數量不會特別大;

  • 代碼運行速度快;

  • 支持多種編程語言;

  • 可以支持不可預計的流量洪峰沖擊。

抽象來說,前端只需要將代碼片段和編程語言的標識傳給 Server 端即可,等待響應結果。Server 端可以針對于不同編程語言進行 runtime 分類、預處理等工作。

Serverless 怎么做

很多人把 Serverless 看做是 FC(function compute:函數計算),使用函數計算,無需業務自己搭建 IT 基礎設施,只需要編碼并上傳代碼。函數計算會按需為你準備好計算資源,彈性、可靠地運行,并提供 trace、日志查詢、監控告警等治理能力。

在 FC 中有服務和函數之分。一個服務可以包含多個函數。我們可以用微服務理解,我們通過 golang 或 java 搭建了一個微服務架構,而 FC 服務就是其中的類,FC 函數是類中的一個方法。

區別在于 Java 搭建的微服務只能運行 java 類代碼,golang 的類只能運行 go 寫的代碼,而 FC 函數可以安裝不同語言的 runtime,支持運行不同語言程序。

類比理解之后,我們再看下如何調用 FC 的函數,一般的 FC 解決方案里面都有一個觸發器的概念。比如 HTTP 觸發器、對象存儲觸發器、日志服務觸發器、定時任務觸發器、CDN 觸發器、消息隊列觸發器等。觸發器是對于 FC 函數調用的抽象收口,比如 HTTP 觸發器一般都類比網關的一個 http 請求事件,或是指定對象存儲路徑下上傳了一個圖片,這些觸發事件的入口都可以是觸發器。

觸發器產生事件之后可以調用 FC 函數,函數執行的邏輯可以是下載一張圖片或是注冊一個用戶。

這樣從觸發器到 FC 函數邏輯處理就是一個 FC 的生命周期了。

那么 FC 是如何實現高可用的呢?

其實每個函數底層代碼都是運行在一套 IaaS 平臺上,使用 IaaS 資源,我們可以為每個函數設置運行代碼時需要的內存配置即可,比如最小 128M,最大 3G 等。研發人員不需要關心代碼運行在什么樣的服務器上,不需要關心啟動了多少函數實例支持當前場景,不需要關注背后的彈性擴縮問題,這些都被收斂在 FC 之后。

有兩種高可用策略:

  • 給函數設置并發實例數,比如 3 個,那么當有三個請求進來時,該函數只啟動一個實例,但是會啟動三個線程來運行邏輯;

  • 線程達到上限后,會再拉起一個函數實例。

那么 Serverless 如何提效呢?

  • 效率高:如果新加了語言,只需要創建一個對應的 Runtime 的 FC 函數即可;

  • 高可用:通過多線程、多實例兩種方式保障高可用,且函數實例擴縮容完全由 FC 自助處理,不需要運維做任何配置;

  • 成本低:在沒有觸發器請求時,函數實例不會被拉起,也不會計費,所以在流量低谷期間或者夜間時,FC 消耗的成本是非常低的。

如何在云平臺創建一個 FC

1. 創建服務

  • 首先新建一個服務名稱;

  • 選定服務部署的地區(背后幫助你就近部署在目標機房);

  • 選擇是否打開調試日志(開發過程開啟,線上運行時可關閉)。

2. 創建函數

有了服務之后就可以創建函數了,比如選擇基于 http 請求的函數。

  • 選擇函數綁定的服務;

  • 設置函數名稱;

  • 選擇 runtime 環境;

  • 是否要求函數實例彈性;

  • 函數入口(觸發器直接調用的目標方法);

  • 函數執行內存;

  • 函數執行超時時間;

  • 設置實例并發度。

配置觸發器,比如選擇了 HTTP 觸發器,然后在觸發器上綁定函數名稱,由于是 http 訪問,可以選擇訪問的鑒權、認證方式,以及請求方式 POST or GET。

3. 代碼編寫

當函數創建好了之后,進入函數,可以看到描述、代碼執行歷史、觸發器類型、日志查詢頁等。
如果是 HTTP 觸發器,需要配置 http 觸發路徑。

類似于類里面的一個函數,上下文請求會打到這里,直接執行。

Python 代碼為例:

# -*- coding: utf-8 -*-
import logging
import urllib.parse
import time
import subprocess
def handler(environ, start_response):
    context = environ['fc.context']
    request_uri = environ['fc.request_uri']
    for k, v in environ.items():
      if k.startswith('HTTP_'):
        pass
    try:        
        request_body_size = int(environ.get('CONTENT_LENGTH', 0))    
    except (ValueError):        
        request_body_size = 0   
    # 獲取用戶傳入的code
    request_body = environ['wsgi.input'].read(request_body_size)  
    codeStr = urllib.parse.unquote(request_body.decode("GBK"))
    # 因為body里的對象里有code和input兩個屬性,這里分別獲取用戶code和用戶輸入
    codeArr = codeStr.split('&')
    code = codeArr[0][5:]
    inputStr = codeArr[1][6:]
    # 將用戶code保存為py文件,放/tmp目錄下,以時間戳為文件名
    fileName = '/tmp/' + str(int(time.time())) + '.py'
    f = open(fileName, "w")
    # 這里預置引入了time庫
    f.write('import time \r\n')
    f = open(fileName, "a")
    f.write(code)
    f.close()
    # 創建子進程,執行剛才保存的用戶code py文件
    p = subprocess.Popen("python ">

流程如下:

  • 前端傳入代碼片段,格式是字符串;

  • 在 FC 函數中獲取到傳入的代碼字符串,截取 code 內容和 input 內容;

  • 將代碼保存為一個 py 文件,以時間戳為文件命名,保存在 FC 函數的 /tmp 目錄下,每個函數有自己獨立的 /tmp 目錄;

  • import time 庫代碼;

  • 通過 subprocess 創建子流程,以 shell 方式通過 py 命令執行保存在 /tmp 目錄下的 py 文件;

  • 最后讀取執行結果返回給前端。

整個過程只需要前端將代碼傳入到 FC 函數里面,整個 Server 端各個環節都不需要研發與運維同學關心,體現了 Serverless 的精髓。

用 Serverless 協調工作流

工作流可以用順序、分支、并行等方式來編排任務執行,之后流程會按照設定好的步驟可靠地協調任務執行,跟蹤每個任務的狀態切換,并在必要時執行定義的重試邏輯,確保流程順利執行。

工作流流程通過記錄日志和審計方式來監視工作流的執行,便于流程的診斷與調試。

系統靈活性與擴展性的核心是服務可編排,所以我們需要做的是將現有系統內部用戶希望定制的功能進行梳理、拆分、抽離、結合 FC 提供的無狀態能力,將這些功能點進行編排,實現業務流程的定制。

需靈活配置工作流的業務

舉個例子,比如餐飲場景下不同商家可以配置不同的支付方式,可以走微信支付、銀聯支付、支付寶支付。可以同時支持三家,也可以某一家,可以到付,也可以積分兌換等。如果沒有一個好的配置化流程解決方案的話,系統中會出現大量硬編碼規則判斷條件,系統迭代疲于奔命,是個不可持續的過程。

有了 FC 搭建的工作流就可以很優雅地解決這種問題。

上面的流程是用戶側的流程,接下來需要轉換成程序側的流程,通過約束的 FDL 創建工作流。

FDL 代碼如下:

version: v1beta1
type: flow
timeoutSeconds: 3600
steps:
  - type: task
    name: generateInfo
    timeoutSeconds: 300
    resourceArn: acs:mns:::/topics/generateInfo-fnf-demo-jiyuan/messages
    pattern: waitForCallback
    inputMappings:
      - target: taskToken
        source: $context.task.token
      - target: products
        source: $input.products
      - target: supplier
        source: $input.supplier
      - target: address
        source: $input.address
      - target: orderNum
        source: $input.orderNum
      - target: type
        source: $context.step.name
    outputMappings:
      - target: paymentcombination
        source: $local.paymentcombination
      - target: orderNum
        source: $local.orderNum
    serviceParams:
      MessageBody: $
      Priority: 1
    catch:
      - errors:
          - FnF.TaskTimeout
        goto: orderCanceled
  -type: task
    name: payment
    timeoutSeconds: 300
    resourceArn: acs:mns:::/topics/payment-fnf-demo-jiyuan/messages
    pattern: waitForCallback
    inputMappings:
      - target: taskToken
        source: $context.task.token
      - target: orderNum
        source: $local.orderNum
      - target: paymentcombination
        source: $local.paymentcombination
      - target: type
        source: $context.step.name
    outputMappings:
      - target: paymentMethod
        source: $local.paymentMethod
      - target: orderNum
        source: $local.orderNum
      - target: price
        source: $local.price
      - target: taskToken
        source: $input.taskToken
    serviceParams:
      MessageBody: $
      Priority: 1
    catch:
      - errors:
          - FnF.TaskTimeout
        goto: orderCanceled
  - type: choice
    name: paymentCombination
    inputMappings:
      - target: orderNum
        source: $local.orderNum
      - target: paymentMethod
        source: $local.paymentMethod
      - target: price
        source: $local.price
      - target: taskToken
        source: $local.taskToken
    choices:
      - condition: $.paymentMethod == "zhifubao"
        steps:
          - type: task
            name: zhifubao
            resourceArn: acs:fc:cn-hangzhou:your_account_id:services/FNFDemo-jiyuan/functions/zhifubao-fnf-demo
            inputMappings:
              - target: price
                source: $input.price            
              - target: orderNum
                source: $input.orderNum
              - target: paymentMethod
                source: $input.paymentMethod
              - target: taskToken
                source: $input.taskToken
      - condition: $.paymentMethod == "weixin"
        steps:
          - type: task
            name: weixin
            resourceArn: acs:fc:cn-hangzhou:your_account_id:services/FNFDemo-jiyuan.LATEST/functions/weixin-fnf-demo
            inputMappings:
            - target: price
              source: $input.price            
            - target: orderNum
              source: $input.orderNum
            - target: paymentMethod
              source: $input.paymentMethod
            - target: taskToken
              source: $input.taskToken
      - condition: $.paymentMethod == "unionpay"
        steps:
          - type: task
            name: unionpay
            resourceArn: acs:fc:cn-hangzhou:your_account_id:services/FNFDemo-jiyuan.LATEST/functions/union-fnf-demo
            inputMappings:
            - target: price
              source: $input.price            
            - target: orderNum
              source: $input.orderNum
            - target: paymentMethod
              source: $input.paymentMethod
            - target: taskToken
              source: $input.taskToken
    default:
      goto: orderCanceled
  - type: task
    name: orderCompleted
    resourceArn: acs:fc:cn-hangzhou:your_account_id:services/FNFDemo-jiyuan.LATEST/functions/orderCompleted
    end: true
  - type: task
    name: orderCanceled
    resourceArn: acs:fc:cn-hangzhou:your_account_id:services/FNFDemo-jiyuan.LATEST/functions/cancerOrder

示例體現了基于 Serverless 的 FC 可實現靈活工作流。

流程如何觸發的呢?

在用戶選擇完商品、填完地址之后,通過拉取商品、訂單上下文,可以自動化觸發流程了。

在微服務背景下,很多能力不是閉環在單體代碼邏輯之內,很多時候是多個業務系統的連接,比如串聯多個 OpenAPI 接口實現。

如想使用流程引擎需要進行相關的備案鑒權:

@Configuration
public class FNFConfig {
    @Bean
    public IAcsClient createDefaultAcsClient(){
        DefaultProfile profile = DefaultProfile.getProfile(
                "cn-xxx",          // 地域ID
                "ak",      // RAM 賬號的AccessKey ID
                "sk"); // RAM 賬號Access Key Secret
        IAcsClient client = new DefaultAcsClient(profile);
        return client;
    }
}

startFNF 代碼里面流程如何串聯起來:

  • 輸入要啟動的流程名稱,比如每次訂單編號作為啟動流程實例名稱;

  • 流程啟動后的流程實例名稱;

  • 啟動輸入參數,比如業務參數,比如一個 json 里面有商品、商家、地址、訂單等上下文信息。

@GetMapping("/startFNF/{fnfname}/{execuname}/{input}")
    public StartExecutionResponse startFNF(@PathVariable("fnfname") String fnfName,
                                           @PathVariable("execuname") String execuName,
                                           @PathVariable("input") String inputStr) throws ClientException {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("fnfname", fnfName);
        jsonObject.put("execuname", execuName);
        jsonObject.put("input", inputStr);
        return fnfService.startFNF(jsonObject);
    }

再看下 fnfService.startFNF:

@Override
    public StartExecutionResponse startFNF(JSONObject jsonObject) throws ClientException {
        StartExecutionRequest request = new StartExecutionRequest();
        String orderNum = jsonObject.getString("execuname");
        request.setFlowName(jsonObject.getString("fnfname"));
        request.setExecutionName(orderNum);
        request.setInput(jsonObject.getString("input"));
        JSONObject inputObj = jsonObject.getJSONObject("input");
        Order order = new Order();
        order.setOrderNum(orderNum);
        order.setAddress(inputObj.getString("address"));
        order.setProducts(inputObj.getString("products"));
        order.setSupplier(inputObj.getString("supplier"));
        orderMap.put(orderNum, order);
        return iAcsClient.getAcsResponse(request);
    }
  • 第一部分是啟動流程;

  • 第二部分是創建訂單對下,并模擬入庫。

前端如何調用?

在前端當點擊選擇商品和商家頁面中的下一步后,通過 GET 方式調用 HTTP 協議的接口 /startFNF/{fnfname}/{execuname}/{input}。和上面的 Java 方法對應。

  • fnfname:要啟動的流程名稱;

  • execuname:隨機生成 uuid,作為訂單的編號,也作為啟動流程實例的名稱;

  • input:將商品、商家、訂單號、地址構建為 JSON 字符串傳入流程。

submitOrder(){
                const orderNum = uuid.v1()
                this.$axios.$get('/startFNF/OrderDemo-Jiyuan/'+orderNum+'/{\n' +
                    '  "products": "'+this.products+'",\n' +
                    '  "supplier": "'+this.supplier+'",\n' +
                    '  "orderNum": "'+orderNum+'",\n' +
                    '  "address": "'+this.address+'"\n' +
                    '}' ).then((response) => {
                    console.log(response)
                    if(response.message == "success"){
                        this.$router.push('/orderdemo/' + orderNum)
                    }
                })
            }

1. generateInfo 節點

先看下第一個 FDL 節點定義:

- type: task
    name: generateInfo
    timeoutSeconds: 300
    resourceArn: acs:mns:::/topics/generateInfo-fnf-demo-jiyuan/messages
    pattern: waitForCallback
    inputMappings:
      - target: taskToken
        source: $context.task.token
      - target: products
        source: $input.products
      - target: supplier
        source: $input.supplier
      - target: address
        source: $input.address
      - target: orderNum
        source: $input.orderNum
      - target: type
        source: $context.step.name
    outputMappings:
      - target: paymentcombination
        source: $local.paymentcombination
      - target: orderNum
        source: $local.orderNum
    serviceParams:
      MessageBody: $
      Priority: 1
    catch:
      - errors:
          - FnF.TaskTimeout
        goto: orderCanceled
```


- name:節點名稱;
- timeoutSeconds:超時時間,節點等待時長,超過時間后跳轉到 goto 分支指向的 orderCanceled 節點;
- pattern:設置為 waitForCallback,表示需要等待確認;
- inputMappings:該節點入參;
   - taskToken:Serverless 工作流自動生成的 Token;
   - products:選擇的商品;
   - supplier:選擇的商家;
   - address:送餐地址;
   - orderNum:訂單號;
- outputMappings:該節點的出參;
   - paymentcombination:該商家支持的支付方式;
   - orderNum:訂單號;
- catch:捕獲異常,跳轉到其他分支。


Serverless 工作流支持多個云服務集成,將其他服務作為任務步驟的執行單元。服務集成方式通過 FDL 表達式實現,在任務步驟中,可以使 用resourceArn 來定義集成的目標服務,使用 pattern 定義集成模式。


在 resourceArn 中配置 /topics/generateInfo-fnf-demo-jiyuan/messages 信息,就是集成了 MNS 消息隊列服務,當 generateInfo 節點觸發后會向 generateInfo-fnf-demo-jiyuanTopic 中發送一條消息。消息的正文和參數在 serviceParams 對象中 zhi'd 指定。MessageBody 是消息正文,配置 $ 表示通過輸入映射 inputMappings 產生消息正文。

generateInfo-fnf-demo 函數:

向 generateInfo-fnf-demo-jiyuanTopic 中發送的這條消息包含了商品信息、商家信息、地址、訂單號,表示一個下訂單流程的開始,既然有發消息,那么必然有接受消息進行后續處理。在函數計算控制臺,創建服務,在服務下創建名為 generateInfo-fnf-demo 的事件觸發器函數,這里選擇 Python Runtime:

![17.png](https://ucc.alicdn.com/pic/developer-ecology/89d43991349e422e8bda26f905cce0c4.png)

創建 MNS 觸發器,選擇監聽 generateInfo-fnf-demo-jiyuanTopic:

![18.png](https://ucc.alicdn.com/pic/developer-ecology/4612a6cd4ba54dc38a79cebf7cacc3ac.png)

打開消息服務 MNS 控制臺,創建 generateInfo-fnf-demo-jiyuanTopic:

![19.png](https://ucc.alicdn.com/pic/developer-ecology/f51714a2ee594dcba4bbbc888c42288c.png)

接下來寫函數代碼:
-- coding: utf-8 --
import logging
import json
import time
import requests
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkfnf.request.v20190315 import ReportTaskSucceededRequest
from aliyunsdkfnf.request.v20190315 import ReportTaskFailedRequest
def handler(event, context):

1. 構建Serverless工作流Client

region = "cn-hangzhou"
account_id = "XXXX"
ak_id = "XXX"
ak_secret = "XXX"
fnf_client = AcsClient(
    ak_id,
    ak_secret,
    region
)
logger = logging.getLogger()
# 2. event內的信息即接受到Topic generateInfo-fnf-demo-jiyuan中的消息內容,將其轉換為Json對象
bodyJson = json.loads(event)
logger.info("products:">
代碼分五部分:

- 構建 Serverless 工作流 Client;

- event 內的信息即接受到 TopicgenerateInfo-fnf-demo-jiyuan 中的消息內容,將其轉換為 Json 對象;

- 判斷什么商家使用什么樣的支付方式組合,這里的示例比較簡單粗暴,正常情況下,應該使用元數據配置的方式獲取。比如在系統內有商家信息的配置功能,通過在界面上配置該商家支持哪些支付方式,形成元數據配置信息,提供查詢接口,在這里進行查詢;

- 調用 Java 服務暴露的接口,更新訂單信息,主要是更新支付方式;

- 給予 generateInfo 節點響應,并返回數據,這里返回了訂單號和支付方式。因為該節點的 pattern 是 waitForCallback,所以需要等待響應結果。

generateInfo-fnf-demo 函數配置了 MNS 觸發器,當 TopicgenerateInfo-fnf-demo-jiyuan 有消息后就會觸發執行 generateInfo-fnf-demo 函數。

### 2. payment 節點

接下來是 payment 的 FDL 代碼定義:
  • type: task
    name: payment
    timeoutSeconds: 300
    resourceArn: acs:mns:::/topics/payment-fnf-demo-jiyuan/messages
    pattern: waitForCallback
    inputMappings:

    • FnF.TaskTimeout
      goto: orderCanceled

    • target: taskToken
      source: $context.task.token

    • target: orderNum
      source: $local.orderNum - target: paymentcombination source: $local.paymentcombination

    • target: type
      source: $context.step.name outputMappings: - target: paymentMethod source: $local.paymentMethod

    • target: orderNum
      source: $local.orderNum - target: price source: $local.price

    • target: taskToken
      source: $input.taskToken serviceParams: MessageBody: $
      Priority: 1
      catch:

    • errors:

當流程流轉到 payment 節點后,用戶就可以進入到支付頁面。

payment 節點會向 MNS 的 Topicpayment-fnf-demo-jiyuan 發送消息,會觸發 payment-fnf-demo 函數。

payment-fnf-demo 函數:

payment-fnf-demo 函數的創建方式和 generateInfo-fnf-demo 函數類似。

# -*- coding: utf-8 -*-
import logging
import json
import os
import time
import logging
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkcore.client import AcsClient
from aliyunsdkfnf.request.v20190315 import ReportTaskSucceededRequest
from aliyunsdkfnf.request.v20190315 import ReportTaskFailedRequest
from mns.account import Account  # pip install aliyun-mns
from mns.queue import *
def handler(event, context):
    logger = logging.getLogger()
    region = "xxx"
    account_id = "xxx"
    ak_id = "xxx"
    ak_secret = "xxx"
    mns_endpoint = "http://your_account_id.mns.cn-hangzhou.aliyuncs.com/"
    queue_name = "payment-queue-fnf-demo"
    my_account = Account(mns_endpoint, ak_id, ak_secret)
    my_queue = my_account.get_queue(queue_name)
    # my_queue.set_encoding(False)
    fnf_client = AcsClient(
        ak_id,
        ak_secret,
        region
    )
    eventJson = json.loads(event)
    isLoop = True
    while isLoop:
        try:
            recv_msg = my_queue.receive_message(30)
            isLoop = False
            # body = json.loads(recv_msg.message_body)
            logger.info("recv_msg.message_body:======================">

上面代碼核心思路是等待用戶在支付頁面選擇某個支付方式確認支付。使用了 MNS 的隊列來模擬等待。循環等待接收隊列 payment-queue-fnf-demo 中的消息,當收到消息后將訂單號和用戶選擇的具體支付方式以及金額返回給 payment 節點。

前端選擇支付方式頁面:

經過 generateInfo 節點后,該訂單的支付方式信息已經有了,所以對于用戶而言,當填完商品、商家、地址后,跳轉到的頁面就是該確認支付頁面,并且包含了該商家支持的支付方式。

進入該頁面后,會請求 Java 服務暴露的接口,獲取訂單信息,根據支付方式在頁面上顯示不同的支付方式。

當用戶選定某個支付方式點擊提交訂單按鈕后,向 payment-queue-fnf-demo 隊列發送消息,即通知 payment-fnf-demo 函數繼續后續的邏輯。

使用了一個 HTTP 觸發器類型的函數,用于實現向 MNS 發消息的邏輯,paymentMethod-fnf-demo 函數代碼:

# -*- coding: utf-8 -*-
import logging
import urllib.parse
import json
from mns.account import Account  # pip install aliyun-mns
from mns.queue import *
HELLO_WORLD = b'Hello world!\n'
def handler(environ, start_response):
    logger = logging.getLogger() 
    context = environ['fc.context']
    request_uri = environ['fc.request_uri']
    for k, v in environ.items():
      if k.startswith('HTTP_'):
        # process custom request headers
        pass
    try:       
        request_body_size = int(environ.get('CONTENT_LENGTH', 0))   
    except (ValueError):       
        request_body_size = 0  
    request_body = environ['wsgi.input'].read(request_body_size) 
    paymentMethod = urllib.parse.unquote(request_body.decode("GBK"))
    logger.info(paymentMethod)
    paymentMethodJson = json.loads(paymentMethod)
    region = "cn-xxx"
    account_id = "xxx"
    ak_id = "xxx"
    ak_secret = "xxx"
    mns_endpoint = "http://your_account_id.mns.cn-hangzhou.aliyuncs.com/"
    queue_name = "payment-queue-fnf-demo"
    my_account = Account(mns_endpoint, ak_id, ak_secret)
    my_queue = my_account.get_queue(queue_name)
    output = "{\"paymentMethod\": \"%s\", \"price\":\"%s\">

函數的邏輯很簡單,就是向 MNS 的隊列 payment-queue-fnf-demo 發送用戶選擇的支付方式和金額。

3. paymentCombination 節點

paymentCombination 節點是一個路由節點,通過判斷某個參數路由到不同的節點,以 paymentMethod 作為判斷條件:

- type: choice
    name: paymentCombination
    inputMappings:
      - target: orderNum
        source: $local.orderNum
      - target: paymentMethod
        source: $local.paymentMethod
      - target: price
        source: $local.price
      - target: taskToken
        source: $local.taskToken
    choices:
      - condition: $.paymentMethod == "zhifubao"
        steps:
          - type: task
            name: zhifubao
            resourceArn: acs:fc:cn-hangzhou:your_account_id:services/FNFDemo-jiyuan/functions/zhifubao-fnf-demo
            inputMappings:
              - target: price
                source: $input.price            
              - target: orderNum
                source: $input.orderNum
              - target: paymentMethod
                source: $input.paymentMethod
              - target: taskToken
                source: $input.taskToken
      - condition: $.paymentMethod == "weixin"
        steps:
          - type: task
            name: weixin
            resourceArn: acs:fc:cn-hangzhou:your_account_id:services/FNFDemo-jiyuan.LATEST/functions/weixin-fnf-demo
            inputMappings:
            - target: price
              source: $input.price            
            - target: orderNum
              source: $input.orderNum
            - target: paymentMethod
              source: $input.paymentMethod
            - target: taskToken
              source: $input.taskToken
      - condition: $.paymentMethod == "unionpay"
        steps:
          - type: task
            name: unionpay
            resourceArn: acs:fc:cn-hangzhou:your_account_id:services/FNFDemo-jiyuan.LATEST/functions/union-fnf-demo
            inputMappings:
            - target: price
              source: $input.price            
            - target: orderNum
              source: $input.orderNum
            - target: paymentMethod
              source: $input.paymentMethod
            - target: taskToken
              source: $input.taskToken
    default:
      goto: orderCanceled

流程是,用戶選擇支付方式后,通過消息發送給 payment-fnf-demo 函數,然后將支付方式返回,于是流轉到 paymentCombination 節點通過判斷支付方式流轉到具體處理支付邏輯的節點和函數。

4. zhifubao 節點

看一個 zhifubao 節點:

choices:
      - condition: $.paymentMethod == "zhifubao"
        steps:
          - type: task
            name: zhifubao
            resourceArn: acs:fc:cn-hangzhou:your_account_id:services/FNFDemo-jiyuan/functions/zhifubao-fnf-demo
            inputMappings:
              - target: price
                source: $input.price            
              - target: orderNum
                source: $input.orderNum
              - target: paymentMethod
                source: $input.paymentMethod
              - target: taskToken
                source: $input.taskToken

節點的 resourceArn 和之前兩個節點的不同,這里配置的是函數計算中函數的 ARN,也就是說當流程流轉到這個節點時會觸發 zhifubao-fnf-demo 函數,該函數是一個事件觸發函數,但不需要創建任何觸發器。流程將訂單金額、訂單號、支付方式傳給 zhifubao-fnf-demo 函數。

zhifubao-fnf-demo 函數:

# -*- coding: utf-8 -*-
import logging
import json
import requests
import urllib.parse
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkfnf.request.v20190315 import ReportTaskSucceededRequest
from aliyunsdkfnf.request.v20190315 import ReportTaskFailedRequest
def handler(event, context):
  region = "cn-xxx"
  account_id = "xxx"
  ak_id = "xxx"
  ak_secret = "xxx"
  fnf_client = AcsClient(
    ak_id,
    ak_secret,
    region
  )
  logger = logging.getLogger()
  logger.info(event)
  bodyJson = json.loads(event)
  price = bodyJson["price"]
  taskToken = bodyJson["taskToken"]
  orderNum = bodyJson["orderNum"]
  paymentMethod = bodyJson["paymentMethod"]
  logger.info("price:">

代碼邏輯很簡單,接收到金額后,將金額打 8 折,然后將價格更新回訂單。其他支付方式的節點和函數如法炮制,變更實現邏輯就可以。在這個示例中,微信支付打了 5 折,銀聯支付打 7 折。

以上是一個基于 Serverless 的 FC 實現的工作流,模擬構建了一個訂單模塊,規則包括:

  • 配置商家和支付方式的元數據規則;

  • 確認支付頁面的元數據規則。

在實際項目中,需要將可定制的部分抽象為元數據描述,需要有配置界面供運營或商家定制支付方式也就是元數據規則,然后前后端頁面基于元數據信息展示相應的內容。

如果之后需要接入新的支付方式,只需要在 paymentCombination 路由節點中確定好路由規則,之后增加對應的支付方式函數即可,通過增加元數據配置項,就可以在頁面展示新加的支付方式,并路由到新的支付函數中。

經過整篇文章相信很多人對于 Serverless 的定義,以及如何基于現有的公有云系統的 Serverless 功能實現商業能力已經有了一定的了解,甚至基于此有實力的公司可以自研一套 Serverless 平臺。當然思想是相同的,其實文中很多邏輯與理論不止適用于 Serverless,就是我們日常基于微服務的平臺化/中臺化解決方案,都可以從中獲取設計營養在工作中應用。

上述就是小編為大家分享的Serverless怎么將配置化思想復用到平臺系統中了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

英山县| 西乌珠穆沁旗| 山东省| 邓州市| 荔波县| 武夷山市| 泊头市| 黎川县| 崇左市| 利津县| 义乌市| 高清| 砚山县| 盐亭县| 滨州市| 兴海县| 个旧市| 连云港市| 明星| 芜湖县| 沅陵县| 枞阳县| 共和县| 广平县| 琼海市| 广元市| 娄烦县| 湖州市| 永福县| 古蔺县| 平定县| 长垣县| 沈阳市| 建始县| 永寿县| 安义县| 青田县| 大埔区| 博野县| 深州市| 新龙县|