Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Node.js
Code

使用 AWS SimpleDB 和 Node.js 構建 REST API

by
Difficulty:IntermediateLength:LongLanguages:

Chinese (Traditional) (中文(繁體)) translation by Fuhuan (you can also view the original English article)

SimpleDB 是 Amazon Web Services(AWS)提供的遠程數據庫。 基於 SQL 語言的使用或不使用,數據存儲通常分為 SQL 和 NoSQL。 NoSQL 數據存儲通常基於更簡單的鍵 / 值設置。  SimpleDB 橫跨這壹行 - 它是壹個鍵 / 值存儲,也可以使用 SQL 的變體進行檢索。  大多數 SQL 語言都基於壹個模式,該模式列出了數據的行和列,但 SimpleDB 是壹個無模式的數據庫,這使得數據存儲非常靈活。

在 SimpleDB 數據庫模型中,有項目,屬性和值。  數據庫中的每壹行都是壹個項目,通過唯壹且可分配的項目名稱進行標識。 每個項目最多可以有 256 對屬性和值。  我認為考慮 SimpleDB 的最佳方法是考慮電子表格,但不是每個列 / 行交集代表壹個值,它代表壹個值數組。  我認為考慮 SimpleDB 的最佳方法是考慮電子表格,但不是每個列 / 行交集代表壹個值,它代表壹個值數組。

Grid illustrating Item Name Attribute Value relationship

此圖表表示存儲在 SimpleDB 域中的兩個項目。 術語域類似於其他數據庫中的 “表”。

第壹列是項目名稱 - 這是唯壹壹個只能包含單個值的列,您可以將其視為唯壹索引列。

其他四列(寵物,汽車,家具和電話)代表當前在此域中的屬性 - 不限於此,因此每個項目都可以具有完全唯壹的屬性集。 在此數據中,項目 personInventory1 上的屬性 pets 有三對; 用 JSON 表示,它看起來像這樣:

另壹方面,項目 personInventory2 只有壹對:

雖然您不必為每個項目提供相同的屬性,但您需要提供至少壹對。  這意味著您不能擁有 “空” 項。  每個屬性的大小最大可達 1kb,因此這意味著每個項目在功能上限制為 256kb,因為 1kb 的值限制和 256 對限制。

SimpleDB 是分布式的,您在設計應用程序時需要理解和記住 SimpleDB 的特性。  作為分布式數據庫意味著整組計算機將響應您的請求,您的數據將在這些服務器中復制。  此分發對您的程序完全透明,但它確實引入了壹致性問題的可能性 - 您的數據無法保證最初出現在所有服務器上。

不要驚慌:由於壹些原因,它並沒有聽起來那麽糟糕。 使用 SimpleDB,不保證壹致性,但它通常非常好,並且快速到達所有節點。 設計這個也不是那麽的難 - 通常妳會盡量避免立即調閱妳剛寫的記錄。 最後,SimpleDB 可以選擇執行壹致的讀取,但它們速度較慢,可能會占用更多資源。 如果您的應用每次都需要壹致的閱讀,您可能需要重新考慮是否需要使用 SimpleDB 作為您的數據存儲,但對於許多應用程序,這可以設計或甚至不擔心。

從好的方面來說,分布式特性還為 SimpleDB 提供了壹些與 Node.js 環境很好地融合的優點。 由於您沒有單個服務器響應您的請求,因此您無需擔心服務飽和,並且可以通過向 SimpleDB 發出許多並行請求來實現良好性能。  並行和異步請求是 Node.js 可以輕松處理的。

與許多 AWS 服務不同,沒有用於管理 SimpleDB 的亞馬遜控制臺。 幸運的是,有壹個很好的瀏覽器管理控制臺,采用谷歌 Chrome 插件 SdbNavigator 的形式。 在 SdbNavigator 中,您可以添加或刪除域,插入,更新和刪除項,修改屬性以及執行查詢。

AWS 開發 SDK

