Is it possible to trigger a lambda init in AWS? - amazon-web-services

Aws lambdas have 3 steps in their lifecycle:
init
invoke
shutdown
Is there a way to trigger automatically a lambda init without deploying any code?
Update:
I have some actions that are launched during the init: saving the content of a file in a variable. Then during the invoke actions, the content is not downloaded anymore. But I need to launch the action of downloading from time to time. Then, I was wondering if there's a way to trigger the init action.

Why not just call your init() function again?
Take the following Go Lambda for example:
// handleRequest does process every request to the Lambda.
func handleRequest(ctx context.Context) error {
init() // <-- call it whenever you want in your handler again
}
// init does store some data from a file in a variable.
func init() {}
func main() {
init() // <-- called on the first start of the Lambda
lambda.Start(handleRequest)
}
The init function is called in the main() method, which is executed when the Lambda is started for first time (cold start or init). But if you move your "business logic" for the initialisation into a separate function, you can call it whenever you want in your handler function.
Note: I don't think at all that this is a great idea. It is definitely a design "smell" if you need/want to do something like this. So you should rather rethink what you are doing than building workarounds like this.

There is no way you can manually trigger those events as I know however, you can perform some action for those events.
check AWS Extention API if you are interested.
https://docs.aws.amazon.com/lambda/latest/dg/runtimes-context.html

Perhaps you should take a look at lambda layers. This allows you to place some files in advance, so that your invocations can access it at runtime (without having to download it). You can then easily update your layer whenever you need.
See documentation here

I figured out a way to do this in NodeJs Lambdas. I’m not aware of any previous solutions for JS Lambdas. Normally, the lambda container is paused before async operations complete in the init phase.
The key is to leverage an AWS Lambda custom Extension. Then if you enable provisioned concurrency, the Lambdas execute the init phase before a request. You have to determine how many provisioned concurrency instances to keep online because concurrent requests can trigger on-demand instances. Or you can enable auto-scaling with provisioned concurrency to try to scale out ahead of the load.
This article explains the details and includes a link to the GitHub sample repo.
https://barker.tech/aws-lambda-nodejs-async-init-88b5c24af567?source=friends_link&sk=79dbb80045ad97c62f58fa4b74ade68b
https://github.com/chuckbarkertech/nodejs-example-async-init-extension
You still have to deploy code. But you can trigger the init before requests hit the lambda by combining provisioned concurrency with AWS Lambda Extensions like the example info above.

Related

Patterns for HTTP endpoint Lambda calling other Lambdas and returning value to user

i have a question about lambda anti patterns, and how to address my specific situation.
My current setup is this:
user/webpage -> ApiGateway -> Lambda1 -> synchronously calls Lambda2 (my other microservice) -> back to lambda1 -> back to user
Currently my lambda2 is behind an apigateway as well, but I toyed with idea of invoking directly. Either way it's basically another microservice that I control.
I understand that generally, lambdas calling other lambdas are considered an antipattern. All the blogs/threads/etc online mention using stepfunctions instead, or sqs, or something else.
In my situation, I don't see how I could use stepfunctions, since I have to return something to the webpage/user. If I used a stepfunction, it seems like I would have to then poll for the results, or maybe use websockets; basically in my webpage I would not be able to just call my endpoint and get a result, I'd have to have some way to asynchronously get my result.
Similarly with a queue, or any other solution I saw online, it's basically all asynchronous.
Is there any other pattern or way of doing this?
Thanks.
While invoking a lambda from another lambda, everything will work fine except when the second lambda timeouts or it throttles. If your business logic is built in such a way that failures are handled gracefully and has idempotent behaviour built in, then a lambda calling another lambda (via API gateway or direct invocation) should work fine. Having said that, AWS has come out with Synchronous Express Workflows for AWS Step Functions. The linked blog has detailed examples of using it. The only caveat here is that your entire operation should get over in 5 minutes. The maximum duration an express workflow can run is 5min. So if your application flow is completing within that time limit then this is the recommended way of orchestrating services.

Converting an AWS Lambda Function into a container

