Azure Functions Internals

Introduction

 
Azure Function is the centerpiece of the Azure Serverless platform. It is basically a compute which react to timers or HTTP or events from Azure services like Event Hubs. Azure Function allows you to define your code in various programming languages like Python, C#, F#, Java and more. So, Azure Function basically allows you to execute your code based on the events you specify.
 

Azure Functions 1.0 challenges

  • Need for additional language support, e.g. Java, Python, PowerShell
  • Only able to host on Windows
  • No support for development on Mac and Linux
  • Assembly probing and binding issues for .NET developers
  • Performance issues on a range of scenarios/languages
  • Lack of UX guidance to production success

What’s new in Azure Functions 2.0?

  • New Functions quick start by selected programming language
  • Updated runtime built on .NET Core 2.1 (supported .NET Framework on the previous version)
  • Deployment: Run code from a package
  • .Net Function loading changes
  • Tooling Update: Visual Studio, CLI and VS Code
  • Consumption-based SLA

Key differences between Azure Functions 1.0 and 2.0

 
Some of the highlighted differences between both the versions of Azure Functions are highlighted in the picture,
 

Bindings and Integration

 
Previously in Azure Functions 1.0, there were a lot of native bindings available, so the runtime had to be changed in order to make changes to them (Bindings), but in Azure Functions 2.0, the runtime will be developed separately (Version independent) to get more clarity on the extensibility model.
 
 

What is hard with Azure Functions?

  • Manageable Sequencing + Error Handling
  • Fanning-out and Fanning-in
  • External Events Correlation
  • Flexible Automated Long-running Process Monitoring
  • Http-based Async Long-running APIs
  • Human Interaction
Furthermore, Azure Functions Monitoring is also becoming hard when involving complex serverless solutions.
 
However, there are a couple of workarounds to ease out the monitoring case.
 

.NET Assembly probing and binding improvement

  1. Runtime assemblies isolation – This involves leveraging new capabilities introduced in the .NET core to provide better isolation between runtime dependencies and the dependencies which users bring in as part of the function using assembly load context. This makes sure the probing and the binding works as expected followed by automatic unification (implicit binding redirects).
  1. Improved probing/resolution behavior – The enhanced probing behavior brings in the following capabilities for the users,
    • Publish artifacts and deps file
    • Automatic resolution of runtime/platform dependencies and native assets
    • Consistent with .NET core
  1. Improved extensibility consolidating on new load behavior – This solves the conflicts involved while loading the dependencies as a common dynamic assembly load mechanism solves it for all the available extensions.
  1. Out-of-Process .NET language worker (Roadmap) – Not yet made generally available, this model involves the following capabilities,
    • Serialization/Deserialization of triggers and bindings
    • More flexibility around .NET versions
    • Dependency injection

Language Extensibility

 
In the 2.0 model, the worker and the host are broken into two separate processes – host process and language process. The events and the HTTP requests will be received in the host processor through the script host which does the inter-process communication to communicate with the language process as in the below picture,
 
 
Through this model, the development of new language workers can happen independently, and the worker process crashes will not bring down the host.
 

Azure Functions tooling option

 
Azure Functions supports the following set of tools such as,
  • Visual Studio
  • VS Code
  • CLI
  • Portal
  • Deployment options

The problem in the previous deployment options

 
Through FTP, users can put their files on production one at a time, and at that time there might be a chance where the deployment may fail in the middle of using the files. Another common scenario that the customer might face is when they want to deploy their work across multiple regions (Functions App) from a single repository where the deployed region might be running on one version and the receiving region on another version leading to deployment issue. So, the solution for this problem is brought up by a functionality where we can run the code from a zip file and that zip file can be stored in Azure storage externally to your app.
 

Demo - Dependency Injection

 
It is not easy to manage dependencies considering the static nature of Azure function triggers. This might be an issue as Dependency Injection is imperative to unit testing in C#. So, here is a scenario on handling dependency injection in Azure Functions.
 
 
The code in the above picture depicts that the run method is not static but an instance method followed by a constructor with dependency on a service which here is IMyService. An instance id will also be created (_instanceId) whenever the constructor is called. Now, when an instance of the function is created, the local variable (_myService) will be assigned with the instance of IMyService and as for _instanceId, a new Id will be assigned.
 
 
So, IMyService creates a new GUID whenever a type or a class is created or initiated, and the runtime will not recognize this activity.
 
 
The Function startup code above evoked by the runtime provides the ability to inject the services which here is IMyService. Here, a singleton service is registered with the interface as IMyService and MyService as the class. So, if anyone calls for IMyService, the implementation that needs to be returned is MyService.
 