現在我們已經了解了 SimpleDB 服務,讓我們開始編寫我們的 REST 服務器。 首先,我們需要安裝 AWS SDK。  此 SDK 不僅處理 SimpleDB,還處理所有 AWS 服務,因此您可能已將其包含在 package.json 文件中。 要安裝 SDK,請從命令行運行以下命令:

要使用 SimpleDB,您還需要獲取 AWS 憑據,其中包括訪問密鑰和密鑰。 SimpleDB 是壹種即用即付服務,但 AWS 目前包含對 SimpleDB 的免費許可。

警告:與任何即用即付服務壹樣,請註意可以編寫可以支付大筆賬單的代碼,因此您需要密切關註您的使用情況並將您的憑據保密而且安全。

壹旦安裝了 AWS SDK 並獲得了憑據,就需要在代碼中設置 SimpleDB。 在此示例中,我們將使用存儲在主目錄中的 JSON 文件中的 AWS 憑據。 首先,您需要包含 SDK 模塊,創建 AWS 對象,最後設置 SimpleDB 接口。

請註意的是,我們正在使用特定的端點和區域。 每個數據中心都是完全獨立的,因此如果您在北弗吉尼亞州創建名為 “ mysuperawesomedata ” 的域,則不會將其復制到聖保羅數據中心,也不會出現在其中。

您使用新的 aws.SimpleDB 創建的 SimpleDB 對象是您與 SimpleDB 交互的所有方法都將基於的位置。 在 AWS SDK 的 SimpleDB 的只有幾個方法:

批量操作

  • batchPutAttributes
  • batchPutAttributes

域名管理和信息

  • 則 createdomain
  • deleteDomain
  • domainMetadata
  • listDomains

項目 / 屬性操作

  • deleteAttributes
  • getAttributes
  • putAttributes

查詢

  • 選擇

在本教程中,我們將只處理項目 / 屬性操作和查詢; 雖然其他類別很有用,但許多應用程序對它們沒有任何用處。

測試數據

使用 SdbNavigator,在工具中輸入訪問和安全密鑰,選擇 “US-East”,然後單擊 “連接”。

Connection UI to SdbNavigator

成功連接後,讓我們創建壹個用於測試的域。 單擊 “ 添加域”。

Adding a domain via the SdbNavigator

然後輸入域名'sdb-rest-tut'並單擊 OK。

Entering the name of the new domain

現在您已經創建了壹個域,讓我們輸入壹些測試數據。 單擊 “ 添加屬性” 並添加名為 “colors” 的屬性。 作為慣例,我通常以復數形式命名屬性以反映 SimpleDB 的多值性質。

Adding a property name to the record

最後,我們將單擊 Add record 以創建我們的第壹個 SimpleDB 項。 在 ItemName()列中,輸入您的唯壹項名稱。  SdbNavigator 的壹個特點是,默認情況下,它只接受每個項目的單個值,但這掩蓋了屬性可以包含多個值的事實。 要輸入多個值,請單擊屬性列右邊緣的 S.

Entering a unique item name

在新框中,選擇 Array 以輸入多個值。 在 “ 值” 列中,輸入 “red”,然後單擊 “ 添加值” 並輸入 “blue”。

Entering the data type of the item

最後,單擊 “ 更新” 以將更改保存到此行。

Updating the data type of the item

現在我們輸入了壹些測試數據,讓我們從 Node 發出第壹個 SimpleDB 請求。 我們將只獲取 Domain 中的所有內容,此時,它只是壹行。

響應將記錄到控制臺。  這是回復,註釋如下:

REST 服務器

由於我們將構建壹個在 SimpleDB 中存儲數據的 REST 服務器,因此了解 REST 服務器的功能很重要。 REST 服務器實際上只是壹個使用 HTTP 標準機制作為數據接口的服務器。 REST 服務器實際上只是壹個使用 HTTP 標準機制作為數據接口的服務器。 通常,REST 用於服務器到服務器的通信,但您可以通過 JavaScript 庫(如 jQuery 或 Angular)將 REST 服務器與客戶端壹起使用。  但是,通常終端用戶不會直接與 REST 服務器交互。

