Context:
I have a usecase where my backend service should compute 1 or more features, where each feature is a simple peace of computation (can be as simple as adding two numbers) and each feature takes input and return an output value, which can be boolean or a number. Client can actually request features (1 or 10 etc), also each feature can have multiple versions.
Design:
Lambda function seems like a good choice, since it supports versioning and takes care of scaling. In my design, one Lambda will receive the request and then call further lambda functions in parallel (Say user asked for 12 features, Lambda function L1 will invoke 12 Lambda functions in parallel) synchronously, and return all computed feature values as one response (HTTP). This way, all features can be versioned in their own Lambda functions.
Questions:
Is it ok to call a lambda function directly from another Lambda function? Is it a good usecase for using Lambda functions?
Thanks
I think Lambda would work just fine for your use case. For versioning, you could use the API versioning provided by API Gateway but I think that is a bit much for your case. Just create different functions.
Check out serverless.com. It is a solid framework and easy to get started with. It will take a lot of the work out of setting it up, plus you'll have your infrastructure as code.
Yes, it is okay to call lambdas from other Lambdas. There is not a 'clean' way to do that though. On the other hand, 'Step functions' may be what you need. Lambda support's chaining functions in a workflow. The previous lambda is not 'calling' the next function as much as proceeding to the next step in the workflow. The Serverless framework also supports using the method and can be configured in the serverless.yml config file
Related
The official guide for AWS API gateway introduces the way to use a lambda function to make responses to the API calls from the gateway. But it can only deal with one function, not for the condition of several functions call one by one.
For a solution, here are two to the best of my mind:
Use AWS Step Function services to bundle the function workflow.
Use one main thread function for orchestration.
Obviously, method 1 will bring extra fees, while method 2 needs a redundant function to run for long.
Could you please give me any help?
If they must be completed one after another before you can return the result, use AWS Step Functions (like you said) to orchestrate this. Synchronous invocation of the other Lambda is also an option (though it's commonly an architectural smell and indicates other issues with your architecture - why are the Lambdas not combined if they need each other etc.)
For asynchronous invocation of the other function (fire and forget), either invoke the Lambda using invocation type Event or even better would be to have an SQS queue in between the Lambdas for improved resiliency.
Seems a little inefficient the way it currently is:
response.body = {
user: await userService(userID) // calls a user service to get info on user
friends: await friendsService(userID) // calls a friends service to get info on friends for
}
Let's say the userService and friendsService are configured on different API Gateway endpoints.
Then wouldn't that make the network request take longer than if I were to just package my entire backend into one zip file that's uploaded to AWS Lambda.
Seems like this is very inefficient.
Is there a way to call other lambdas without having to make a network request? I understand putting the lambdas/gateway in the same VPC as the main Gateway endpoint exposed to the internet, but this is expensive?
Anyway to do this more efficiently?
You can call a Lambda function by using the AWS SDK (a LambdaClient object). So, for example assume you wrote two Lambda functions - funA and funB.
Next assume:
you want to call funB from funA
you wrote your Lambda function by using the Lambda Java runtime
You can use the Lambda Java API to invoke funB. There is no need to wrap either one in Restful call using API Gateway. You can use the AWS SDK. Here is the Java API example that shows you how to invoke a Lambda function:
https://github.com/awsdocs/aws-doc-sdk-examples/blob/master/javav2/example_code/lambda/src/main/java/com/example/lambda/LambdaInvoke.java
#smac2020 writes in the answer about using SDK, that is of course a network call too. It just skips api gateway and calls directly AWS api.
I think the key point about Lambda is if it scales well. Let you try to thing about the algorithms in a different way. For example you can create a pipeline where in each step your "state object" is enriched with additional data. You can use step function or SQS and send the requests in between the steps or you can make the client responsible to manage the data. You should try to avoid one function waiting for another function. You are then paying two lambdas running - the caller and the called one.
If you are thinking "but microservices..." - look at the design of the AWS API itself. You do not need output of one service as an input to another one. It needs some time to adapt and to look at problems from different perspectives. In your case I would consider if the user list can for example live in the user object and the calls can be merged (look at some no-sql database design principles).
I have been checking some resources on internet and all the examples of lambda in AWS are very basic but I am not sure how we will modularize an application with multiples dependencies, for example in java we usually have some structure like this
packages
repository
controllers
..
..
And we place the code related to each logic inside the package, but now in AWS seems that is more like scripting that will glue the pieces than OOP that I am used to, so my question is how we handle (if apply) this relationships, because I have seen code that all the logic is in one lambda and that not seems the best way to go, for example if we had some functionality that fist authenticate, authorize, transform, call an external api, get the response and then do a call to a final rest endpoint, how we can split this, for example will be the same lambda with packages(directories) inside and we call to each other? or we have multiples lambdas each one with one purpose? and this will generate cold start for each lambda?
I was thinking in using layers, but seems very new and not sure if this is production ready feature and seems that is more related to reuse code that is common across all the environment that the way to modularize our code
Generally when you're developing Lambda functions, the function should have a single purpose (which will keep the function relatively small).
If you have multiple actions, by having each Lambda as its own function it will improve the development and deployment experience. Having a single developer working on the function reduces the risk of breaking unrelated functionality, whilst also allowing them to deploy only the function that they've worked on.
To orchestrate between Lambdas for APIs people tend to use API Gateway (be that for your clients communicating to the Lambdas, or between the Lambdas themselves).
Regarding any shared dependencies/libraries Lambda Layers as you mentioned is the correct way to go. It will allow you to centralise the dependencies that your applications share rather than the need to package the Lambda with a version of the dependencies each time.
There's an article on Best Practices for Developing on AWS Lambda that should offer additional guidance.
So I have a class and some constants defined that 10 or more lambda functions will need. Currently, I have packaged the common code into each lambda function. Unfortunately, if I change the common code I have to repackage all 10 lambda functions and upload the changes.
Ideas that I had considered:
Lambda return a class with defs and constants – not feasible, lambda returns JSON
Try to magically load the common code from S3 – (not sure how and do not
really like that there are multiple steps to update a lambda
function)
Packaged the common code into each lambda function – (current design)
What is the best method for referencing common python code for lambda?
The first thing I did was an automatic deployment script in python for my lambdas + API gateway (+ intern usage of S3 etc). You can deploy your lambda without changing your API gateway endpoint, and be doing so, all your lambdas can be updated in one click without modification of the interaction with outside of your AWS box.
Inside, you can manage the bounds with S3 or dynamoDB or anything else automatically. It's an investment at the beginning, but it's definitely worth it, even more in your case with many lambdas.
Your solution of a constant provider could be a short term good strategy, but you'll need to be sure that your old lambdas will work with your news constants, so either you are limited in your provider's evolutions, either you'll have to manage many versions of your provider. Lambdas are meant to be easily deployed and replaced.
Say I have a Lambda function called 'TestExecutor' which takes takes in an argument which contains ARNs for N 'Tests' which are also implemented as Lambda functions.
The workflow:
TestExecutor is invoked with a list of ARNs of various 'Tests'
TestExecutor calls each Test concurrently; each Lambda is expected to return a JSON
TestExecutor waits for each Test to complete. It consolidates all the JSONs received
Consolidated JSON is stored in DynamoDB/S3
Problem statement - What is the best way to create this kind of workflow in a Serverless manner?
I considered two AWS Services to manage this:
AWS Step Functions - My step function would need states for each possible 'Test' Lambda that can be executed. I want to give flexibility to the user to invoke any Lambda without needing to 'register' it in my Step function.
AWS SWF - Just seems a little overkill. Suffers from the same problem as above too.
So right now the best I can think of is doing this in a simple manner:
In my TestExecutor Lambda, I could create N threads for N tests each thread invokes a particular Test's Lambda function. Each thread waits for its Test to return a JSON. As all executions are successful, all JSONs are consolidated. Consolidated JSON is stored in DynamoDB.
I'm not happy with this solution - it will be a little tricky to manually manage failures and retries of the Test Lambdas from within the TestExecutor Lambda. This is my first time into trying something serverless, but it just seems like the wrong pattern. I'd like to get a nice top-down view of my workflow - it seems like monitoring this would be a little messy and scattered since there's no formal link between TestExecutor and the Test Lambdas
Maybe I could create an SQS Queue along with each Test Lambda. For each ARN supplied to the TestExecutor, I could push a message to a corresponding queue. But what now? I'd have to create 'Listener' Lambda's for each Test which polls each queue every T seconds. It would then invoke the actual Test Lambda. This also sounds needlessly complex.
Would love to hear some advice! Cheers.
AWS SWF doesn't suffer from the same problem as it doesn't require registration of a lambda function to invoke it.
The main limitation of SWF is that it is still not possible to run decider process as a lambda function. So you'll have to run it somewhere else. If you already have some host that can run it implementing your use case using AWS Flow Framework is pretty straightforward.
You could leverage the AWS SDK to generate a Step Machine using said ARNs from within a Lambda Function.
It would require some way to clean up afterwards somehow, and / or avoid duplicates, or the console would quickly get messy.