經過 AWS 的 Lambda 和 API Gateway 走向 Serverless

簡短回憶下計算領域的發展html

經過 AWS 的 Lambda 和 API Gateway 走向 Serverless經過 AWS 的 Lambda 和 API Gateway 走向 Serverless
早期,出現了……好吧,這有點複雜。很早的時候,出現了機械計算機,後來又有了埃尼阿克 ENIAC(Electronic Numerical Integrator And Computer,很早的電子計算機),可是都沒有規模生產。直到大型機出現後,計算領域才快速發展。python

  • 上世紀 50 年代 - 大型機
  • 上世紀 60 年代 - 微型機
  • 1994 - 機架服務器
  • 2001 - 刀片服務器
  • 本世紀初 - 虛擬服務器
  • 2006 - 服務器雲化
  • 2013 - 容器化
  • 2014 - serverless(計算資源服務化)

這些日期是大概的發佈或者流行日期,無需和我爭論時間的準確性。
計算領域的演進趨勢是執行的功能單元愈來愈小。每一次演進一般都意味着運維負擔的減少和運維靈活性的增長。linux

發展前景web

喔,Serverless!可是,serverless 能給咱們帶來什麼好處? 咱們將面臨什麼挑戰呢?數據庫

未執行代碼時無需付費。我認爲,這是個巨大的賣點。當無人訪問你的站點或用你的 API 時,你無需付錢。沒有持續支出的基礎設施成本,僅僅支付你須要的部分。換句話說,這履行了雲計算的承諾:「僅僅支付你真正用的資源」。json

無需維護服務器,也無需考慮服務器安全。服務器的維護和安全將由你的服務提供商來處理(固然,你也能夠架設本身的 serverless 主機,只是這彷佛是在向錯誤的方向前進)。因爲你的執行時間也是受限的,安全補丁也被簡化了,由於徹底不須要重啓。這些都應該由你的服務提供商無縫地處理。flask

無限的可擴展性。這是又一個大的好處。假設你又開發了一個 Pokemon Go, 與其頻繁地把站點下線維護升級,不如用 serverless 來不斷地擴展。固然,這也是個雙刃劍,大量的帳單也會隨之而來。若是你的業務的利潤強依賴於站點上線率的話,serverless 確實能幫上忙。api

強制的微服務架構。這也有兩面性,一方面,微服務彷佛是一種好的構建靈活可擴展的、容錯的架構的方式。另外一方面,若是你的業務沒有按照這種方式設計,你將很難在已有的架構中引入 serverless。安全

可是如今你被限制在他們的平臺上服務器

受限的環境。你只能用服務提供商提供的環境,你想在 Rust 中用 serverless?你可能不會太幸運。

受限的預裝包。你只有提供商預裝的包。可是你或許可以提供你本身的包。

受限的執行時間。你的 Function 只能夠運行這麼長時間。若是你必須處理 1TB 的文件,你可能須要有一個解決辦法或者用其餘方案。

強制的微服務架構。參考上面的描述。

受限的監視和診斷能力。例如,你的代碼幹什麼? 在 serverless 中,基本不可能在調試器中設置斷點和跟蹤流程。你仍然能夠像往常同樣記錄日誌併發出統計度量,可是這帶來的幫助頗有限,沒法定位在 serverless 環境中發生的難點問題。

競爭領域

自從 2014 年出現 AWS Lambda 之後,serverless 的提供商已經增長了一些。下面是一些主流的服務提供商:

  • AWS Lambda - 起步最先的
  • OpenWhisk - 在 IBM 的 Bluemix 雲上可用
  • Google Cloud Functions
  • Azure Functions

