It is generally recommended to use ConfigureAwait(false) when awaiting async calls when context is not required. Just wondering is there any benefit of using ConfigureAwait(false) in Azure Functions.
Do Azure Function threads have non-null SynchronizationContext as such it would make beneficial to use ConfigureAwait(false) to avoid unnecessarily capturing it and rescheduling the await continuation back on the captured SynchronizationContext?
It is a bit of a churn to add ConfigureAwait(false) at the end of every async call so prefer to avoid it for the code that runs in Azure Functions if there is no perf/or any other related gain.
Looking at the azure function host code:
https://github.com/Azure/azure-functions-host/blob/918b057707acfb842659c9dad3cef0193fae1330/src/WebJobs.Script.WebHost/WebScriptHostManager.cs#L181
it seems like azure function host attempts to strip out the ASP.NET SynchronizationContext before calling the azure function.
Just wondering is there any benefit of using ConfigureAwait(false) in Azure Functions.
Not if your code knows it is running in that context, no.
In my Azure Functions code, I divide it up into "library-ish" code in separate library projects, and the "Azure Functions" code. I do use ConfigureAwait(false) in the library projects, since they can (in theory, at least) be reused in other applications.
But for code that knows it is running in Azure Functions, no ConfigureAwait(false) is necessary. The v1 host would strip out the SynchronizationContext, and the v2 host runs on ASP.NET Core which doesn't have a context to begin with.
Related
We are considering migrating a medium-sized F# ASP.NET WebAPI application running on .NET 6 from sync to async route-by-route. That is, convert one route at a time to async-all-the-way. Are there any pitfalls to this approach?
Embedded in this question, I would like some insight into how threads are managed for async vs. non-async routes. If we were to have sync and async routes living side-by-side in the same ASP.NET process, would they share the same ASP.NET managed thread pool, or would they each have separate thread pools? I am curious if during the transition we would actually end up with greater total number of threads in use.
And to be perfectly clear, I am asking about implementing "traditional" F# async computation expressions specifically, not the new task computation expressions (though any additional insights there would be welcome too).
I didn't find any posts related to this topic. It seems natural to use Lambda as a getstream backend, but I'm not sure if it heavily depends on persistent connections or other architectural choices that would rule it out. Is it a sensible approach? Has anyone made it work? Any advice?
While you can build an entire website only in Lambda, you have to consider the followings:
Lambda behind API Gateway has a timeout limit of 30 seconds and a Payload size limit (both received and sended) of 6MB. While for most of the cases this is fine, if you have some really big operations or you need to send some really big datas (like a high resolution image), you can't do it with this approach, but you need to think about something else (for instance you can send an SNS to another Lambda function with higher timeout that can do all this asynchronously and then send the result to the client when it's done, supposing the client is capable of receiving events)
Lambda has cold starts, which in terms slow down your APIs when a client calls them for the first time in a while. The cold start time depends on the language you are doing your Lambdas, so you might consider this too. If you are using C# or Java for your Lambdas, than this is probably not the best choice. From this point of view, Node.JS and Python seems to be the best choices, with Golang rising. You can find more about it here. And by the way, you can now specify a Provisioned Throughput for your Lambda, which aims to fix the cold start issue, but I haven't used it yet so I can't tell if there is any difference (but I'm sure there is)
If done correctly you'll end up managing hundreds of Lambda functions, while with a standard Docker Container under ECS you'll manage few APIs with multiple endpoints. This point should not be underestimated, as on one side it will make changes easier in the future, since lambda will be small and you'll easily find the bug and fix it, but on the other side you have to move across these functions, which if you don't know exactly which lambda is responsible of what can be a long process
Lambda can't handle sessions as far as I know. Because after some time the Lambda container gets dropped, you can't store any session inside the Lambda itself. You'll always need a structure to store the session so it can be shared across multiple Lambda invocations, such as some records in a DynamoDB table or something else, but this mean that you have to write the code for this, while in a classic API (like a .NET Core one) all of this is handled by the language itself and you only need to store or retrieve items from the session (most of the times)
So... yeah! A backed written entirely in Lambda is possible. The company I work in does it and I must say is a lot better, both in terms of speed and development time. But those benefits comes later, since you need to face all of the reasons I listed above before, and is not as easy as it could seem
Yes, you can use AWS Lambda as backend and integrate with Stream API there.
Building an entire application on Lambda directly is going to be very complex and requires writing lot of boiler plate code just to enforce some basic organization and structure to your project.
My recommendation is use a serverless framework to do this that takes care of keeping your application well organized and to deploy new versions (and environments).
Serverless is a good option for that: https://serverless.com/framework/docs/providers/aws/guide/intro/
While learning the Serverless Framework I came across several tutorials showing how to run an Express instance in a Lambda. This seems to me like an overkill and against the purpose of Lambda functions.
The approach usually involves running an Express instance in the Lambda and proxying API Gateway requests to the Express router for internal handling.
To me the trivial approach is to just create an API in API Gateway and route individual requests to a Lambda for handling. Am I missing something?
Taking into account that Lambdas' execution time is 15 minutes, isn't just spinning up the Express instance quite expensive in terms of memory? Also, limited to 100 concurrent Lambda executions would create a bottleneck, no? Wouldn't an EC2 instance be a better fit in such case? Using a Lambda like this seems like an overkill.
The only two benefits I see in running an Express instance in a Lambda are:
In the case of migration of an existing app written in Express, allows to slowly break down the app into API Gateway endpoints.
Internal handling of routing rather than relying on the API Gateway request/response model (proxying to Express router).
What would be the benefit of such approach, in case I am missing something?
Some resources promoting this approach:
Express.js and AWS Lambda — a serverless love story (Slobodan Stojanović, freeCodeCamp)
awslabs/aws-serverless-express (GitHub)
Deploy a REST API using Serverless, Express and Node.js (Alex DeBrie, Serverless Framework Blog)
Most of your points are valid, and it can indeed be called an antipattern to run Express inside your Lambda functions behind an API Gateway.
Should be noted that the initialization time is not that much of a concern. While the execution time of a single invocation is capped at 15 minutes, a single Lambda instance will serve multiple requests after it has been fired up. A frequently invoked single Lambda instance has usually a lifetime or 6 to 9 hours, and is disposed of at about 30 minutes of inactivity. (note that AWS does not publicly disclose these parameters and these figures should only be used as a ballpark). Whoever is the unlucky one to get the cold start and eat the initialization delay could get an additional delay in the thousands of milliseconds however.
The singular main advantage of this approach is, as you said, providing a migration path for existing Node developers with existing Express knowledge and applications. You should generally not consider this approach when developing an application from scratch and implement idiomatic serverless patterns instead (e.g. utilizing API Gateway routing).
Just to reiterate, the main downsides of this approach:
Higher needless overall code complexity due to forgoing API Gateway functionality (routing etc.)
Higher initialization time resulting in longer cold starts
Larger code footprint due to more dependencies
Larger code footprint due to losing tree shaking / individual packaging due to internal routing
P.S. The main contender these days probably wouldn't be a dedicated EC2 instance, and rather Fargate containers running Express in Node.js. This pattern has many of the same benefits as Serverless while keeping existing development patterns and tools largely intact.
I am considering to use the AWS lambda serverless architecture for my next project. This is my understanding of the technology and I would very much appreciate it if somebody can correct me.
You can deploy function that acts as the event handlers.
The event handlers are configured to respond to any events that are provided
In the case of writing the lambda functions in Javascript, you can require any other Javascript modules you write and use them.
All your lambda and its required modules are written stateless. Your app's states are ultimately kept in the database.
If you ever want to write some stateful logic such as keeping the results from one HTTP request and temporarily store it somewhere and look it up in the subsequent request, is this not possible in Lambda?
About your question, lambdas can use a temporal directory /tmp to storage files. This has a limitation of 500MB. Since the lambda container COULD be reused for performance, there is a chance that the file is still there for the next lambda invocation. This is discouraged but in some particular cases could be helpful. Anyway, if you really need it, the better approach would be to use a cache system.
In addition to your considerations, AWS Lambdas are not good for:
To keep state, like files that are downloaded and could be reused later.
Handle OS
Long running tasks
Hard latency requirements apps.
Depending on the database client, multiple concurrent lambdas can lead to an overhead in the database connections since a client is instantiated for each lambda.
I'm using the DataCache API that is part of the Windows Azure Caching Nuget package and I was wondering why there isn't a way to make non-blocking calls against the constituent methods. Am I missing something? I understand that the latencies on these calls are going to be low but it's still a network call - if you're not using the local cache setting.
Suggestions, thoughts?
Thanks!
If you want to understand why the library is this way then I'd have a read of this article on exposing async wrappers for synchronous methods. TL:DR; There are two distinct reasons for wanting to do async, scalability and responsiveness. You really only need an async version of a method if it will help with the former, the latter you can leave to the consumers of your API because it's easy.
EDIT: It seems people have missed my intent in this answer, so I'll try adding some more clarification.
Yes, the cache client may make a network call and MS are trying to get everyone to make all their network calls in a non-blocking manner so that apps remain responsive. However this is a cache and it is designed to be very fast. If you make a request to the cache and the item is not in local cache (according to Scott Guthrie) the response should take 1ms. Given that the response is so quick (and if you are using local cache it will be even quicker), they would have likely added more overhead by creating tasks to run it in the background than they would have gained.