I am accessing auroradb service from my java lambda code. Here I set my lambda concurrency as 1.
Since creating/closing database connection is an expensive process, I have created the mysql connection and made it static. So it will reuse the same connection every time. I haven't added the code to close the connection.
Will it cause any problems?
Will it automatically close after some days?
Most certainly yes! When your lambda "cools" down, your connection to the database will be broken. The next time you invoke your lambda, it goes through a cold start, and your lambda code should initialize the connection again. This is a standard issue with working with persisted connections from serverless infrastructure.
What you need to use is something like a REST API for your data apis, and that's something Aurora Serverless supports as beta.
https://aws.amazon.com/about-aws/whats-new/2018/11/aurora-serverless-data-api-beta/
Each request is a independent HTTP request, and you don't end up managing you persisted connections.
Related
The Postgres query builder my Lambda functions use, Knex, uses prepared statements so I'm unable to fully take advantage of RDS Proxy since the sessions are pinned. I try to ensure that the lambdas run for as little time as possible so that the pinned session completes as quickly as possible and its connection is returned to the pool.
I was wondering how I might be able to make the sessions shorter and more granular and thinking about creating and closing a connection to AWS RDS Proxy with each query.
What performance considerations should I be considering to determine the viability of this approach?
Things I'm thinking of:
RDS Proxy connection overhead (latency and memory)
The time that RDS Proxy takes to return a closed connection back to the pool and make it reusable by others (haven't been able to find documentation on this)
Overhead of Knex's local connection pool
Using RDS proxy when building applications with Lambda functions is a recommended infrastructure pattern by AWS. Relational Databases are not built to handle tons of connections, while Lambdas can scale to thousands of instances.
RDS Proxy connection overhead (latency and memory)
This would definitely increase your latency, but you will see a great improvement in the CPU and memory usage of your database, which would ultimately prevent unnecessary failures. It's a good trade-off when you can do a lot of other optimizations on the lambda side.
The time that RDS Proxy takes to return a closed connection back to the pool and make it reusable by others (haven't been able to find documentation on this)
While working with Lambdas, you should drop the connection to your RDS proxy, as soon as you finish processing your logic without worrying about the time the RDS proxy would take to return the closed connection back. Once the connection is dropped, the RDS proxy keeps it warm in the pool of connections it maintains for a certain duration of time. If another lambda tries to make a connection meanwhile, it can share the same connection which is still warm in the pool. Dropping the database connection at the right time from your lambda would save you lambda processing time -> money.
Overhead of Knex's local connection pool
I would suggest not using Knex local connection pool with lambda as it won't do any good (Keep the pool max to 1). Every lambda execution is independent of another, the pool will never be shared and the connection doesn't persist after the execution completes unless you plan to use it with a serverless-offline kind of local framework for development purposes.
Read More about AWS Lambda + RDS Proxy usage: https://aws.amazon.com/blogs/compute/using-amazon-rds-proxy-with-aws-lambda/
AWS Documentation on where to use RDS Proxy: https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/rds-proxy-planning.html
I'm using a service that runs outside of my premises that uses a websocket API to emit events that occur inside it. Let's call this wss://X.
I have a web app that currently runs a websocket client that connects to wss://X and if it receives an event fires a call back that does some book keeping (update a database, queue a notification).
I'd like to keep this separate from my web app (different developer, separate logic etc.). I'd like to have something I'm called a listener for wss://X which will just sleep till something comes up on this connection and if so, do something and then shut down.
This seems like a good candidate for AWS lambda. Short running functions that do book keeping based on events but I'm not sure how I can trigger them. Someone suggested AWS API gateway but I don't know how to make it listen (rather than bind) to a certain URL and then trigger lambda functions based on events that it receives. If this is not possible, what can I use on AWS that would solve this problem for me?
You can't use Lambda for long-running tasks (refer to Is it possible to subscribe to a WebSocket in a serverless fashion using AWS?).
Considering that the listener needs to be long-running as it must listen to events from wss://X, an alternative that I can think of is to start an EC2 instance that runs code which continuously listens to wss://X and does the operations that you want.
Currently, I have a working modded Minecraft server working running on a C5 EC2 instance. The problem is that I have to manually start and stop the server which can be annoying for my friends. I was wondering if it would be possible to automate the EC2 state so that it runs as soon as a player attempts to join the sever. This would be similar to how Minecraft realms behaves which I heard Mojang was using AWS for:
https://aws.amazon.com/blogs/aws/hosting-minecraft-realms-on-aws/
I have looked up tutorials for this and this is the best I could come across:
https://github.com/trevor-laher/OnDemandMinecraft
The problem with this solution is that it requires to make a separate website to log users in and start the EC2 instance while I want the startup and shutdown to be completely automatic.
I would appreciate any guidance.
If the server is off, it would not be possible to "connect" to the server. Therefore, another mechanism is required that can be used to start the server.
Combine that with your desire to minimise costs and the only real solution is to somehow trigger an AWS Lambda function, which could start the server.
There are a few ways you could have users trigger the AWS Lambda function:
Make a call to API Gateway
Upload an object to Amazon S3
Somehow put a message in an SNS topic or an SQS queue
Trigger an Amazon CloudWatch Alarm (which calls Lambda via SNS)
...and probably other ways
When considering a method to use, you should consider security implications such as:
Whether only authorized users should be able to trigger the Lambda function, or is it okay that anybody (eg a web crawler) might trigger it.
Whether you willing to give your friends AWS credentials (not a good idea) that they could use to start the server directly, or whether it should be an indirect method.
Frankly, I would recommend the following architecture:
Create an AWS Lambda function that turns on the server
Create an API Gateway that triggers the Lambda function
Give a URL to your friends that calls the API Gateway and passes a 'secret' (effectively a password)
The API Gateway will call the Lambda function, passing the secret
The Lambda function confirms that the secret is correct and starts the Amazon EC2 instance with Minecraft installed
Here is a tutorial that shows many of these concepts: Build an API Gateway API with Lambda Integration
The purpose of the secret is to avoid the server from starting if an unauthorized person (or a bot) happens to hit the API Gateway endpoint. They will not provide the secret, so the server will not be started.
Stopping the server after a period of non-use is a different matter. The library you referenced might be able to assist with finding a way to do this. You could have a script running on the Minecraft server that monitors the game and, after a period of inactivity, simply calls the operating system to perform a Shutdown.
You could use a BungeeCord hub server that then allows user to begin a connection to the main server and spin it up via. AWS.
This would require the bungee server to be always up however, but the cost of hosting a small bungee server should be relatively cheap.
I don't think there's any way you could do this without having a small server that receives the initial request to spin up the AWS machine.
I’m trying to build an application on aws that is 100% serverless (minus the database for now) and what I’m running into is that the database is the bottleneck. My application can scale very well but my database has a finite number of connections it can accommodate and at some point, my lambdas will run into that limit. I can do connection pooling outside of the handler in my lambdas so that there is a database connection per lambda container instead of per invocation and while that does increase the number of concurrent invocations before I hit my connection limit, the limit still exists.
I have two questions.
1. Does serverless aurora solve this by autoscaling to increase the number of instances to meet the need for more connections.
2. Are there any other solutions to this problem?
Also, from other developers interested in serverless, am I trying to do something that’s not worth doing? I love how easy deployment is with serverless framework but is it better just to work with Microservices in something like Kubernetes instead?
I believe there are two potential solutions to that problem:
The first and the simplest option is to take advantage of "lambda hot state", it's the concept when Lambda reuses the execution context for subsequent invocations. As per AWS suggestion
Any declarations in your Lambda function code (outside the handler code, see Programming Model) remains initialized, providing additional optimization when the function is invoked again. For example, if your Lambda function establishes a database connection, instead of reestablishing the connection, the original connection is used in subsequent invocations. We suggest adding logic in your code to check if a connection exists before creating one.
Basically, while the lambda function is the hot stage it "might/should" reuse opened connection(s).
The limitations of the following:
you only reuse connection for single lambda type, so if you have 5 lambda functions invoked all the time you still will be using 5 connections
when you have a spike in lambda invocations, including parallel executions this approach becomes less effective since, lambda will be executed in a new execution context for majority of requests
The second option would be to use a connection pool, connection pool is an array of established database connections, so that the connections can be reused when future requests to the database are required.
While the second option provides a more consistent solution it requires much more infrastructure.
you would be required to run a separate instance for the pool, and if you want to do things properly probably at least two instances and a load balancer (unless use containers).
While it might be overwhelming to provision that much additional infrastructure for connection pooler, it still might be a valid option depending on the scale of the project, your existing infrastructure (may be you already using containers) and cost benefits
Best practices by AWS recommends to take advantage of hot start. You can read more about it here: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Streams.Lambda.BestPracticesWithDynamoDB.html
I'm trying to find a good architecture for connecting to the database. It is required that the connection to the database is not repeated in each lambda function. In addition, this way will create many connections for individual lambdas instead of one common. Can I implement the structure as in the figure below, so that one lambda connects to the database, and everyone else uses its connection in its code
Your proposed architecture will not work because unless your Innovation of DB Lambda is too frequent to always keep it warm and that you are storing your connection in /tmp for reusing on subsequent innovations your DB Lambda will create new connections for each invocation. Moreover if your invocations of DB Lambda create multiple containers to serve simultaneous requests then you will anyways have those many connections instead of just one
Ideal solution will be to replace the DB Lambda with a tiny EC2 instance
The DB connection can be cached in your "DB Lambda" when the Lambda stays warm. If the Lambda does not stay warm, then invoking that lambda will suffer the price of a cold lambda, which could be dominated by having to recreate a DB connection, or could be dominated by what other work you do in "DB Lambda".
How frequently you expect your Lambdas to go cold is something to take into consideration. It depends on the statistics of your incoming traffic. Are you willing to suffer the latency of recreating a DB connection once in a while or not, another consideration?
Managing a tiny EC2 instance like someone else said, could be a lot of extra work depending on whether your cloud service is a complex set of backend services, whether that service shuts down during periods of inactivity. Managing EC2 instances is more work that Lambdas.
I do see one potential problem with your architecture. If for whatever reason your "DB Lambda" fails, the calling Lambda won't know. That could be a problem if you need to handle that situation and do cleanup.