有趣的是,AWS SDK 實際上使用 REST 協議與 SimpleDB 交互,因此向另壹個 REST 服務器創建 REST 服務器似乎很奇怪。  您不希望直接使用 SimpleDB REST API,因為您需要對請求進行身份驗證,這可能會危及您的 AWS 賬戶的安全性。 此外,通過編寫服務器,您將能夠為數據存儲添加壹層抽象和驗證,這將使整個應用程序的其余部分更容易處理。

在本教程中,我們將構建基本的 CRUD + L 函數,即 C reate,R ead,U pdate,D elete 和 L ist。 如果妳考慮壹下,妳可以將大多數應用程序分解為 CRUD + L.  使用 REST,您將使用有限數量的路徑和多個 HTTP 方法或動詞來創建直觀的 API。 大多數開發人員都熟悉壹些 HTTP 動詞,即 GET 和 POST,因為它們最常用於 Web 應用程序,但還有其他幾個。

手術 HTTP 動詞
創建 POST
得到
更新
刪除 刪除
名單 得到

請註意,Read 和 List 都使用相同的動詞; 我們將使用稍微不同的路徑來區分兩者。  我們使用 POST 來表示 Create,因為創建不被視為冪等。 冪等意味著多個相同的調用將對用戶和數據產生相同的結果,因此更新(也稱為 PUT)將被視為冪等的。

作為我們的例子,我們將構建壹個個人庫存服務器 - 壹個數據庫來保存您擁有的任何內容。 以下是路徑的外觀:

手術 HTTP 動詞 創建
創建 POST / 存貨 
得到 / 存貨 / 1234
更新 / 存貨 / 1234
刪除 刪除 / 存貨 / 1234
名單 得到 / 庫存

1234 是人員標識符(ID)的占位符 - “創建”和 “列表” 沒有 ID 的註釋。 在 create 的情況下,將生成 ID,並且使用 list,我們將獲得所有名稱,因此我們不需要特定的 ID。

構建服務器

首先,讓我們安裝壹個 Node.js HTTP 服務器框架 Express:

Express 在設置服務器時管理大部分細節,但它不包括處理 HTTP 請求體的任何工具,因此我們需要安裝另壹個模塊,body-parser,以使我們能夠讀取請求體。

Body-parser 有壹些不同的選項可用於解析 HTTP 請求的主體。 我們將使用 json()方法來提高可讀性,但切換到另壹個方法只是在 bodyParser 對象上交換方法。 我們只需要在 create 和 update 方法上使用 bodyParser 方法,因此我們可以將它包含在那些特定的路由中。

創建

由於每個 SimpleDB itemName 都必須是唯壹的,因此我們可以為每個新創建的項自動生成壹個新的 itemName。 我們將使用 cuid 模塊,這是壹種生成唯壹標識符的輕量級方法。

SimpleDB 期望屬性采用屬性名稱 / 值對格式:

您的服務器當然可以直接接受並將這種格式的值直接傳遞給 SimpleDB,但是對於數據的常常結構化而言,這是違反直覺的,並且這是壹個難以理解的概念。 我們將使用更直觀的數據結構,壹個對象 / 值數組:

這是壹個基於 Express 的基本服務器,具有 create 操作:

讓我們啟動妳的服務器並嘗試壹下。 與 REST 服務器交互的壹種好方法是使用 cURL 工具。  此工具允許您從命令行使用任何動詞發出 HTTP 請求。 要嘗試使用我們的 REST 服務器創建項目,我們需要激活壹些額外的選項:

選項 目的
-H 在 HTTP 標題中添加壹行
-X 定義將使用哪個動詞
-d 要在 HTTP 請求正文中發送的數據

運行該命令後,您將看到包含新創建的 itemName 或 ID 的 JSON 響應。 如果切換到 SdbNavigator,則在查詢所有項目時應該會看到新數據。

現在讓我們構建壹個從 SimpleDB 讀取項目的基本函數。