Whenever an HTTP request is made, the _instanceId gets changed upon running the project. But, the Id from MyService will not be changed for each trigger. The Scope of the instance is maintained until the function is restarted or redeployed.
 

Functions Hosting Model

 
 
The above picture shows several types of hosting models. The first block shows the classic Functions Hosting model, initially, the Function contains code and scales when an event occurs. The Functions runs on a VM and that VM runs on the APP services which is based on Windows OS. This model works great for many scenarios. But, there are some scenarios to which the classic model serves better if you implement some changes. The second block shows the classic model with some changes to improve a few scenarios, at the top it still contains the Functions code and it is packaged as a container which runs on Linux. Service Fabric Mesh can be used as an Infrastructure to run it on. The Third model is Functions and Container combinational model, it can be leveraged on having dedicated App Service plan. The Functions can bring with the Containers itself. The fourth model is slightly different from the third one where the Functions with Container runs on the Kubernetes infrastructure. In the fifth model, it runs on open-source hosting. The sixth model contains the IoT infrastructure which is based on the Raspberry Pi and Windows operating system. Finally, On-prem Functions which runs on the Azure Stack based on the Windows operating system.
 

DEMO: Python Sharks

 
 
The above Function gets triggered when an HTTP request is received and it contains Prediction() which predicts the content depicted in the image. Also, it gives the probability of the result on the scale of 0 to 1.
 
There is an Endpoint to this Function and on passing any image URL, the Function predicts the image and returns the TagName, the Probability value of the image depicted.
 

Durable Functions

 
It allows writing long-running orchestrations as a single function while maintaining local state. Also, it simplifies complex transactions and coordination like functions chaining. Further, it makes easy to call a Function from another Function, synchronously or asynchronously.
 

Components of Durable Functions

 
The Starter Function kick-offs the Orchestrator Function which can run for a long time and in a controlled state. It triggers the Activity Function which performs the logic.
 
How does it look like?
 
 
In the orchestrator function, you write your workflow in code. The workflow can consist of code statements calling other functions like activity, or other orchestration function. You can call so-called activity functions from an orchestration function. These activity functions are the basic unit of work in a Durable Function solution.
 

Durable Function: How Durable is it?

 
publicstaticasynctask<List<string>>RunOrchestrator(
{OrchestrationTrigger}DurableOrchestrationContext context)
{
varoutput=newList<string>();
//Replace “hello” with the name of your Durable Activity Function.
outputs.Add(await context.CallActivityAsync<string>(“FunctionIgnite_Hello”, “Orlando”));
await context.CreateTimer(context.Current<DateTime.AddSeconds(20),CancellationToken.None);
outputs.Add(await context.CallActivityAsync<string>(“FunctionIgnite_Hello”, “Miami”));
await context.CreateTimer(context.Current<DateTime.AddSeconds(5),CancellationToken.None);
outputs.Add(await context.CallActivityAsync<string>(“FunctionIgnite_Hello”, “Tampa”));
returnoutputs;
}
 
The above code is the orchestrator function which calls the activity functions one after the other.
 
Test for Durability
 
Initially, start the host using “func host start” command in the console. It will detect the function and provide an endpoint.
 
 
Paste the endpoint in the Postman tool and hit send. You can see the status of the Function in the Postman as “Running”. Now, head back to the console and kill the host. Again, start the host using the same command used above. Hit the function endpoint again and now you can see the function executing successfully. Here, the orchestrator function exactly knows the point where the host got killed and it will continue the process from the point where it was left.
 

Conclusion

 
In this blog post, we investigated the factors differentiating Azure Functions 1.0 and 2.0. Furthermore, it gives a detailed coverage into Azure Functions Bindings and problems involved in the deployment options of the previous Azure Functions version followed by some demos for a better understanding of the audience.
 
Refer here to access some cool resources!