I’ve written a couple of articles about AWS Lambda
- I showed how to use Hibernate in AWS Lambdas over on Baeldung
- I also showed a full alternative to Spring for an enterprise-grade set up
- Then I’ve discussed how the size of Log4j can make a Lambda start up more slowly
- I’ve even complained about Oracle making a huge Java library for MySQL
It’s probably fair to say that if you want a fast Lambda start up then you need:
- A small package
- A fast startup of the runtime, for which Java benefits from a tweak
However, there are three competing directions we may be facing with our code:
- Response time
- Ease of implementation
If your Lambda is behind an API Gateway/REST interface, then the response time, for which the cold start may be a common event, is the most important thing, and we need to trim everything down to the minimum. We may even sacrifice average processing speed in favour of a generally fast response time.
Throughput may be a concern for Lambdas that process asynchronous requests, especially many thousands of them. Even a nightly job that runs for 10 minutes might benefit from the fastest possible configuration to keep the job at 10 minutes, rather than risk it hitting a timeout at 15minutes or whatever.
We may be optimising throughput for cost, or, for actual throughput!
High throughput may require the leanest libraries, or may benefit from some of the features of a more bloated set of libraries that may come with some relevant optimisations which pay off over non-trivial execution times.
Ease of Implementation
Ease of implementation falls into two categories:
- Can we easily and write the code without too much effort
- Does the code for our Lambda sit well with the rest of our code
Having to build patterns from scratch to assemble our components is less fun than using Guice or Spring, if it’s non-trivial.
Having to use raw JDBC or even JDBI may be easy, or it may give us hassle if we’re importing a project from a previous Hibernate version, or trying to share entity objects with a JPA project.
As always, this dimension can take us into the “it depends” category of implementation.
A Recent Challenge
I’ve recently written the first of a few serverless
cron jobs to sit alongside a Spring server. There are a few reasons not to run it inside the Spring server itself:
- there are multiple nodes, so we’d have also to add a job manager to stop the nodes all doing the cron jobs
- we don’t want to share server resources that should be serving customer traffic with background jobs
The server uses Spring and Spring Data JPA. I don’t want to reinvent any of the DAOs or relevant services for the cron jobs.
Can Spring Cloud Function Help?
Short answer: yes.
I made the data model and DAO layer common to the Spring Cloud Function module and the Spring Boot Server module. Spring Cloud Function allows us to create a bean for each function and then hook up those beans, via the common
main to the
template.yml, which shares the final jar for all functions, but has a separate function definition for each job.
How does it compare?
Essentially, this is all about the ease of coding and virtually nothing to do with runtime efficiency.
Spring Cloud function promises to abstract a function from any specific cloud provider’s serverless framework. The cost of doing this is an enormous package, and it’s a crazy idea for most AWS Lambdas you might choose to write to do general things. Especially crazy if you want a fast cold start.
However, for the use case above, it’s a good way to create a common data layer that can be shared by the two faces of the application.
Spring Cloud Function is bloatware, but it allows you to do anything you might want to do in a Spring Boot application. I had to use the
SimpleDriverDataSource rather than use a connection pool to ensure the application wasn’t holding connections open between invocations.
There are ways to make Spring Cloud Function start quicker by using functional programming rather than component scans and reflection to boot up… but this is a bit like saying that a private jet can be more environmentally friendly if they serve bottled water in recyclable bottles… it’s still very extravagant.
Would I Use Spring Cloud Function Again?
If I ever have another nut that needs a sledgehammer to crack it, certainly!
In seriousness, if we’re in the ease of coding dimension, then it’s a good solution. For asynchronous lambdas in a hybrid project, this is the bridge that allows Spring Boot to be available in a Lambda in a way that works…
… but it’s not a great idea for the majority of situations.