快速上手亞馬遜的 Serverless 服務

什麼是 Serverless ?

定義

引用一段對於 Serverless 較爲官方的定義:「Serverless 是一種執行模型(execution model)。在這種模型中,雲服務商負責經過動態地分配資源來執行一段代碼。雲服務商僅僅收取執行這段代碼所須要資源的費用。代碼一般會被運行在一個無狀態的容器內,而且可被多種事件觸發( http 請求、數據庫事件、監控報警、文件上傳、定時任務……)。代碼經常會以函數(function)的形式被上傳到雲服務商以供執行,所以 Serverless 也會被稱做 Functions as a Service 或者 FaaS。」html

從定義中不難看出 Serverless 的出現免去了工程師在開發應用時對服務器與後端運維的考量,使工程師能夠全心全意地投入業務邏輯代碼的實現中去。再歸納一下 Serverless 老生常談的幾條優點:前端

  • 應用開發迅速
  • 無須考慮運維
  • 按用量收費

對於開發者的意義

  • 對於前端開發者來講,Serverless 的出現無疑大大下降了編寫後端應用的門檻,而且賦予前端開發者開發完整先後端應用的能力。
  • 對於企業及獨立開發者來講,Serverless 的出現大大縮短了業務從開發至上線的時間,甚至可能會改變企業的傳統先後端合做模式與人員結構。

應用場景

Serverless 對於前端開發者來講主要會有如下幾個應用場景node

  • 開發後端接口:這是 Serverless 目前最爲普遍應用的場景。經過搭配數據庫等後端服務,能夠實現低門檻、高效率的後端接口開發。
  • 代替 NodeJS 服務器:Serverless 能夠代替傳統的 NodeJS 服務器,使咱們能夠更爲便捷地實現原有的功能,例如後端數據適配前端、服務端渲染等。
  • 搭建基於事件的服務:Serverless 基於事件觸發的特性註定了它極爲適合用於搭建基於事件的服務。例如咱們能夠經過監聽特定的數據庫事件來觸發相關的業務邏輯。

什麼是 AWS Lambda ?

AWS Lambda 是由亞馬遜雲服務平臺( AWS )最先推出於 2014 年、最爲著名的 Serverless 雲計算平臺之一。相較於其餘雲服務商,AWS Lambda 以完善的設施(觸發器種類多、支持編程語言多……)和豐富的社區支持在多數評測中佔據了上風。從體驗與學習的目的出發,AWS Lambda 能夠說是咱們的不二選擇。git

Serverless 與 AWS Lambda 現存的問題

冷啓動

冷啓動是最常被提到的問題之一,用簡單的話來講就是當你的函數一段時間未被運行後,系統就會回收運行函數的容器資源。這樣帶來負面影響就是,當下一次調用這個函數時,就須要從新啓動一個容器來運行你的函數,結果就是函數的調用會被延遲。來看一下在 AWS Lambda 上函數調用時間間隔與冷啓動機率的關係:github

那麼具體的延遲時間是多少呢?延遲時間受許多因素的影響,好比編程語言、函數的內存配置、函數的文件大小等等。可是一個較爲廣泛的建議就是 Lambda 不適合用做對延遲極其敏感的服務(< 50ms)。web

遷移

在使用 AWS Lambda 開發應用時,咱們所寫的代碼與 AWS 這個雲服務商是具備強關聯性的。儘管目前有一些框架(例以下文會應用到的 Serverless 框架)來幫助咱們抹平不一樣服務商之間的代碼差別,想從一個服務商遷移至另外一個服務商依然是一件繁重的體力勞動,甚至包含着必定的代碼重構。數據庫

代碼維護

函數式的開發模式註定了代碼之間的複用與共享會成爲一個難題,也註定了代碼量會隨着服務的增多而膨脹。 Serverless 會使得函數數量與代碼量呈線性增加的關係,以下圖npm

