New for AWS Lambda: Use Any Programming Language and Share Common Components
aws.amazon.com
aws.amazon.com
We are making these open source runtimes available soon:
C++[1]
Rust[2]
We are also working with our partners to provide more open source runtimes:
Erlang (Alert Logic)
Elixir (Alert Logic)
Cobol (Blu Age)
N|Solid (NodeSource)
PHP (Stackery)
There is also native Ruby support as well[3]1. https://aws.amazon.com/blogs/compute/introducing-the-c-lambd...
2. https://aws.amazon.com/blogs/opensource/rust-runtime-for-aws...
3. https://aws.amazon.com/blogs/compute/announcing-ruby-support...
With the native ruby support[3], I wonder how hard it would be to implement a Lambda ActiveJob handler..
Honest question: I don’t Ruby, I just looked up what it is.
Boom, no need for Active Job.
Welcome to Serverless.
There’s going to be a lot of people trying to do things the “rails way” on serverless and it’s going to be a little confusing for a while. Many will write it off, some will creat innovative new gems. And of course the Ruby community will come up with the best abstraction for SAM templates and deployment, because we like nice tools.
SQS -> Multiple lambda instances
Unless you set the concurrency to one. But as always when working with any queue, don’t depend on only once processing or in order processing.
AWS does have FIFO queues but they don’t work with lambda directly.
But, I prefer to use SNS for producers and SQS for consumers and assign the SQS queue to a topic. With SNS+SQS you get a lot more flexibility.
2. You can have one SNS message go to different targets. There may be more than one consumer interested in an event.
3. “Priority” processing. I can have the same lambda function subscribed to both an SQS queue and an SNS topic. We do some things in batch where the message will go to SNS -> SQS -> lambda. But with messages with a priority of “high” they will go directly from SNS -> Lambda but they will also go through the queue. High priority messages are one off triggered by a user action.
It's also a useful pattern to, instead of configuring the SQS event itself as your Lambda trigger, have a scheduled trigger and then perform health checks on your service dependencies before pulling messages from the queue. This technique saves you wasted retries and even gives you more fine-grained control over deleting messages (the SQS mechanism for saying, "this is done and you don't need to retry it after the timeout). The SQS trigger, in contrast, deletes the entire batch of messages if the Lambda exits cleanly and does not delete any of them if the Lambda does not exit cleanly, which is a bit messy.
Also, you can have an SQS queue subscribe to multiple SNS topics, which means you can set up separate SNS topics for backfill or other use cases. This is especially useful in cross-account use cases, where often your online events are coming from an SNS from a different account, but you want to be able to inject your own testing and backfill events.
It’s better to retry a finite number of times and stash any messages that fail to process offline for further investigation. If there is an issue that can be resolved, it’s possible to feed deadletter messages back in for processing once the issue is addressed.
Feeding your deadletter events back into your normal processing flow not only hides these issues but forces you to pay real money to fail to process them in an infinite loop that is hard if not impossible to diagnose and detect.
I also log to Cloudwatch though and keep those logs for maybe a week.
https://aws.amazon.com/step-functions/
Basically you define your steps with an input to each step (all of the below is psuedocode of course$ :
Step 1: {“Event”:”step a”}
Step 1: {“Event”:”step b”}
Step 1: {“Event”:”step c”}
And define the handler in your lambda:
Switch event:
Case “step a”
DoA()
Case “step b”
DoB()
Case “step c”
DoC()
I’ve had a lambda run for two hours doing this.Let’s see all the reasons not to use a VM.
1. If this job is run based on when a file comes in, instead of a simple S3 event -> lambda, then you have to do S3 Event -> SNS -> SQS and then poll the queue.
2. Again if you are running a job based on when a file comes in, what do you do if you have 10 files coming in at the same time and you want to run them simultaneously? Do you have ten processes running and polling the queue? What if there is a spike of 100 files coming in, do you have 100 processes running just in case? With the lambda approach you get autoscaling. True you can set up two Cloudwatch alarms - one to trigger when the number of items in the queue is X and to scale down when the number of items in the queue is below Y, then set up an autoscaling group and launch configuration. Of course since we are automating our deployments that means we also have to set up a CloudFormation template with a user data section to tell the VM what to download and the description of the alarms, scale in, scale out rules, the autoscaling group, the launch configuration, the definition of the EC2, etc.
Alternatively, you can vastly over provision that one VM to handle spikes.
The template for the lambda and the state machine will be a lot simpler.
And after all of that work, we still don’t have the fine grained control of the autoscaling with the EC2 instance and cron job that we would have with the lambda and state machine.
3. Now if we do have a VM and just one cron job, not only do we have a VM running and costing us money waiting on a file to come in, we also have a single point of failure. Yes we can alleviate that by having an autoscaling group with one instance and set up a health check that automatically kills the instance if it is unhealthy and bring up another one and set the group up to span multiple AZs.
Re reliablity, I have VMs on AWS with multiple years of uptime - it's the base building block of the entire system, so it's expected to work all the time. You monitor those systems with any sort of nagios-type tool and alert into something like pager duty for when things do go wrong, but they mostly don't. Redundancy I build in at the VM layer.
Additional services on AWS however have their own guarantees and SLAs and they're more often down than the low-level virtual machines are - so it's an inherently less reliable way to build systems imo, but to each their own.
Also, this notion that you can conveniently split your processing up into 15m chunks is just crazy -- you may never know how long some batch job is going to take any given day if it's long running. They're typically leaning on some other systems outside your control that may have differing availability over time. I met a guy who built some scraper on lambda that did something convoluted and he was happy to make like 100k updates in the db overnight -- I built a similar thing using a single core python job running on a VM that did 40MM updates in the same amount of time. It's just silly what people think simple systems are not capable of.
So now I am going to manage my own queueing system, object storage system, messaging system, Load Balancer, etc? My time is valuable.
and at scale, all these extra services on AWS cost more than their OSS equivalent running on VMs. Take a look at ELB for example, there's a per-request charge that yes is very small, but at 10k req/s it's significant - not to mention the extra bytes processed charges. Nginx/haproxy with DNS load balancing can do pretty much what ELB is offering.
ELB automatically scales with load. Do you plan to overprovision to handle peak load? My manager would laugh at me if I were more concerned with saving a few dollars than having the cross availability zone, fault tolerant, AWS managed ELB.
In the very small none of this matters, but you can just run smaller/bigger VMs as needed; prices starting at the cost of a hamburger per month.
Again, we have processes that don’t have to process that many messages during a lull but can quickly scale up 20x. Do we provision our VMs so they can handle a peak load?
Re reliablity, I have VMs on AWS with multiple years of uptime - it's the base building block of the entire system, so it's expected to work all the time. You monitor those systems with any sort of nagios-type tool and alert into something like pager duty for when things do go wrong, but they mostly don't.
Why would I want to be alerted when things go wrong and be awaken in the middle of the night? I wouldn’t even take a job where management was so cheap that they wouldn’t spend money on fault tolerance and scalability and instead expected me to do wake up in the middle of the night.
The lambda runtime doesn’t “go down”. Between Route53 health checks, ELB health checks, EC2 health checks, and autoscaling, things would really have to hit the fan for something to go down after a successful deployment.
Even if we had a slow resource leak, health checks would just kill the instance and bring up a new one. The alert I would get is not something I would have to wake up in the middle of the night for, it would be something we could take our time looking at the next day or even detach an instance from the autoscaling group to investigate it.
Redundancy I build in at the VM layer. Additional services on AWS however have their own guarantees and SLAs and they're more often down than the low-level virtual machines are - so it's an inherently less reliable way to build systems imo, but to each their own.
When have you ever heard that the lambda runtime is down (I’m completely making up that term - ie the thing that runs lambdas).
Also, this notion that you can conveniently split your processing up into 15m chunks is just crazy -- you may never know how long some batch job is going to take any given day if it's long running.
If one query is taking up more than 15 minutes, it’s probably locking tables and we need to optimize the ETL process....
And you still didn’t answer the other question. How do you handle scaling? What if your workload goes up 10x-100x?
I met a guy who built some scraper on lambda that did something convoluted and he was happy to make like 100k updates in the db overnight -- I built a similar thing using a single core python job running on a VM that did 40MM updates in the same amount of time. It's just silly what people think simple systems are not capable of.
Then he was doing it wrong. What do you think a lambda is? It’s just a preconfigured VM. There is nothing magic you did by running on Linux EC2 instance that you also couldn’t have optimized running a lambda - which is just a Linux VM with preinstalled components.
Yes costs do scale as you grow and they may scale linear but the cost should scale at lower slope than your revenues. But then again, I don’t work for a low margin B2C company. B2B companies have much greater margins to work with and the cost savings of not having to manage infrastructure is well worth it.
If I get called once after I get off work about something going down, it’s automatically my top priority to find the single point of failure and get rid of it.
Another example is SFTP. Amazon just announced a managed SFTP server. We all know that we could kludge something together much cheaper than what Amazon is offering. But my manager jumped at the chance to get rid of our home grown solution that we wouldn’t have to manage ourselves.
[1] https://en.wikipedia.org/wiki/Service_Component_Architecture
Seeing this takes away one of my biggest comparative advantages, but I'm happy to see that at least I was not wrong in thinking this feature would be important for developers.
CGI still has the advantage of being an open standard, locally testable, and not vendor specific.
1. Lambda Layers - Reusable components that can be shared across lambda functions (covered in the linked article)
2. AWS (Serverless) Toolkits for PyCharm, IntelliJ & VS Code - https://aws.amazon.com/blogs/aws/new-aws-toolkits-for-pychar...
3. Nested Applications Using the AWS Serverless Application Repository - https://aws.amazon.com/about-aws/whats-new/2018/11/sam-suppo...
It relaxes constraints that have historically restricted the shape of viable languages. With massively-parallel deterministic compilation (like Stanford's gg - which just got simpler to implement). Parallel distributed incremental shared type checking, like Facebook's Hack. Language-community-wide sharing of compilation artifacts (sort-of like build images, or typescript's type definition repos, or Coq's proof repo).
"That would be a nice language feature, but we don't know how to compile it efficiently, so you can't have it" has been a crippling refrain for decades. "[D]on't know how to either parallelize or centrally cache it" is a much lower bar. At least for open source.
This involves not just compiler tech in isolation, but also community organization for fine-grain code sharing. Any suggestions on things to look at?
https://www.serverless-ruby.org/
We've been waiting! I thought this would never happen. Eating major crow today, as I've assumed for a long time that AWS's lack of Ruby support in Lambda was an intentional omission and sign that they are not our friends.
I will change my tone starting today!
(edit: Or Google Cloud Functions, or probably some other major ones I've missed...)
It's pretty comprehensive. And it was able to cache the execution context (and keep the cache warm) to approach native execution times. All of this obviously before native Ruby support was announced.
Not the first time I heard of it. But actively trying to kill it is a whole different level.
10 minutes before the announcement that OP is about here, one of our architects copied this line from an AWS slide deck:
> AWS Lambda supports code written in Node.js (JavaScript), Python, Java (Java 8 compatible), and C# (.NET Core) and Go.
... and intimated that, if your language is not on this list, you're not part of the dominant side of the industry.
As if to say, to the large cohort of Ruby developers we have on staff, "You guys are basically irrelevant because Amazon doesn't care if you can work on the pride and joy of their platform or not."
Every other week I've got a different person telling me that Ruby is a quirky niche language and I should get with the times and become a full-stack JavaScript developer instead.
I get it, there's growth in other languages, but if I have years of experience that means I should throw it away?
Sometimes these conversations get really personal, too. Almost like we're choosing a football team, you'd think it was politics or religion that we're debating...
I've learned a lot since I started writing Ruby at my first permanent job in 2010, and I'm 100% sure that if I looked at any of the early Ruby code I wrote in 2010, I'd grumble and groan at it just as hard as if you showed me some PHP code that I wrote at my first co-op job as a sophomore in college.
You can write great code in any language. You can also write a shanty-town or big ball of mud, in practically any language. I think it's unfair to say that PHP in and of itself represents a "bad code smell." But I'm also fairly sure from anecdotal evidence that I'm in the minority.
I understand completely now. Thanks for that.
serverless-haskell also takes care of packaging shared objects depended upon alongside the binary. You will have to package any binary dependencies of your Haskell code yourself.
The way it works is by generating a Node script which invokes the compiled binary with the payload as an environment variable, although this is encapsulated by an interface which you implement in the Haskell code.
One thing to make sure is that your libraries and Haskell code are compiled on a system compatible with the Lambda execution environment. Documentation going further into ELF compatibility is available, but I can’t remember where. I remember using stack to have my Haskell code compile on an Ubuntu docker image which was compatible.
We use both Lambda for data processing on incoming IoT events, and also for API interactions with our user, along with services to send mails and SMS, etc.
---
I would just want to use the robustness and correctness that I'm able to ensure with Haskell, compare to TypeScript, and especially bundling quirks with Webpack and NPM.
An example of an easy thing to let through is missing an _await_ on a call (might be for logging or something else), which means it'll go out-of-band, and can then easily not be run during the execution, if you have disabled waiting for the event loop to be done (which is necessary in many cases for global setup optimizations).
The call might then finish when the lambda function is thawed, but it might also never run, because the function gets collected.
Now, admittedly, this is not a big issue in any way, but it's the death by a thousand papercuts that I'd like to avoid.
We have so many Lambdas that share common Java JAR libs.
Lambda Layers appears to solve our reuse and deployment headaches.
* We had to hack around Lambda zip size limits. Now we can deploy fat dependencies to Layers and ditch the hacks.
* We can drastically speed up build and packaging time locally by keeping fat dependencies in Layers.
* We use a shared in-house library to wrap all code that lives in a Lambda. Updating the version of this required us to deploy every single Lambda that used it. Now it can live in one place.
* We can eliminate repeated deployment pain for Python code with C dependencies by deploying the manylinux wheel to Layers. Now devs can go back to just packaging up pure Python and not worry about cross-platform problems.
And probably loads more I'm not thinking of.
> The overall, uncompressed size of function and layers is subject to the usual unzipped deployment package size limit.
https://aws.amazon.com/blogs/aws/new-for-aws-lambda-use-any-...
I came to this thread specifically to find out about numpy and pandas on lambda.
A similar method is described here: https://serverlesscode.com/post/deploy-scikitlearn-on-lamba/
Layers should make this entire process easier.
package: exclude: - venv/
would reduce the size considerably (to 50 MB in my case)
In the end, we came to the conclusion that Amazon is smart and won’t let you hack together the equivalent of a cheaper EC2.
On the other hand, their incentive to solve the problem is relatively weak vs an on-premise alternative.
Life on a lambda is too short to pay 6-8 second startup penalty over and over millions of time.
[1]: https://github.com/libmir/mir-algorithm [2]: https://mratsim.github.io/Arraymancer/
Often it is a sign that the problem is not "big" enough (eg: not crunching truly large data sets) OR data science team gets disproportionate amount of goodwill (thus money) to spend on its foibles. :)
Of course an official method is nice here.
TBH, I'm very happy to see native support, but it was already super, super easy to use Rust on lambdas without a shim layer.
That said I I hope they increase the limit to at least 500 Mb sooner than next reInvent.
"Prepared statements only last for the duration of the current database session. When the session ends, the prepared statement is forgotten, so it must be recreated before being used again. This also means that a single prepared statement cannot be used by multiple simultaneous database clients..."[1]
I have used C++ in Lambda before, it is quite cumbersome and it still has the performance hit of using Node.JS.
Check out some of the examples in the GitHub repository.
There are only example CMake calls to find_library, that will or will not find this library based on things that are not documented.
AWS Lambda still uses Amazon Linux AMI as the base for running all code. MySQL C++ connector library is not available to be easily installed by yum for this particular OS.
In particular, the library is distributed as an RPM, from Oracle website, which requires you to be logged in to download it, and then manually installed.
Also, an appropriate CMake find script has to be available to CMake.
Therefore, this is still a valid question, and AWS support needs to clarify.
For the previous Lambda version, I had to add the mysqlcppconn.so file to the uploaded zip and use something like this to ensure the executable runs:
"/lib64/ld-linux-x86-64.so.2 --library-path "+process.cwd() +"/node_modules/.bin/lib "+process.cwd() +"/node_modules/.bin/helloworld "
I have O365 scripts i need to run, but i only see support for PS6+
I hope this runtime API is a simplification of the go rpc api
The lambda team is now letting you write that runtime, and presumably providing more documentation on the responsibilities of the runtime.
Check out the example C++ and Rust runtimes to understand why each language needed to have it's own custom runtime.
The way Lambda manages to achieve the performance it does is because it bootstraps the application and then runs each new request through the loaded application.
This means Lambda needs some way to communicate with an already running service.
Initially, Lambda had language specific runtimes that took care of this (i.e. with Node they have their own bootstrapper that loads your top-level JS file and then calls the defined method each time it receives a new event).
With the release of the Go runtime, they built a framework that gets compiled into your service that runs a simplified HTTP server that Lambda then submits events to.
This latest generalised version eschews an embedded HTTP server for letting your app do something like a long-poll to a local event RPC source in the Lambda container. Basically, your app boots and attempts to pull a job off the queue, if there's a job, your Lambda runs, if there isn't, your Lambda service gets paused until there's something to send it.
We've tried this and it helps somewhat but when AWS attempts to scale your function based on load, cold starts re-appear. We've moved away from Lambdas where a dependable response time is required.
If you are experiencing cold starts it means that function is not used very often. If it's not used very often that likely means it's not user facing (or something less important like a Terms of Service page). If that's the case, why do you need instant response times?
With delays as bad as 8+ seconds for ENI attachment, this is a significant holdback (https://medium.freecodecamp.org/lambda-vpc-cold-starts-a-lat...)
AWS is making continual improvements in this area.
Thankfully, in my case, I have a very steady flow of data so I don't expect too many cold starts.
One thing though, does your lambdas need both public and private access? Else you can place them in a subnet for private only, since the slow part is the ENI for the Nat Gateway.
[1] https://twitter.com/jeremy_daly/status/1068272580556087296
So, 10+ seconds cold start, and 200 + 200-300ms (around 500-600ms avg) calls to the Lambda function. Complete garbage for our application at least (I imagine using it for background processing might not be an issue with latency).
Switched over to EC2, less than 200ms response total, no cold starts.
You can basically replace all HTTP-API Lambdas with it, because it allows direct access to DynamoDB.
Guess you're stuck with Aurora Serverless or DynamoDB.
MySQL tends to have very low connection times, which helps a lot in this area also.
So I will go with AWS Lambda. But seems like having lot of dependency increases the lag, wonder if there's a way to put the source on a diet.
The VTL resolvers don't have the cold-start problem, AFAIK.
These issues that Azure has already solved, make me wonder how much longer i will stay with AWS.
Source: just implemented cross acct lambda -> RDS connection using VPC
1. https://aws.amazon.com/about-aws/whats-new/2018/08/aws-farga...
Create a simple ping/pong HTTP service in both and you'll quickly see difference in everything from billing to startup time.
If you're gonna use containers, use containers. If you want someone else to manage the container for you, use Lambda.
On the other you're saying "you can make fargate spin up a container for an event, but it would be too slow for any useful event driven computing", which is the truth, but it contradicts your initial comment.
If you're gonna use containers, use containers. If you want someone else to manage the container for you, use Lambda.
That’s the only major difference I can see, though. The rest is convention/standardization on what’s put into the image (an executable that speaks HTTP over its stdio; separately-namespaced projects under /opt rather than use of the global namespace; etc.)
(Disclaimer: I work for AWS, but this is strictly my personal opinion/observation.)
Per-event invocation of a docker container instead of a specific bundle of code seems much more flexible, especially with the Firecracker tech they announced.