2017-09-10 131 views
2

我想在Amazon Lambda上運行的NodeJS服務中使用mysql池。 這是我的模塊開始,隨着數據庫的工作原理:如果我剛剛部署的服務和執行在亞馬遜lambda上使用mysql池

  1. console.log('init database module ...'); 
    var settings = require('./settings.json'); 
    var mysql = require('mysql'); 
    var pool = mysql.createPool(settings); 
    

    如從亞馬遜日誌以下控制檯這段代碼被執行非常頻繁10個請求同時執行 - 所有這10個請求都執行這段代碼。

  2. 如果我在第一系列後立即再次同時執行10個請求 - 它們不執行此代碼。
  3. 如果有一段時間從最後一次查詢傳遞過來 - 那麼某些請求將重新執行該代碼。

即使我使用全球 - 這降低但不是消除重複:

if (!global.pool) { 
    console.log('init database module ...'); 
    var settings = require('./settings.json'); 
    var mysql = require('mysql'); 
    global.pool = mysql.createPool(settings); 
} 

而且,如果請求執行具有一定的誤差 - 被請求和之後執行這一段代碼global.pool此時爲空。

那麼,這是否意味着在Amazon Lambda中使用池是不可能的? 有沒有什麼辦法可以讓亞馬遜每次都使用同一個池實例?

+1

所有你在點1,2描述,以及圖3是具有多個容器一致和[容器再利用](https://aws.amazon.com/blogs/compute/container-reuse-in-lambda/)在LAMBDA 。你熟悉這個嗎? –

+0

結論是什麼?彙集沒有意義,對吧? – Boris

回答

5

每次調用Lambda函數時,都會在其自己的獨立容器中運行。如果沒有閒置的容器可用,則由該服務自動創建一個新容器。因此:

  1. 如果我剛剛部署的服務,並同時執行10個要求 - 所有這些10個請求執行這段代碼。

如果容器可用,它可能很可能會被重用。發生這種情況時,進程已經在運行,所以全局部分不會再運行 - 調用以處理程序開始。因此:

  • 如果我再次後立即第一系列同時執行10個請求 - 它們不執行該代碼。
  • 之後每次調用完成,使用的被凍結,並最終將被解凍,要麼和後續調用中重複使用,或者如果幾分鐘後不需要它,它破壞了容器。因此:

  • 如果一段時間是從上次查詢通過 - 然後一些請求的重新執行該代碼。
  • 有意義,現在吧?

    唯一的「捕獲」是時間的容器被銷燬之前必須經過的量不是固定值。有趣的是,它似乎是大約15分鐘,但我不認爲它有記錄,因爲很可能計時器是自適應的...服務可以(在其分娩時)使用啓發式方法來預測近期活動是高峯還是可能持續下去,並可能考慮其他因素。 (Lambda @ Edge,與lambda集成的用於HTTP頭部處理的Lambda似乎以不同的時序運行,空閒容器似乎持續時間更長,至少少量存在,但這是有道理的,因爲它們總是很小容器......,這再次觀察是傳聞。)

    你的代碼在全球的部分僅在創建新的容器時運行。

    池沒有意義,因爲沒有被調用過程中共享 - 每次調用是在其容器運行只有一個 - 每個過程中的一個 - 在任何一個時間。

    什麼,你會想要做的,雖然是改變連接的idle_timeout。 MySQL服務器沒有一種有效的方式來「發現」一個空閒連接已經完全消失,所以當你的連接在容器被銷燬時消失,服務器就在那裏,並且連接保持在Sleep狀態,直到默認idle_timeout到期。默認值爲28800秒,或8小時,這個時間太長。您可以在服務器上更改此項,或發送查詢SET @@IDLE_TIMEOUT = 900(儘管您需要嘗試使用適當的值)。

    或者,您可以建立和銷燬每個調用處理程序內部的連接。當然,這需要多一點時間,但如果你的功能不會經常運行,這是一個明智的方法。 MySQL客戶端/服務器協議的連接/握手順序相當輕量級,並且頻繁的連接/斷開連接不會像您期望的那樣對服務器施加儘可能多的負載......雖然您不希望在使用RDS服務器IAM令牌認證,這是資源密集型的。