I currently have a bunch of AWS Lambda functions and would like to spin them each up in containers (preferably Docker) to integrate with the current CICD pipeline. It's totally OK to have these containers spun up in an Amazon service such as Fargate -- the important thing is that it must be spun up in a container. The closest thing I've found is this repo by Amazon that converts images into Lambdas, though this is the opposite of what I'm looking for.
Is this task possible, and if so what's the best way to go about it?
Behind the scenes, a Lambda "function" is a Python script that listens for invocation events and invokes the actual handler function. This means that you can pretty easily invoke the function using the standard Python "script" code:
if __name__ == "__main__":
args = # this is the tricky part
ctx = # some dict that looks like what Lambda expects
handler(args, ctx)
These two parameters are just dicts, so if you can populate them with something that looks right then you can wrap the entire thing in a container and deploy it to ECS or Batch, or your own Docker daemon.
The problem is how you populate them, and that depends on what your lambda functions do -- which you don't say -- and how they're invoked -- which you also don't say.
You could use command-line parameters. For example, if your lambda is intended to respond to an S3 PutObject operation, then all you really need is the bucket and key name. From that you can easily create a dummy S3 invocation event, using fake values for all of the other fields.
If you invoke your Lambda in response to an SQS message it's even easier: your "main" handler enters a loop that polls SQS, and reformats the messages that it pulls off the queue.
Other event sources are going to be much harder. It may make sense (depending on why you're doing this) to use SQS for all invocations, and simply pass a fully-formed event message into the queue.

How do you run ('invoke') an AWS lambda function?

I have written and saved a lambda function. I see:
Congratulations! Your Lambda function "lambda_name" has been
successfully created. You can now change its code and configuration.
Choose Test to input a test event when you want to test your function.
Now how do I run it? I cannot see a 'run' or 'invoke' button as I would expect
Note
The lambda doesn't accept any arguments (it's extremely simple - for the purposes of this question, please presume it's simply 2 * 2 so when I run it it should not require any inputs and should return 4).
Also note
I can see a tonne of different ways to run the lambda here. I just want the simplest way (preferably a button in the browser)
Sending a test message via the Lambda console will run your Lambda function. The test message that you configure will define what is in the event parameter of your lambda handler function.
Since you are not doing anything with that message, you can send any arbitrary test message and it should work for you. You can just use the default hello world message and give it an arbitrary name.
It should then show you the results: any logs or returned objects right in the AWS Lambda console.
Further reading here
AWS Lambda functions are typically triggered by an event, such as an object being uploaded to Amazon S3 or a message being send to an Amazon SNS topic.
This is because Lambda functions are great at doing a small task very often. Often, Lambda functions only run for a few seconds, or even less than a second! Thus, they are normally triggered in response to something else happening. It's a bit like when somebody rings your phone, which triggers you to answer the phone. You don't normally answer your phone when it isn't ringing.
However, it is also possible to directly invoke an AWS Lambda function using the Invoke() command in the AWS SDK. For convenience, you can also use the AWS Command-Line Interface (CLI) aws lambda invoke command. When directly invoking an AWS Lambda function, you can receive a return value. This is in contrast to situations where a Lambda function is triggered by an event, in which case there is nowhere to 'return' a value since it was not directly invoked.

aws lambda invoke multiple lambda

I need my python lambda to invoke multiple lambda so they can run in parallel. I have it working - kind of. To test it, I invoke the code below for 5 different lambda calls (could be more in the future)... when i look at the Step Function console, I only see 2 lamdbas running concurrently and the other 3 are ignored after the first 2 finished. In researching concurrency issues, I didnt find a limit that is this low (5 should be nothing for AWS!)..
response = lambdaClient.invoke(
FunctionName=lambdaToInvoke <---this var is an ARN,
InvocationType='Event',
Payload=json.dumps(event) <--just passing state
)
All IAM is provisioned...Any thoughts are appreciated!
Usually when I need to do a "fan out" operation like you are describing I don't invoke the lambda functions directly.
Rather I would recommend you setup your 5 "slave" lambda functions to get activated from either SNS or SQS. From your "master" function you can use the SDK to create a SNS alert or SQS message.
What happens when you try to manually invoke the 3 functions that don't run?
Do you have logging setup in CW logs? Can you post?

How can I keep warm an AWS Lambda invoked from API Gateway with proxy integration

I have defined a lambda function that is invoked from API Gateway with proxy integration. Thus, I have defined an eager resource path for it:
And referenced my lambda function:
My lambda is able to process request like GET /myresource, POST /myresource.
I have tried this strategy to keep it warm, described in acloudguru. It consists of setting up a CloudWatch event rule that invokes the lambda every 5 minutes to keep it warm. Unfortunately it isn't working.
This is the behaviour I have seen:
After some period, let's say 20 minutes, I call GET /myresource from API Gateway and it takes around 15 seconds. Subsequent requests last ~30ms. The CloudWatch event is making no difference...
Let's suppose another long period without calling the gateway. If I go to the Lambda console and invoke it directly (test button) it answers right away (less than 1ms) with a 404 (that's normal because my lambda expects GET /myresource or POST /myresource).
Immediately after this lambda console execution I call GET /myresource from API Gateway and it still takes ~20 seconds. That is to say, the function was still cold despite having being invoked from the Lambda console. This might explain why the CloudWatch event doesn't work since it calls the lambda without setting the method/resource-url.
So, how can I make this particular case with API Gateway with proxy integration + Lambda stay warm to prevent those slow first request?
As of now (2019-02-27) [1], A periodic CloudWatch event rule does not deterministically solve the cold start issue. But a periodic CloudWatch event rule will reduce the probability of cold starts.
The reason is it's upto the Lambda server to decide whether to use a new Lambda container instead of an existing container to process an incoming request. Some of the related details regarding how Lambda containers are reused is explained in [1]
In order to reduce the cold start time (not to reduce the number cold starts), can you try followings? 1. increasing the memory allocated to the function, 2. reduce the deployment package size (eg- remove unnecessary dependencies), and 3. use a language like NodeJS, Python instead of Java, .Net
[1]According to reinvent session, (39:50 at https://www.youtube.com/watch?v=QdzV04T_kec), the Lambda team expects to improve the VPC cold start latency in Lambda.
[2] https://aws.amazon.com/blogs/compute/container-reuse-in-lambda/
Denis is quite right about the non deterministic lambda behaviour regarding the number of containers hit by CloudWatch events. I'll follow his advice to improve the startup time.
On the other hand I have managed to make my CloudWatch events hit the lambda function properly, reducing (in many cases) the number of cold starts.
I just had to add an additional controller mapped to "/" with a hardcoded response:
#Controller("/")
class WarmUpController {
private val logger = LoggerFactory.getLogger(javaClass)
#Get
fun warmUp(): String {
logger.info("Warming up")
return """{"message" : "warming up"}"""
}
}
With this in place the default (/) invocation from CloudWatch does keep the container warm most of the time.