I need to write some endpoint that simulate the response of third party server to run performance test regularly. I have decided to go with API Gateway to Step Function (waits 2 seconds) to Lambda that returns response based on the request. This needs to be done to emulate latency of 2 seconds on third party service. The question is what would be the cheapest solution to solve the task using these services.
Should I go only with Lambda alone (no Step Functions and even API Gateway)? If I use only Lambda we would need many concurrent Lambdas each running for 2 seconds. What is the cheapest solution?
When working with AWS services and trying to work out pricing, you should use the AWS Price Calculator. Each service also has pricing breakdowns:
AWS Step Functions Pricing
AWS Lambda Pricing
Here's a quick work-up I did:
Service
Price
Request/day
Notes
Lambda
$32/mo
10k
5 second runtime
Step Function
$76/mo
10k
n/a
From these numbers, the most cost effective solution would be to remove the Step Functions from the orchestration and just go with Lambdas.
A nice addition of using Lambdas are the ability to pass in a parameter to specify the 3rd party end-point latency. Or even a range or latency, i.e., random delay between 1 second and 3 seconds.
You can review this estimate here.
Consider a SQS Delay Queue in front of the Lambda to simulate the 2 second latency. The first million SQS messages are always free each month, the next million cost $0.40.
Your Lambdas will execute without any artificial delay, reducing your compute cost by (more than?) half.
I have enabled provisioned concurrency (5 units) on one of my lambda functions which is invoked via API Gateway requests.
My impression of this was that it eliminates "cold starts" or "inits" altogether yet when I hit my appropriate Api endpoint after an "idle period" X-Ray & Cloudwatch show me what I would have thought is a cold start?
Init Duration: 2379.57 ms
Subsequent requests don't have this and my total time for the request goes from approx 3.8s to approx 200ms.
My understanding was that provisioning the concurrency would automatically hit the provisioned ones first and thus ALWAYS produce that latter 200ms scenario (assuming we are not exceeding concurrency count). I've created a separate lambda and am the only one using it so I know that is not the issue. I've created an alias, which point to to a version, not $LATEST.
Lambda metrics display "Invocations" "ProvisionedConcurrencyInvocations" with the appropriate colour on the chart which indicated provisioned concurrency.
Why am I getting what is seemingly a cold start still?
If all the above seems OK and my understanding is indeed what should be happening then would it be related to the services used in the lambda itself?
I use S3, SQS and DynamoDB.
Lambda is a c# .net core 3.1 function
Edit #1 -
I Should clarify that the function is actually an asp.net core 3.1 web api serverless and has all the usual attached ConfigureServices/Configure points as well as Controller classes.
I have timed and written to console the times it takes to ConfigureServices/Configure and Constructor of the controller. Times are .6s/0.0s/0.0s at first run.
I have enabled XRay at the SDK level in Startup.cs with:
AWSSDKHandler.RegisterXRayForAllServices();
I can now see the following breakdown in X-Ray:
And after a few (quick) executions I see:
I want to have EVERY single execution sitting at that 163ms and bypass the nearly 4s entirely.
I used to think aws lambda was best suited to handle background tasks which did not require immediate results. However more and more I have seen aws lambda being used to handle real-time requests as well, for example fetch users from a db in a http get.
API Gateway -> AWS Lambda -> Results
Is this a standard approach or is this the improper use of lambda ?
Use of API Gateway to provide a front end for the Lambda function invocation is the standard way of executing Lambda function code on the fly. If you are concerned about the cold starts on the function; and want to minize the latency, you can consider Provisioned Concurrency to keep 'n' active containers at a small cost.
I am currently using AWS EC2 for my workloads.
Now I want to convert the EC2 server to the Serverless Platform i.e(API Gateway and Lambda).
I have also followed different blogs and I am ready to go with the serverless. But, my one concern is on pricing.
How can I predict per month cost for the serverless according to my use of EC2? Will the EC2 Cloudwatch metrics help me to calculate the costing?
How can I make cost comparison?
Firstly, there is no simple answer to your question as a simple lift and shift from a VM to Lambda is not ideal. To make the most of lambda, you need to architect your solution to be serverless. This means making use of the event-driven nature of Lambda.
Now to answer the question simply, you are charged only for the time it takes to serve a request (to the next 100ms). So if your lambda responds to the request in 70ms you pay for 100ms of execution time. If you serve the request in 210ms then you pay for 300ms.
You also pay for the memory allocated to the function on the order of GB per/month.
If you have a good logging or monitoring strategy you could check how long it takes to serve each type of request and how often they occur. If your application is fairly low-scale and is not accessed often (say all requests come within an 8 hour window) then you may end up saving money with lambda as you are only paying AWS for the time spent serving the request.
Also, it may help to read the following article on common pitfalls:
https://medium.com/#emaildelivery/serverless-pitfalls-issues-you-may-encounter-running-a-start-up-on-aws-lambda-f242b404f41c
If i understood the whole concept correctly, the "serverless" architecture assumes that instead of using own servers or containers, one should use bunch of aws services. Usually such architecture includes Amazon API Gateway, bunch of Lambda functions and DynamoDB (or alternative) for storing data and state, as Lambda can't keep state. And such services as EC2 is not participating in all this, well, because this is a virtual server and it diminish all the benefits of serverless architecture.
All this looks really cool, but i feel like i'm missing something important, because right now this seems to be not applicable for such cases as real time applications.
Say, i have 2 users online. One of them performs an action in an app, which triggers changes in database, which in turn, should trigger changes in the second user app.
The conventional way to send some data or command from server to client is websocket connection. But with serverless architecture there seem to be no way to establish and maintain websocket connection. So... where did i misunderstood the concept? Or, if i understood everything correctly, then how do i implement the interactions between 2 users as described above?
where did i misunderstood the concept?
Your observation is correct. It doesn't work out of the box using API Gateway and Lambda.
Applicable solution as described here is to use AWS IoT - yes, another AWS Service.
Serverless isn't just a matter of Lambda, API Gateway and DynamoDB, it's much bigger than that. One of the big advantages to Serverless is the operational burden that it takes off your plate. No more patching, no more capacity planning, no more config management. Those may seem trivial but doing those things well and across a significant fleet of instances is complex, expensive and time consuming. Another benefit is the economics. Public cloud leverages utility billing, meaning you pay for what you run whether or not you actually use it. With AWS most of the billing per service is by hour but with Lambda it's per 100ms. The cheapest EC2 instance running for a full month is about $10/m (double that for redundancy). $20 in Lambda pricing gets you millions of invocations so for most cases serverless is significantly cheaper.
Serverless isn't for everything though, it has it's limitations, for example it's not meant for running binaries. You can't run nginx in Lambda (for example), it's only meant to be a runtime environment for the programming languages that it supports. It's also specifically meant for event based workloads, which is perfect for microservice based architectures. Small independent discrete pieces of compute doing work that when done they send an event to another(s) to do something else and if needed return a response.
To address your concerns about realtime processing, depending on what your code is doing your Lambda function could complete in less than 100ms all the way up to 5 minutes. There are strategies to optimize it's duration time but in general it's for short lived work which is conducive of realtime scenarios.
In your example about the 2 users interacting with the web app and the db, that could very easily be built using serverless technologies with one or 2 functions and a DynamoDB table. The total roundtrip time could be as low as milliseconds if not seconds, it really all depends on your code and what it's doing. These would all be HTTP calls so no websockets needed. Think of a number of APIs calling each other and your Lambda code is the orchestrator.
You might want to look at SNS (simple notification service). In your example, if app user 2 is a a subscriber to an SNS topic, then when app user 1 makes a change that triggers an SNS message, it will be pushed to the subscriber (app user 2). The message can be pushed over several supported protocols (Amazon, Apple, Google, MS, Baidu) in addition to SMTP or SMS. The SNS message can be triggered by a lambda function or directly from a DynamoDB stream after an update (a database trigger). It's up to the app developer to select a message protocol and format. The app only has to receive messages through its native channels. This may not exactly be millisecond-latency 'real-time', but it's fast enough for all but the most latency-sensitive applications.
I've been working on an AWS serverless application for several months now, and am amazed at the variety of services available. The rate of improvement and new features being added is enough to leave you out-of-breath.