這些平臺都有它們的相對優點和劣勢(例如,Azure 支持 C#,或者緊密集成在其餘提供商的平臺上)。這裏面最大的玩家是 AWS。

經過 AWS 的 Lambda 和 API Gateway 構建你的第一個 API

咱們來試一試 serverless。咱們將用 AWS Lambda 和 API Gateway 來構建一個能返回 Jimmy 所說的「Guru Meditations」的 API。

全部代碼在 GitHub 上能夠找到。

API文檔:

POST /
{
    "status": "success",
    "meditation": "did u mention banana cognac shower"
}

怎樣組織工程文件

文件結構樹:

.
├── LICENSE
├── README.md
├── server
│   ├── __init__.py
│   ├── meditate.py
│   └── swagger.json
├── setup.py
├── tests
│   └── test_server
│       └── test_meditate.py
└── tools
    ├── deploy.py
    ├── serve.py
    ├── serve.sh
    ├── setup.sh
    └── zip.sh

AWS 中的信息(想了解這裏究竟在作什麼的詳細信息,可查看源碼tools/deploy.py)。

  • API。實際構建的對象。它在 AWS 中表示爲一個單獨的對象。
  • 執行角色。在 AWS 中,每一個 Function 做爲一個單獨的角色執行。在這裏就是 meditations。
  • 角色策略。每一個 Function 做爲一個角色執行,每一個角色須要權限來幹活。咱們的 Lambda Function 不幹太多活,故咱們只添加一些日誌記錄權限。
  • Lambda Function。運行咱們的代碼的地方。
  • Swagger。 Swagger 是 API 的規範。API Gateway 支持解析 swagger 的定義來爲 API 配置大部分資源。
  • 部署。API Gateway 提供部署的概念。咱們只須要爲咱們的 API 用一個就行(例如,全部的都用生產或者 yolo等),可是得知道它們是存在的,而且對於真正的產品級服務,你可能想用開發和暫存環境。
  • 監控。在咱們的業務崩潰的狀況下(或者由於使用產生大量帳單時),咱們想以雲告警查看方式爲這些錯誤和費用添加一些監控。注意你應該修改 tools/deploy.py 來正確地設置你的 email。

代碼

Lambda Function 將從一個硬編碼列表中隨機選擇一個並返回 guru meditations,很是簡單:

import logging
import random

logger = logging.getLogger()
logger.setLevel(logging.INFO)

def handler(event, context):

    logger.info(u"received request with id '{}'".format(context.aws_request_id))

    meditations = [
    "off to a regex/",
    "the count of machines abides",
    "you wouldn't fax a bat",
    "HAZARDOUS CHEMICALS + RKELLY",
    "your solution requires a blood eagle",
    "testing is broken because I'm lazy",
    "did u mention banana cognac shower",
    ]

    meditation = random.choice(meditations)

    return {
        "status": "success",
        "meditation": meditation,
    }

deploy.py 腳本

這個腳本至關長,我無法貼在這裏。它基本只是遍歷上述「AWS 中的信息」下的項目,確保每項都存在。

咱們來部署這個腳本

只需運行 ./tools/deploy.py。

基本完成了。不過彷佛在權限申請上有些問題,因爲 API Gateway 沒有權限去執行你的 Function,因此你的 Lambda Function 將不能執行,報錯應該是「Execution failed due to configuration error: Invalid permissions on Lambda function」。我不知道怎麼用 botocore 添加權限。你能夠經過 AWS console 來解決這個問題,找到你的 API, 進到 "/POST" 端點,進到「integration request」,點擊「Lambda Function」旁邊的編輯圖標,修改它,而後保存。此時將彈出一個窗口提示「You are about to give API Gateway permission to invoke your Lambda function」, 點擊「OK」。

當你完成後,記錄下/tools/deploy.py 打印出的 URL,像下面這樣調用它,而後查看你的新 API 的行爲:

$ curl -X POST https://a1b2c3d4.execute-api.us-east-1.amazonaws.com/prod/
{"status": "success", "meditation": "the count of machines abides"}

本地運行

不幸的是,AWS Lambda 沒有好的方法能在本地運行你的代碼。在這個例子裏,咱們將用一個簡單的 flask 服務器來在本地託管合適的端點,並調用 handler 函數。

from __future__ import absolute_import

from flask import Flask, jsonify

from server.meditate import handler

app = Flask(__name__)

@app.route("/", methods=["POST"])
def index():

    class FakeContext(object):
        aws_request_id = "XXX"

    return jsonify(**handler(None, FakeContext()))

app.run(host="0.0.0.0")

你能夠在倉庫中用 /tools/serve.sh 運行它,像這樣調用:

$ curl -X POST http://localhost:5000/
{
    "meditation": "your solution requires a blood eagle",
    "status": "success"
}

測試

你老是應該測試你的代碼。咱們的測試方法是導入並運行咱們的 handler 函數。這是最基本的 python 測試方法:

from __future__ import absolute_import

import unittest

from server.meditate import handler

class SubmitTestCase(unittest.TestCase):

    def test_submit(self):

        class FakeContext(object):

            aws_request_id = "XXX"

        response = handler(None, FakeContext())

        self.assertEquals(response["status"], "success")
        self.assertTrue("meditation" in response)

你能夠在倉庫裏經過 nose2 運行這個測試代碼。

更多前景

  • 和 AWS 服務的無縫集成。經過 boto,你能夠完美地輕易鏈接到任何其餘的 AWS 服務。你能夠輕易地讓你的執行角色用 IAM 訪問這些服務。你能夠從 S3 取文件或放文件到 S3,鏈接到 Dynamo DB,調用其餘 Lambda Function,等等。
  • 訪問數據庫。你也能夠輕易地訪問遠程數據庫。在你的 Lambda handler 模塊的最上面鏈接數據庫,並在handler 函數中執行查詢。你極可能必須從它的安裝位置上傳相關的包內容才能使它正常工做。可能你也須要靜態編譯某些庫。
  • 調用其餘 webservices。API Gateway 也是一種把 webservices 的輸出從一個格式轉換成另外一個格式的方法。你能夠充分利用這個特色經過不一樣的 webservices 來代理調用,或者當業務變動時提供後向兼容能力。

原文來自:http://www.lai18.com/content/24630408.html

本文地址:http://www.linuxprobe.com/lambda-api-gateway.html

相關文章
相關標籤/搜索