當服務達到必定數量後,維護一個無限膨脹的代碼庫所須要的額外人力與開支也是不可小視的。編程

本地開發

運行 AWS Lambda 的函數依賴於許多外部的庫和應用(aws-sdk、API Gateway、DynamoDB...),所以想要在一個徹底本地的環境運行這樣的函數是十分困難的。若是咱們每次修改函數後都須要部署並依賴於 AWS CloudWatch 中輸出的運行日誌來調試與開發 Lambda 函數,那想必效率是極低的。 Serverless CLI 對於本地開發難的問題,提供了必定的插件來支持(serverless-offlineserverless-dynamodb-local...)。不使用 Serverless CLI 開發 Lambda 的用戶可能就須要研讀官方提供的 AWS-SAM 文檔來配置本地開發環境了。json

計價方式

AWS Lambda 收費的最小單位是 100ms ,也就是意味着你的函數哪怕只執行了 1ms 也會看成 100ms 來計費。這種計費方式在某些狀況下甚至會致使使用高內存的函數比低內存的要便宜。咱們來看下 AWS Lambda 的計費表:

舉一個較爲極端的例子:假設咱們設置了一個內存爲 448MB 的函數,它運行時間爲 101ms ,那麼每次執行咱們都須要支付 0.000000729 x 2 = $0.000001458 。而若是咱們將這個函數的內存提升到 512MB ,使它的運行時間下降 100ms 之內,那麼每次執行咱們只須要支付 $0.000000834 。僅僅是一個設置,咱們就下降了整整 (1458 - 834) / 1458 ≈ 42.8% 的成本!

找到性價比最高的內存設置意味着額外的工做量,很難想象 AWS 在這個問題上竟然沒有爲客戶提供一個合理的解決方案。

捆綁消費

在使用 AWS Lambda 時幾乎全部的周邊服務(API Gateway、CloudWatch、DynamoDB...)都是須要額外收費的。其中一個很明顯的特徵就是捆綁消費,你可能很難想象 CloudWatch 是在使用 Lambda 時被強制使用的一個服務;而 API Gateway 也是在搭建 http 服務時幾乎沒法逃過的一個收費站,其 $3.5/百萬次請求 的高額價格甚至遠遠高於使用 Lambda 的價格。

與傳統雲主機的費用權衡

AWS Lambda 對於低計算複雜度、低流量的應用是有着絕對的價格優點的。可是當部署在 Lambda 上的函數複雜度與流量逐漸上升的時候,使用 Lambda 的成本是有可能在某一時間點超過傳統雲主機的。就比如使用 Lambda 是租車,而使用傳統雲主機是買車。但從另外一角度看,使用 Serverless 服務又能夠節省必定的開發與運維成本。所以對於「Serverless 與傳統雲主機誰更節省成本」這個問題,不只與具體開發的應用類型有關,也與應用的開發模式密不可分,該問題的真正答案極可能只有經過精密的成本計算與實踐才能得出。

如何選擇?

雖然 Lambda 有以上值得權衡的問題,但它所帶來對於開發效率的提升是前所未有的,它所帶來對於服務器及運維層面的成本削減也是肉眼可見的。全面而且客觀地瞭解 Lambda 的長處與短處是決定是否使用它的必要步驟。目前許多的外國企業及開發者已漸漸開始擁抱與接納 Serverless 的開發模式,儘管國內可能對於 Serverless 應用範圍並非很廣,儘早地瞭解與熟悉 Serverless 相信對於國內開發者來講也是百利而無一害的。

在 AWS Lambda 上搭建服務

在瞭解了 Serverless 與 AWS Lambda 後,接下來咱們就能夠着手在 AWS Lambda 上開發應用了。

目標