現在讓我們構建壹個從 SimpleDB 讀取項目的基本函數。 為此,我們不需要執行查詢,因為我們將從請求的路徑獲取 itemName 或 ID。 我們可以使用該 itemName 或 ID 執行 getAttributes 請求。

如果我們停在這裏,我們將擁有壹個功能性但不是非常友好的數據形式。 讓我們將 Name / Value 數組轉換為我們用於接受數據的相同形式(屬性:值數組)。 為此,我們需要遍歷每個名​​稱 / 值對,並將其添加到每個唯壹名稱的新數組中。

最後,讓我們添加 itemName 並返回結果。

為了測試這個,我們需要再次使用 curl。 嘗試使用本教程前面創建項目示例中返回的 itemName 或 ID 替換 [cuid]。

請註意,我們使用的是 -D- 選項。  這將轉儲 HTTP 頭,以便我們可以看到響應代碼。

REST 的另壹個方面是使用您的響應代碼。 在當前示例中,如果您提供不存在的 ID 以進行 curl,則上述服務器將崩潰,因為您嘗試 forEach 壹個不存在的數組。 我們需要考慮到這壹點並返回壹個有意義的 HTTP 響應代碼,表明找不到該項。

為了防止錯誤,我們應該測試變量 awsResp.Attributes 的存在。 如果它不存在,讓我們將狀態代碼設置為 404 並結束 http 請求。 如果存在,那麽我們可以使用屬性來提供響應。

嘗試使用新代碼和不存在的 ID,您將看到服務器返回 404。

現在我們知道如何使用 status 來更改值,我們還應該更新我們對 POST / create 的響應方式。 雖然 200 響應在技術上是正確的,因為它意味著'OK',但更具洞察力的響應代碼將是 201,表示'已創建'。  要進行此更改,我們會在發送之前將其添加到狀態方法中。

更新

更新通常是任何系統最困難的操作,此 REST 服務器也不例外。

SimpleDB 的本質使得這個操作也更具挑戰性。  對於 REST 服務器,更新是替換整個存儲數據的地方; 另壹方面,SimpleDB 表示 itemName 下的各個屬性 / 值對。

為了允許更新來表示單個數據而不是名稱 / 值對的集合,我們需要為代碼的目的定義模式(即使 SimpleDB 不需要)。  如果現在還不清楚,請不要擔心,請繼續閱讀,我會說明要求。

與許多其他數據庫系統相比,我們的模式將非常簡單:只是壹個已定義的屬性數組。 在我們的例子中,我們有四個我們關註的領域:寵物,汽車,家具和手機:

使用 SimpleDB,您不能存儲空屬性 / 值對,SimpleDB 也沒有任何單個項的概念,因此我們假設如果 SimpleDB 沒有返回值,則它不存在。  同樣,如果我們嘗試使用空屬性 / 值對更新 SimpleDB 項,它將忽略該數據。  以這個數據為例:

從邏輯上講,我們知道作為壹個空陣列的汽車應該沒有價值,寵物應該有兩個值,但手機和家具呢?  妳對那些人做了什麽?  以下是我們如何翻譯此更新請求以使用 SimpleDB:

  • 將具有值的屬性 pet 放入 cat。
  • 將帶有值的屬性 pet 放到 dog 上。
  • 刪除汽車的屬性。
  • 刪除手機的屬性。
  • 刪除家具的屬性。

如果沒有至少定義屬性的某種形式的架構,我們就不會知道需要刪除手機和家具。 幸運的是,我們可以將此更新操作合並為兩個 SimpleDB 請求而不是五個:壹個用於放置屬性,另壹個用於刪除屬性。 現在是從 post / create 函數中提取代碼的好時機,該函數將 values 對象的屬性 / 數組轉換為屬性 / 值對數組。

我們還將對 create 函數進行重要更改。  我們將為所有項添加新的屬性 / 值。  此屬性不會添加到架構中,並且實際上是只讀的。

