异步api_如何设计无服务器异步API
異步api
by Garrett Vargas
通過Garrett Vargas
如何設(shè)計無服務(wù)器異步API (How To Design a Serverless Async API)
I recently ran a workshop to teach developers how to create an Alexa skill. The workshop material centered around a project to return car rental search results. Because I wanted to focus the learning on developing the conversational flow and not the mechanics of doing a car search, I decided to encapsulate the search logic behind an API. In addition, since the car search request can take 10 or more seconds to complete, I wanted the call to be asynchronous so we could build a conversation like:
我最近舉辦了一個講習(xí)班,教開發(fā)人員如何創(chuàng)建Alexa技能。 研討會資料圍繞一個項目返回了租車搜索結(jié)果。 因為我想將學(xué)習(xí)重點放在開發(fā)對話流程上,而不是在進行汽車搜索的機制上,所以我決定將搜索邏輯封裝在API后面。 此外,由于汽車搜索請求可能需要10秒鐘或更長時間才能完成,因此我希望通話是異步的,因此我們可以建立如下對話:
“Find a Car in New York next weekend”
“下周末在紐約找車”
“What size car would you like for your trip in New York next weekend?”
“下周末您要在紐約旅行時選擇哪種尺寸的汽車?”
“A small car”
“一輛小汽車”
“Is there a specific company you’d like to rent from?”
“您想租一家特定的公司嗎?”
“No”
“沒有”
The implementation of the asynchronous API was a pretty interesting project in and of itself, and in this blog post I’m going to tell you how I did this in a serverless way using API Gateway, Lambda functions, and S3.
異步API的實現(xiàn)本身就是一個非常有趣的項目,在這篇博客文章中,我將告訴您如何使用API??網(wǎng)關(guān),Lambda函數(shù)和S3以無服務(wù)器方式進行此操作。
S3水桶 (S3 Bucket)
The S3 bucket in this architecture serves as a cache that stores search results to be retrieved later. Callers of the API are given a token when they start a search, and the basic design is to use that token as part of the S3 object name to allow you to retrieve the contents on a subsequent call. To prevent the bucket from filling up with search results, you can set an expiration policy that is appropriate for the lifecycle of your API results (i.e. how long do you want the asynchronous results to stay alive?).
此體系結(jié)構(gòu)中的S3存儲桶用作緩存,用于存儲以后要檢索的搜索結(jié)果。 API的調(diào)用者開始搜索時會得到一個令牌,并且基本設(shè)計是將該令牌用作S3對象名稱的一部分,以允許您在后續(xù)調(diào)用中檢索內(nèi)容。 為了防止存儲桶填滿搜索結(jié)果,您可以設(shè)置一個適用于您的API結(jié)果生命周期的過期策略(即,您希望異步結(jié)果保持多長時間?)。
Note that the expiration policy can only be set in day increments, so even if you have results that should be considered stale after 30 minutes, with this approach you’ll still have the object in storage for at least a day.
請注意,過期策略只能以天為單位進行設(shè)置,因此即使您將30分鐘后的結(jié)果認為是過時的,使用這種方法,您仍將對象存儲至少一天。
You can associate a timestamp with the object and check it in your code to make sure that the result is ignored if it is more than a certain age, but the object itself will persist for at least a day.
您可以將時間戳記與對象關(guān)聯(lián),并在代碼中對其進行檢查,以確保結(jié)果(如果超過一定期限)將被忽略,但是對象本身將持續(xù)至少一天。
To set up your bucket, take the following steps in the AWS Management Console:
要設(shè)置存儲桶,請在AWS管理控制臺中執(zhí)行以下步驟:
Click Create Bucket from S3
單擊從S3 創(chuàng)建存儲桶
- Enter the name of the bucket and make note of which region you create it in (you’ll need to make sure your Lambda functions and API Gateway are all set up in this same region). Note that S3 bucket names are globally unique, which means a name like “test” will likely be taken. You’ll need to pick something that no other user has created before, so something that incorporates your name or the current date would be a good starting point 輸入存儲桶的名稱,并記下創(chuàng)建存儲桶的區(qū)域(您需要確保在同一區(qū)域中都設(shè)置了Lambda函數(shù)和API網(wǎng)關(guān))。 請注意,S3存儲桶名稱是全局唯一的,這意味著可能會使用“ test”之類的名稱。 您需要選擇以前沒有其他用戶創(chuàng)建過的內(nèi)容,因此可以使用包含您的姓名或當前日期的內(nèi)容作為一個很好的起點
- You can keep the bucket with the default permissions and no versioning — you’ll explicitly grant your Lambda function permission to this bucket, so don’t expose it publicly to the world (in fact, that would be a bad idea!) 您可以將存儲桶保留為默認權(quán)限,而無需進行版本控制-您將向該存儲桶明確授予Lambda函數(shù)權(quán)限,因此不要將其公開暴露給世界(實際上,這是個壞主意!)
Once the bucket is created, click on it and go to the Management tab
創(chuàng)建存儲桶后,單擊它并轉(zhuǎn)到“ 管理”選項卡
Enter a lifecycle by clicking Add Lifecycle Rule
通過單擊添加生命周期規(guī)則輸入生命周期
Enter a name and skip through the Transitions screen to end up on the Expiration screen
輸入名稱并跳過“過渡”屏幕以顯示在“ 到期”屏幕上
Since we didn’t add versioning to our S3 bucket, you only need to configure an expiration rule for the Current Version as illustrated below
由于我們沒有向S3存儲桶添加版本控制,因此您只需為“ 當前版本”配置到期規(guī)則,如下所示
Lambda函數(shù) (Lambda Functions)
I had the basic idea to use a Lambda function to perform a search, return a token to the caller, and write the results into an S3 bucket. The results could then be retrieved by a subsequent call, passing in the token and any additional filtering information (for example, “small car” in the example above).
我的基本想法是使用Lambda函數(shù)執(zhí)行搜索,將令牌返回給調(diào)用者,然后將結(jié)果寫入S3存儲桶。 然后可以通過后續(xù)調(diào)用,傳遞令牌和任何其他過濾信息(例如,上例中的“小型汽車”)來檢索結(jié)果。
However, I quickly realized that my Lambda function would return after I validated the input parameters and called back with a token, which meant that I wasn’t able to keep it alive to write the search results out to S3.
但是,我很快意識到,在驗證輸入?yún)?shù)并使用令牌進行回調(diào)之后,Lambda函數(shù)將返回,這意味著我無法保持活動狀態(tài),無法將搜索結(jié)果寫入S3。
What I needed was a way to continue code execution after I had the token so I could return to the API caller. To do this, I created two Lambda functions, one to validate the parameters, and the other to perform the search and lookup the cached results.
我需要的是在獲得令牌后繼續(xù)執(zhí)行代碼的方法,這樣我就可以返回到API調(diào)用者。 為此,我創(chuàng)建了兩個 Lambda函數(shù),一個用于驗證參數(shù),另一個用于執(zhí)行搜索和查找緩存結(jié)果。
The first function validates the parameters, and once it has done so, it invokes the second Lambda function asynchronously to kick off the search, then returns with a generated token back to the caller while the second Lambda function churns away. The token that my generateToken function used in my workshop was just a timestamp since I didn’t have scalability considerations, but it could also be a UUID or other generated ID.
第一個函數(shù)驗證參數(shù),一旦完成驗證,它將異步調(diào)用第二個Lambda函數(shù)以開始搜索,然后在第二個Lambda函數(shù)失效時以生成的令牌返回給調(diào)用者。 由于我沒有可伸縮性考慮,所以我的generateToken函數(shù)在我的講習(xí)班中使用的令牌只是一個時間戳,但是它也可以是UUID或其他生成的ID。
Because this Lambda function invokes another Lambda function, you’ll need to give it the appropriate permissions to make this call. You do this by creating the appropriate IAM role following these steps:
由于此Lambda函數(shù)將調(diào)用另一個Lambda函數(shù),因此您需要為其授予適當?shù)臋?quán)限才能進行此調(diào)用。 您可以按照以下步驟通過創(chuàng)建適當?shù)腎AM角色來做到這一點:
In your Lambda function, under Execution role, select Create a Custom Role in the dropdown
在Lambda函數(shù)的“執(zhí)行角色”下,從下拉列表中選擇“ 創(chuàng)建自定義角色 ”
- This will launch IAM in a new tab 這將在新標簽頁中啟動IAM
Select Create a new IAM Role from the dropdown for IAM Role and provide it with a name
從“ IAM角色 ”下拉列表中選擇“ 創(chuàng)建新的IAM角色” ,并為其提供名稱。
In the full list of IAM roles, select this new role and click Attach Policies
在IAM角色的完整列表中,選擇此新角色,然后單擊“ 附加策略”。
Filter for the AWSLambdaRole policy and add it to this role. Optionally, you can modify the JSON to give it access only to the second Lambda function after you create it in the following step, by referring to its ARN in the Resource field
過濾AWSLambdaRole策略并將其添加到該角色。 (可選)您可以修改JSON,以使其在接下來的步驟中通過在Resource字段中引用其ARN使其僅訪問第二個Lambda函數(shù)。
The second Lambda function has two responsibilities — to perform the search and save the results into an S3 bucket, and to retrieve the results from an S3 bucket when called with a valid token. I could have separated this logic and created three Lambda functions, but I felt that it was a better design to have the logic that accessed the cache and knew how to encode/decode the object in one place.
Lambda的第二個功能有兩個職責-執(zhí)行搜索并將結(jié)果保存到S3存儲桶中,以及在使用有效令牌調(diào)用時從S3存儲桶中檢索結(jié)果。 我本可以分開這個邏輯并創(chuàng)建三個 Lambda函數(shù),但是我認為讓邏輯訪問緩存并知道如何在一處編碼/解碼對象是一個更好的設(shè)計。
Because API Gateway allows you to map query parameters, you’ll find it easy to differentiate between the cases when this function is being called to perform a new search and when it is being asked to retrieve a search result (I’ll demonstrate how to do that later). Note that this function calls a lengthy internal doSearch function which writes results to S3 based on token provided from the previous function.
由于API Gateway允許您映射查詢參數(shù),因此您將很容易區(qū)分在調(diào)用此函數(shù)以執(zhí)行新搜索和要求其檢索搜索結(jié)果的情況之間(我將演示如何稍后再執(zhí)行)。 請注意,此函數(shù)調(diào)用一個冗長的內(nèi)部doSearch函數(shù),該函數(shù)根據(jù)前一個函數(shù)提供的令牌將結(jié)果寫入S3。
Because this Lambda function makes a call to read and write from S3, you’ll have to set the appropriate permissions for this Lambda function — which will be different than the first one. Follow the same set of steps to create an IAM role, only this time rather than the AWSLambdaRole policy, you’ll want to associate the AmazonS3FullAccess policy — again optionally providing the ARN of the specific S3 bucket that you want to provide full access to.
由于此Lambda函數(shù)會調(diào)用S3進行讀取和寫入操作,因此您必須為此Lambda函數(shù)設(shè)置適當?shù)臋?quán)限-這將與第一個函數(shù)不同。 遵循同一組步驟來創(chuàng)建IAM角色,只是這次而不是AWSLambdaRole策略,您將要關(guān)聯(lián)AmazonS3FullAccess策略-再次有選擇地提供要提供完全訪問權(quán)限的特定S3存儲桶的ARN。
API網(wǎng)關(guān) (API Gateway)
With the Lambda functions out of the way, the next step is to create an API Gateway around these functions so that a user has a REST API to call into. Remember, the flow I wanted to build from a client perspective was:
在不使用Lambda函數(shù)的情況下,下一步是圍繞這些函數(shù)創(chuàng)建API網(wǎng)關(guān),以便用戶可以調(diào)用REST API。 記住,我要從客戶角度構(gòu)建的流程是:
- POST call to the API with the desired search parameters 使用所需的搜索參數(shù)對API進行POST調(diào)用
- Get a token back as a response 取回令牌作為回應(yīng)
- Ask the user some additional questions to help narrow the results 向用戶詢問一些其他問題,以幫助縮小結(jié)果范圍
- GET call to the API with the token and additional filter criteria to get the actual result set 使用令牌和其他過濾條件對API進行GET調(diào)用,以獲取實際結(jié)果集
API Gateway makes it easy and convenient to access your Lambda functions as desired.
API網(wǎng)關(guān)使您可以根據(jù)需要輕松便捷地訪問Lambda函數(shù)。
The first step is to create your new API. In the AWS Management Console, you can navigate to API Gateway and click Create API to create a new API. Once you’ve given it a name, you need to create the methods that you want to use in accessing the API. In my case, that meant selecting POST and GET as new methods from the Actions drop down menu.
第一步是創(chuàng)建新的API。 在AWS管理控制臺中,您可以導(dǎo)航到API網(wǎng)關(guān),然后單擊創(chuàng)建API以創(chuàng)建新的API。 為其命名后,需要創(chuàng)建要用于訪問API的方法。 就我而言,這意味著從“ 操作”下拉菜單中選擇POST和GET作為新方法。
Let’s start with the POST. Once you’ve selected the POST method, you’ll be asked the Integration Type you’d like to use. Select Lambda Function, and then fill in the details with the first Lambda function you created to validate parameters and kick off the search. You don’t need to point API Gateway to the second Lambda function that does the search — that is done by by the validation function for you.
讓我們從POST開始。 選擇POST方法后,系統(tǒng)將詢問您要使用的集成類型 。 選擇Lambda Function ,然后使用您創(chuàng)建的第一個Lambda函數(shù)填寫詳細信息以驗證參數(shù)并開始搜索。 您無需將API Gateway指向執(zhí)行搜索的第二個Lambda函數(shù),這是由驗證函數(shù)為您完成的。
After you set these parameters, you’ll see the full API flow, along with a TEST sidebar that will allow you to pass a test payload to your API to see if it executes properly.
設(shè)置完這些參數(shù)后,您將看到完整的API流程以及一個TEST側(cè)邊欄,該邊欄將允許您將測試有效負載傳遞給API,以查看其是否正常執(zhí)行。
For the GET call, do similar, though in this case you’re going to call the second Lambda function passing in a token so it knows to retrieve the results from your S3 cache. Also, in this case you won’t have a JSON payload to pass on — rather the expectation is that the customer supplies query parameters in the URL. API Gateway allows you to do this transformation easily via a Mapping Template.
對于GET調(diào)用,請執(zhí)行類似操作,盡管在這種情況下,您將調(diào)用傳遞令牌的第二個Lambda函數(shù),以便它知道從S3緩存中檢索結(jié)果。 同樣,在這種情況下,您將沒有傳遞JSON有效負載的方法,而是期望客戶在URL中提供查詢參數(shù)。 API Gateway使您可以通過映射模板輕松進行此轉(zhuǎn)換。
The basic steps are as follows:
基本步驟如下:
Add a GET method under the Actions drop down menu
在“ 操作”下拉菜單下添加GET方法
Set Integration Type to Lambda Function
將積分類型設(shè)置為Lambda函數(shù)
- Enter in the details of the second Lambda function 輸入第二個Lambda函數(shù)的詳細信息
Once created, click on the Integration Request step of your GET method execution
創(chuàng)建完成后,單擊GET方法執(zhí)行的Integration Request步驟
Expand the Mapping Templates section and click Add mapping template
展開“ 映射模板”部分,然后單擊“ 添加映射模板”。
Type application/json into the edit box and click the check to confirm
在編輯框中輸入application / json ,然后單擊檢查以確認
Enter in the mapping from query parameters to JSON request — you’ll do this with keys of the form "field": “$input.params('queryparam')" This will map the query param named queryparam to a field named field
輸入從查詢參數(shù)到JSON請求的映射-您將使用"field": “$input.params('queryparam')"形式的鍵來執(zhí)行此操作"field": “$input.params('queryparam')"這會將名為queryparam的查詢參數(shù)queryparam到名為field
The nice thing here is that you don’t have to have the same name for the query parameters exposed to your client as for internal usage in your Lambda function. For example, in my case I expect parameters of User, CarSize, SupplierRating, and UpgradeClass but I map these to id, size, rating, and upgrade respectively for internal use.
這里的好處是,不必為暴露給客戶端的查詢參數(shù)使用與Lambda函數(shù)內(nèi)部使用的名稱相同的名稱。 例如,在我的情況下,我希望使用User,CarSize,SupplierRating和UpgradeClass的參數(shù),但是我將它們分別映射到id,大小,等級和升級以供內(nèi)部使用。
構(gòu)建和部署 (Build and Deploy)
Now that you’ve integrated your Lambda function into API Gateway, you’re ready to build and deploy. Under the Actions menu, select Deploy API. API Gateway will ask you for a Deployment Stage; choose [New Stage] to create a new stage, and provide it a name like Beta. After you deploy the API, API Gateway will tell you the URL to use to invoke your API. You use the same URL for both the POST and GET functions. Pretty easy, isn’t it?
現(xiàn)在,您已將Lambda函數(shù)集成到API Gateway中,就可以開始構(gòu)建和部署了。 在“操作”菜單下,選擇“ 部署API” 。 API網(wǎng)關(guān)將要求您進行部署; 選擇[新階段]創(chuàng)建一個新階段,并提供一個類似Beta的名稱。 部署API后,API網(wǎng)關(guān)將告訴您用于調(diào)用API的URL。 POST和GET函數(shù)使用相同的URL。 很簡單,不是嗎?
結(jié)語 (Wrap Up)
What I described here is the foundation for an asynchronous serverless API. There are a lot of edge cases and error handling that I glossed over, as well as techniques within API Gateway to harden the API that I didn’t address such as validating that all required parameters are set before invoking the Lambda function or requiring an access token as opposed to creating a wide-open API.
我在這里描述的是異步無服務(wù)器API的基礎(chǔ)。 我掩蓋了很多極端情況和錯誤處理,以及API網(wǎng)關(guān)中用于強化我未解決的API的技術(shù),例如在調(diào)用Lambda函數(shù)或要求訪問之前驗證是否已設(shè)置所有必需的參數(shù)令牌而不是創(chuàng)建一個廣泛開放的API。
In addition, this use case was for a small workshop environment. You’d have to look at your own use case to understand the scale you need and whether this approach would work for you. You’d want to pay particular attention to the concurrent execution settings for your Lambda function. If the underlying call you are trying to make takes a minute to run for example, even with a limit of 1000 concurrent executions you’d only be able to make 16 calls per second, which may not prove sufficient for a full production workload.
另外,該用例用于小型車間環(huán)境。 您必須查看自己的用例,以了解所需的規(guī)模以及此方法是否對您有用。 您需要特別注意Lambda函數(shù)的并發(fā)執(zhí)行設(shè)置。 例如,如果您要進行的基礎(chǔ)調(diào)用需要一分鐘才能運行,即使限制了1000次并發(fā)執(zhí)行,則您每秒只能進行16次調(diào)用,這可能不足以滿足全部生產(chǎn)工作負荷。
Caveats aside, for the right use cases this approach can be a simple and powerful way to create an async API without having to stand up dedicated servers or a caching solution.
除了警告之外,對于正確的用例,此方法可以是一種創(chuàng)建異步API的簡單而強大的方法,而無需使用專用服務(wù)器或緩存解決方案。
翻譯自: https://www.freecodecamp.org/news/how-to-design-a-serverless-async-api-6cfd68939459/
異步api
總結(jié)
以上是生活随笔為你收集整理的异步api_如何设计无服务器异步API的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 梦到蚂蝗吸血是啥意思
- 下一篇: 做梦梦到跟死人说话好不好