接下來時間內,咱們要在 Lambda 上部署一套在應用開發中較爲常見的用戶服務,主要有註冊、登陸、與接口訪問權限校驗的功能,包含如下四個接口

  • /api/user/signup - 建立一個新用戶並錄入數據庫
  • /api/user/login - 登陸並返回 JSON Web Token 來讓用戶訪問私有接口
  • /api/public - 公共接口,無須登陸的用戶也可訪問
  • /api/private - 私有接口,只有登陸後的用戶才能訪問

預備知識

  • JavaScript 基礎語法

  • JSON Web Token

  • Serverless 應用框架

    Serverless

    這裏的 Serverless 指的是一個在 GitHub 上超 過 3 萬星的 CLI 工具。經過 Serverless CLI ,咱們能夠快速生成 Lambda 應用服務模版,標準化、工程化服務的開發以及一鍵部署服務至多套的環境與節點,極大地縮短了服務開發至上線的時間。

準備材料

建立工程

咱們選擇的語言是 JavaScript ,數據庫是 AWS 提供的 DynamoDb ,從 Serverless CLI 的示例庫中很快能夠找到這樣的模版 aws-node-rest-api-with-dynamodb

複製模版至本地做爲起步工程

serverless install -u https://github.com/serverless/examples/tree/master/aws-node-rest-api-with-dynamodb
複製代碼

這個工程包含了一個 Todo 列表的 CRUD 操做服務。核心文件有:

  • serverless.yml 定義了該服務所提供的 Lambda 函數 、觸發函數的 觸發器 以及運行該函數所須要的其餘 AWS 資源

  • package.json 定義了該服務所依賴的其餘庫。

  • todos 目錄下包含了全部的函數文件。咱們能夠看到函數都是較爲直白的,每個文件都是相似如下的結構:

    const AWS = require('aws-sdk'); // 引入 AWS SDK
    const dynamoDb = new AWS.DynamoDB.DocumentClient(); // 建立 dynamoDb 實例
    
    // 經過 module.exports 來導出該函數
    module.exports.create = (
      event, // event 對象包含了關於觸發該函數事件的信息,每一個觸發事件 event 包含的信息都會有所不一樣,具體可參閱文檔
      context, // context 對象包含了有關函數調用、執行環境等信息,具體可參閱文檔
      callback // callback 是一個方法,經過調用 callback 能夠在非異步函數中發送響應信息,關於如何定義異步函數與在異步函數內如何發送響應信息可參閱文檔
    ) => {
      const data = JSON.parse(event.body); // 解析 event 來得到 http 請求參數
      /* 業務邏輯 */
      callback(); // 用提供的 callback 函數來發送響應信息
    }
    複製代碼

    相關文檔:event 文檔, context 文檔, 定義異步函數

當咱們運行 npm installserverless deploy 將該起步工程部署到雲端後,就能夠經過 API 地址(例:xxxxxx.execute-api.us-east-1.amazonaws.com/dev/todos)來運行和訪問這些函數。

建立與定義函數

根據這個工程原有的函數 ,建立相似的函數文件並不是難事,咱們在工程中建立如下 4 個文件:

  • user/signup.js
  • user/login.js
  • user/public.js
  • user/private.js

但僅僅建立函數文件是不夠的,咱們須要同時在 serverless.yml 中爲這幾個函數添加定義。以 signup 函數爲例,在 functions 中添加如下內容:

signup:
 handler: user/signup.signup #定義了函數文件的路徑
 events:
 - http: #定義了函數觸發器種類爲 http (AWS API Gateway)
 path: api/user/signup #定義了請求路徑
 method: post #定義了請求 method 種類
 cors: true #開啓跨域
複製代碼

這樣咱們就完整地定義了 4 個函數。接下來咱們來看這四個函數具體的實現方法。

Public 函數

GET

返回一條無須登陸便可訪問的信息

1. 返回消息

public 函數是 4 個函數中最爲簡易的一個,由於該函數是徹底公開的,咱們不須要對該函數作任何校驗。以下,簡單地返回一條信息即可:

// user/public.js
module.exports.public = (event, context, callback) => {
  const response = {
    statusCode: 200,
    body: JSON.stringify({
      message: '任何人均可以閱讀此條信息。'
    })
  }
  return callback(null, response);
};
複製代碼

注:callback 第一個參數傳入的爲錯誤,第二個參數傳入的爲響應數據。

2. 部署及訪問服務

  • 執行如下命令來部署 public 函數

    # 部署單個函數
    serverless deploy function -f public
    複製代碼

    # 部署全部函數
    serverless deploy
    複製代碼
  • 在瀏覽器中直接輸入 API 地址或用 cURL 工具執行如下命令來發送請求(替換成你的 API 地址, API 地址可在運行 serverless deploy 後的 log 中或在 AWS API Gateway控制檯 - 階段(stage) 中找到)

    curl -X GET https://xxxxxx.execute-api.us-west-2.amazonaws.com/dev/api/public
    複製代碼
  • 返回數據

    {
      "message": "任何人均可以閱讀此條信息。"
    }
    複製代碼

Sign up 函數

POST

建立一個新用戶並錄入數據庫,返回成功或失敗信息

1. 定義資源

signup 函數的運行須要 DynamoDB 這一資源,因此第一步咱們須要在 serverless.yml 文件中對 resources 進行以下修改來添加所須要的數據庫資源

# serverless.yml
resources:
 Resources:
 UserDynamoDbTable:
 Type: 'AWS::DynamoDB::Table' #資源種類爲 DynamoDB 表
 DeletionPolicy: Retain #當刪除 CloudFormation Stack(serverless remove)時保留該表
 Properties:
 AttributeDefinitions: #定義表的屬性
 -
 AttributeName: username #屬性名
 AttributeType: S #屬性類型爲字符串
 KeySchema: #描述表的主鍵
 -
 AttributeName: username #鍵對應的屬性名
 KeyType: HASH #鍵類型爲哈希
 ProvisionedThroughput: #表的預置吞吐量
 ReadCapacityUnits: 1 #讀取量爲 1 單元
 WriteCapacityUnits: 1 #寫入量爲 1 單元
 TableName: ${self:provider.environment.DYNAMODB_TABLE} # 定義表名爲環境變量中的 DYNAMODB_TABLE
複製代碼

resources 一欄中填寫的內容是使用 yaml 語法寫的 AWS CloudFormation 的模版

DynamoDB 表在 CloudFormation 中更爲詳細定義文檔請參考 連接

2. 獲取請求數據

signup 是一個方法爲 POST 的接口,所以須要從 http 事件的 body 中獲取請求數據。

// user/signup.js
module.exports.signup = (event, context, callback) => {
  // 獲取請求數據並解析 JSON 字符串
  const data = JSON.parse(event.body);
  const { username, password } = data;
  /* ... 校驗 username 與 password */
}
複製代碼

3. 錄入用戶至 DynamoDB

獲取完了請求數據後,咱們須要構造出新用戶的數據,並把數據錄入 DynamoDB

// user/signup.js
// 引入 NodeJS 加密庫
const crypto = require('crypto');
// 建立 dynamoDB 實例
const AWS = require('aws-sdk'); 
const dynamoDb = new AWS.DynamoDB.DocumentClient();