我們將添加壹個名為 created 的屬性並將值設置為 1。 使用 SimpleDB,在添加屬性和值之前檢查項是否存在的能力有限。 在每個 putAttributes 請求中,您可以檢查單個屬性的值和是否存在 - 在我們的示例中,我們將使用 created 並檢查值為 1。 雖然這可能看起來像壹個奇怪的解決方法,但它提供了壹個非常重要的安全措施,以防止更新操作能夠創建具有任意 ID 的新項目。

由於我們將執行幾個異步 HTTP 請求,讓我們安裝異步模塊以簡化這些回調的處理。

請記住,由於 SimpleDB 是分布式的,因此沒有理由按順序放置我們的屬性然後刪除。 我們將使用函數 async.parallel 來運行這兩個操作,並在兩個操作完成時獲得回調。 來自 AWS 表單 putAttributes 和 deleteAttributes 的響應不提供重要信息,因此如果沒有錯誤,我們將發送狀態代碼為 200 的空響應。

為了實現這壹點,讓我們更新以前創建的條目。  這壹次,我們將使庫存只包括壹個 “狗”,刪除所有其他項目。  再次,使用 cURL,運行命令,用 [cuid] 替換您的壹個項目 ID。

刪除

SimpleDB 沒有項目刪除的概念,但它可以刪除屬性,如上所述。 要刪除項目,我們需要刪除所有屬性,“項目” 將不再存在。

由於我們已經在模式中定義了屬性列表,因此我們將使用 deleteAttributes 調用來刪除所有這些屬性以及創建的屬性。 根據我們的計劃,此操作將與 Update 處於相同的路徑,但使用動詞刪除。

名單

列出我們的 REST 動詞。  為了實現列表操作,我們將使用 select 命令和類似 SQL 的查詢語言。 我們的列表函數將是準系統,但將作為稍後進行更復雜檢索的良好基礎。 我們將做壹個非常簡單的查詢:

當我們遇到 get / read 操作時,SimpleDB 的響應不是很有用,因為它專註於屬性 / 值對。 為了避免重復,我們將把 get / read 操作的部分重構為壹個單獨的函數並在此處使用它。 雖然我們在這裏,但我們也會過濾掉創建的屬性(因為它將顯示在 get 操作中)。

通過 select 操作,SimpleDB 返回 Items 數組中的值。 每個項目由壹個對象表示,該對象包含 itemName(簡稱為 Name)和屬性 / 值對。

為簡化此響應,讓我們返回單個對象中的所有內容。 首先,我們將屬性 / 值對轉換為屬性 / 值數組,就像我們在 read / get 操作中所做的那樣,然後我們可以添加 itemName 作為屬性 ID。

要查看我們的結果,我們可以使用 curl:

驗證

驗證完全是它自己的主題,但是使用我們已經編寫的代碼,我們可以開始使用簡單的驗證系統。

目前,我們要確保的是,除了架構中的內容之外,用戶無法提交任何內容。 回顧為 update / put 編寫的代碼,forEach over the schema 將防止添加任何未經授權的屬性,因此我們實際上只需要應用類似於我們的 create / post 操作的東西。  在這種情況下,我們將過濾屬性 / 值對,從而消除任何非模式屬性。

在您的生產代碼中,您可能需要壹個更強大的驗證系統。 我建議集成壹個 JSON 模式驗證器,如 ajv,並在創建和更新操作上構建位於 bodyParser 和路由功能之間的中間件。

下壹步

使用本文中概述的代碼,您可以獲得存儲,讀取和修改數據所需的所有操作,但這只是您旅程的開始。 在大多數情況下,您需要開始考慮以下主題:

  • 認證
  • 分頁
  • 復雜的列表 / 查詢操作
  • 其他輸出格式(xml,csv 等)

這個由 SimpleDB 支持的 REST 服務器的基礎允許您添加中間件和其他邏輯,以便為您的應用程序構建主幹。

最終的服務器代碼可以在 GitHub 上的 simpledb-rest-api 上找到。

Envato qr branded
关注我们的公众号
Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.