module.exports.signup = (event, context, callback) => {
  // ...獲取並校驗 username 與 password
  
  // 生成 salt 來確保哈希後密碼的惟一性
  const salt = crypto.randomBytes(16).toString('hex');
  // 用 sha512 哈希函數加密,生成僅可單向驗證的哈希密碼
  const hashedPassword = crypto.pbkdf2Sync(password, salt, 10000, 512, 'sha512').toString('hex');
  const timestamp = new Date().getTime(); // 生成當前時間戳
  // 生成新用戶的數據
  const params = {
    TableName: process.env.DYNAMODB_TABLE, // 從環境變量中獲取 DynamoDB 表名
    Item: {
      username, // 用戶名
      salt, // 保存 salt 用於登陸時單向校驗密碼
      password: hashedPassword, // 哈希密碼
      createdAt: timestamp, // 生成時間
      updatedAt: timestamp // 更新時間
    }
  }
  // 將新用戶數據錄入至 dynamoDb
  dynamoDb.put(params, (error) => {
    // 返回失敗信息
    if (error) {
      // log 錯誤信息,可在 AWS CloudWatch 服務中查看
      console.error(error);
      callback(null, {
        statusCode: 500,
        body: JSON.stringify({
          message: '建立用戶失敗!'
        })
      });
    } else {
      // 返回成功信息
      callback(null, {
        statusCode: 200,
        body: JSON.stringify({
          message: '建立用戶成功!'
        })
      });
    }
}
複製代碼

DynamoDB 在 NodeJS 中更詳細的 CRUD 操做文檔請參考連接

4. 部署及訪問服務

  • 執行如下命令來部署 signup 函數

    # 部署單個函數
    serverless deploy function -f signup
    複製代碼

    # 部署全部函數
    serverless deploy
    複製代碼
  • cURL 工具執行如下命令來發送請求(替換成你的API地址,API地址可在運行 serverless deploy 後的 log 中或在 AWS API Gateway控制檯 - 階段(stage) 中找到)

    curl -X POST https://xxxxxx.execute-api.us-west-2.amazonaws.com/dev/api/user/signup --data '{ "username": "new_user", "password": "12345678" }'
    複製代碼
  • 返回數據

    {
      "message": "建立用戶成功!"
    }
    複製代碼

Login 函數

GET

校驗用戶名密碼並返回 JSON Web Token 來讓登陸用戶訪問私有接口

1. 設置 JSON Web Token

在用戶調用了 Login 接口並經過驗證後,咱們須要爲用戶返回一個 JSON Web Token ,以供用戶來調用須要權限的服務。設置 JSON Web Token 須要如下幾步操做:

  • npm install jsonwebtoken --save 安裝 jsonwebtoken 庫並添加至項目依賴

  • 在項目中添加一個 secret.json 文件來存放密鑰,這裏咱們採用對稱加密的方式來定義一個私有密鑰。

    // secret.json
    {
      "secret": "私有密鑰"
    }
    複製代碼
  • 將私有密鑰定義至環境變量,以供函數訪問。在 serverless.ymlprovider 下做以下變動

    # serverless.yml
    provider:
     environment:
        # 使用serverless變量語法將文件中的密鑰賦值給環境變量PRIVATE_KEY
     PRIVATE_KEY: ${file(./secret.json):secret}
    複製代碼

2. 獲取請求數據

login 是一個方法爲 GET 的接口,所以須要從觸發事件的 queryStringParameters 中獲取請求數據。

// user/login.js
module.exports.login = (event, context, callback) => {
  // 獲取請求數據
  const { username, password } = event.queryStringParameters;
  /* ... 校驗 username 與 password */
}
複製代碼

3. 驗證帳號密碼並返回 JSON Web Token

// user/login.js
const crypto = require('crypto');
const jwt = require('jsonwebtoken');
const AWS = require('aws-sdk');
const dynamoDb = new AWS.DynamoDB.DocumentClient();

module.exports.login = (event, context, callback) => {
  // ...獲取並校驗 username 與 password
  
  // 驗證帳號密碼並返回 JSON Web Token
  
  // 構造 DynamoDB 請求數據,根據主鍵 username 獲取數據
  const params = {
    TableName: process.env.DYNAMODB_TABLE,
    Key: {
      username
    }
  };
  // 從 DynamoDB 中獲取數據
  dynamoDb.get(params, (error, data) => {
    if (error) {
      // log 錯誤信息,可在 AWS CloudWatch 服務中查看
      console.error(error);
      // 返回錯誤信息
      callback(null, {
        statusCode: 500,
        body: JSON.stringify({
          message: '登陸失敗!'
        })
      });
      return;
    }
    
    // 從回調參數中獲取 DynamoDB 返回的用戶數據
    const user = data.Item;
    if (
      // 確認 username 存在
      user &&
      // 確認哈希密碼匹配
      user.password === crypto.pbkdf2Sync(password, user.salt, 10000, 512, 'sha512').toString('hex')
    ) {
      // 返回登陸成功信息
      const response = {
        statusCode: 200,
        body: JSON.stringify({
          username, // 返回 username
          // 返回 JSON Web Token
          token: jwt.sign(
            {
              username // 嵌入 username 數據
            },
            process.env.PRIVATE_KEY // 使用環境變量中的私有密鑰簽發 token
          )
        })
      };
      callback(null, response);
    } else {
      // 當用戶不存在,以及用戶密碼校驗錯誤時返回錯誤信息
      callback(null, {
        statusCode: 401,
        body: JSON.stringify({
          message: '用戶名或密碼錯誤!'
        })
      });
    }
  });
};
複製代碼

4. 部署及訪問服務

  • 執行如下命令來部署 login 函數

    # 部署單個函數
    serverless deploy function -f login
    複製代碼

    # 部署全部函數
    serverless deploy
    複製代碼
  • 在瀏覽器中直接輸入 API 地址或用 cURL 工具執行如下命令來發送請求(替換成你的 API 地址, API 地址可在運行 serverless deploy 後的log中或在 AWS API Gateway控制檯 - 階段(stage) 中找到)

    curl -X GET 'https://xxxxxx.execute-api.us-west-2.amazonaws.com/dev/api/user/login?username=new_user&password=12345678'
    複製代碼
  • 返回數據

    {
      "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Im5ld191c2VyIiwiaWF0IjoxNTYxODI1NTgyfQ.Iv0ulooGayulxf_MkkpBO1xEw1gilThT62ysuz-rQE0",
      "username": "new_user"
    }
    複製代碼

Auth 函數

校驗請求中所包含的 JSON Web Token 是否有效

在編寫 private 函數以前,咱們須要提供另外一個函數 auth 來校驗用戶提交請求中的 JSON Web Token 是否與咱們所簽發的一致。

1. 建立函數

  • 在項目中添加 user/auth.js 文件

  • serverless.ymlfunctions 中添加如下內容:

    auth:
    handler: user/auth.auth
    # auth 是一個僅會在服務內被調用的函數,所以沒有任何觸發器
    複製代碼

2. 生成包含 IAM 權限策略的響應信息

爲了可以讓 AWS API Gateway 觸發器正確地識別函數有無權限執行,咱們必須在 auth 函數中返回一個含 IAM ( AWS 服務與權限管控系統) 權限策略信息的響應數據,來使得有權限的函數能夠經過 AWS API Gateway 成功觸發。在 user/auth.js 內定義一個以下的方法:

// user/auth.js
const generatePolicy = (principalId, effect, resource) => {
  const authResponse = {};
  authResponse.principalId = principalId; // 用於標記用戶身份信息
  if (effect && resource) {
    const policyDocument = {};
    policyDocument.Version = '2012-10-17'; // 定義版本信息
    policyDocument.Statement = [];
    const statementOne = {};
    statementOne.Action = 'execute-api:Invoke'; // 定義操做類型,這裏爲 API 調用操做
    statementOne.Effect = effect; // 可用值爲 ALLOW 或 DENY ,用於指定該策略所產生的結果是容許仍是拒絕
    statementOne.Resource = resource; // 傳入 ARN( AWS 資源名)來指定操做所須要的資源
    policyDocument.Statement[0] = statementOne;
    authResponse.policyDocument = policyDocument; // 將定義完成的策略加入響應數據
  }
  return authResponse;
};
複製代碼

關於 IAM 策略更爲詳細的配置文檔請查看連接

3. 解析並校驗 JSON Web Token

咱們在解析 JSON Web Token 時默認請求遵循 OAuth2.0 中的 Bearer Token 格式。

// user/auth.js
const jwt = require('jsonwebtoken');

/* ...定義 generatePolicy 方法 */

module.exports.auth = (event, context, callback) => {
  // 獲取請求頭中的 Authorization
  const { authorizationToken } = event;
  if (authorizationToken) {
    // 解析 Authorization
    const split = event.authorizationToken.split(' ');
    if (split[0] === 'Bearer' && split.length === 2) {
      try {
        const token = split[1];
        // 使用私有密鑰校驗 JSON Web Token
        const decoded = jwt.verify(token, process.env.PRIVATE_KEY);
        // 使用 generatePolicy 生成包含容許API調用的IAM權限策略的響應數據
        const response = generatePolicy(decoded.username, 'Allow', event.methodArn);
        return callback(null, response);
      } catch (error) {
        // JSON Web Token 校驗失敗,返回錯誤
        return callback('Unauthorized');
      }
    } else {
      // Authorization 格式校驗失敗,返回錯誤
      return callback('Unauthorized');
    }
  } else {
    // 請求頭未含 Authorzation,返回錯誤
    return callback('Unauthorized');
  }
};
複製代碼

Private 函數

GET

返回一條須要登陸纔可訪問的信息

private 函數的實現與以前的 public 函數十分相似,惟一的區別就是咱們須要在函數的 http (AWS API Gateway) 觸發器中加入剛剛定義的 auth 做爲權限校驗函數。

1. 設置 authorizer

serverless.yml 中對先前定義的 private 函數做以下變動:

# serverless.yml
functions: 
 private:
 handler: user/private.private
 events:
 - http:
 path: api/private
 method: get
 authorizer: auth #設置 authorizer 爲剛剛定義的 auth 函數
 cors: true
複製代碼

2. 返回消息

// user/private.js
module.exports.private = (event, context, callback) => {
  // 從觸發事件中獲取請求的用戶信息
  const username = event.requestContext.authorizer.principalId;
  // 返回消息
  const response = {
    statusCode: 200,
    body: JSON.stringify({
      message: `你好,${username}!只有登陸後的用戶才能夠閱讀此條信息。`
    })
  }
  return callback(null, response);
};
複製代碼

3. 部署及訪問服務

  • 執行如下命令來部署 private 函數

    # 部署單個函數
    serverless deploy function -f private
    複製代碼

    # 部署全部函數
    serverless deploy
    複製代碼
  • 用 cURL 工具執行如下命令來發送請求(替換成你的 API 地址, API 地址可在運行 serverless deploy 後的 log 中或在 AWS API Gateway控制檯 - 階段(stage) 中找到)

    curl -X GET -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Im5ld191c2VyIiwiaWF0IjoxNTYxODI1NTgyfQ.Iv0ulooGayulxf_MkkpBO1xEw1gilThT62ysuz-rQE0" https://xxxxxx.execute-api.us-west-2.amazonaws.com/dev/api/private
    複製代碼
  • 返回數據

    {
      "message": "你好,new_user!只有登陸後的用戶才能夠閱讀此條信息。"
    }
    複製代碼

實踐小結

用了什麼?

  • Serverless CLI
  • AWS Lambda
  • AWS API Gateway
  • AWS CloudWatch
  • DynamoDB
  • OAuth2.0

作了什麼?

  • 使用 Serverless 開發與部署了一套 HTTP 接口服務
  • 服務提供了用戶的註冊、登陸接口
  • 服務提供了徹底開放接口與僅登陸用戶可訪問接口

完整工程

若是在教程中有疑點,能夠在 Github 上查看完整的代碼。

引用

本文發佈自 網易雲音樂前端團隊,歡迎自由轉載,轉載請保留出處。咱們一直在招人,若是你剛好準備換工做,又剛好喜歡雲音樂,那就 加入咱們

相關文章
相關標籤/搜索