Hello friends! In this blog I am going to talk about fundamentals of Azure Functions.
Azure Functions is a server less solution that allows you to write less code, maintain less infrastructure, and save on costs. Instead of worrying about deploying and maintaining servers, the cloud infrastructure provides all the up-to-date resources needed to keep your applications running.
Hence, main advantages of Azure Functions are -
- serverless programming
- highly scalable
- low cost
Azure Functions can be look on as Events + Code which means all we have to do is to write code and then tell Azure what trigger will run the code. A trigger can be a scheduler, a message in MessageQueue, a new item in blob storage, a http request etc.
So how do we run code in Azure -
Azure VM
install whatever u want
web servers, windows services etc
IaaS
complete control of the serverless
choose your operating system
You are responsible
patching and maintaining
scaling
operational overhead
Azure app services
PaaS
Azure web applications
easy to deploy
choice of many frameworks
Hosting in a hosting plan
combine multiple sites on one server
scale up to many servers
Web jobs -simple way to keep running background jobs in webapplications
simplified background tasks
the basis for azure functions
Azure functions is based on webjob hosted on web app services
Azure functions are part of App services. It can be seen as a simplified programming tool which helps to
- just write the code to respond to the event
- eliminate the boilerplate
- focus on business requirements
It has consumption based pricing model -
- pay as you go
- only pay for what you use
- automatic scale
Azure functions pricing
run in app service plan
you can use existing pricing models
pay for dedicated servers
predictable monthly costs
serveral prciing tiers
or use the consumption based pricing model
Billing
number of executions
cpu time*Ram
free monthly grant available
Cutting costs
reduces your costs with
faster invocation times
fewer invocations
reduced memory requirements
consumption plan
optional daily quota
limited to five mins per executions
Docker Container
azure function can be run in docker containers
host anywhere
onprem
other cloud providers
Benefits of Azure Functions
- Rapid and simple development
code within azure portal
eliminate boilerplate
- All the powers of azure web apps
ci, kudu, easyauth, certificates, custom domains, settings etc
- Cost effective pricing
pay for what you use
- No servers to maintain
automatic scaling
What is SERVERLESS ARCHITECTURE?
There are still servers of course even in a serverless architecture.
you delegate the management of the server
use PaaS wherever possible
e.g comos db, auth0
run your custom code on azure functions
respond to events
Functions as a service (FaaS)
A real world example
monolithic architecture is hard to scale and tries to do everything
Refractoring to functions
payment provider as azure function which places a message in queue
this triggers generate license message which is azure func which stores license file in blob storage
this triggers license file azure func which sends email to customer
report error web hook azure func which add new row in table storage
validate license api azure func which does a db lookup
nightly scheduled task azure func generated report eachnight
Our web server now has lot less to do
Microservices taken to next level
Function app - group related functions together
e.g. previous examples all funcs can be grouped in single func app
Azure functions use cases
experiments and prototyping
automating development processes
integrate slack with CI server
decomposing or extending monolithic applications
independent scaling
adapters for integrating systems
go serverless
CREATING YOUR FIRST AZURE Function
Demo -
open tryfunctions.com>
scenario - webhook+api, timer, data processing
>langugae - c#, java
>Create function>creates function in AZURE
Function app has a randomly generated name
httptiggerCSharp1 contains run.csx contains code for the function which gets triggered
function.json - defines each func in azure function
viewfiles tab shows code files
test tab provides option to trigger func and check output
logs window show the logs
Get function url - url for the func
Creating functions from templates
lang - JS
plus button helps to add a function
one can select any function template to create function (just like build templates)
functions select many languages like JS, Powerhsell, typescript, C#
TimeTrigger - runs on schedule
Create a function app in azure portal
Create a resource>Function app>name>subscription>resource group>OS>hostingplan=consumptionPlan>location>runtime stack=.NET>Storage=CreateNew>Create
Function app setting -
runtime version
daily usage quota
function app edit mode (read/write or read only)
host keys to call the function
Application Settings
The files of azure functions gets stored in storage account e.g. logs, fucntion.json etc.
All the code for azure functions is opensource
UNDERSTANDING TRIGGER AND BINDINGS
Bindings
connect to external resources
reduce amount of code
check standard documentation
Developing Azure Functions
Visual Studio>Azure development (enables all azure tools)
Azure function core tools
cross platform
command line
.NET SDK shall be installed
azure function core tools
install using npm
open powershell
>func
>func init //creates azure fucntion project in the folder
Select a worker runtime:dotnet
host.json
local.settings.json //startup values
open the project in VS code
Demo - webhook trigger
>func new
Select a template:
HttpTrigger
>FunctionName: OnPaymentReceived
the function created successfully.
.cs files get added successfully
WIthin .cs
[FunctionName("OnPaymentReceived")]//attributes
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get",//signifies this is an HttpTrigger
"post", Route=null)]HttpRequest req,
ILogger log){
string requestBody= await new StreamReader (req.Body).ReadToEndAsync();
dynamie data =JsonConvert.DeserializeObject(requestBody);
return new OkObjectResult($"Thanks for your purchase");
}
func start //starts function in cmd line
default route is
api/functionName?id=123
One can trigger the request the method using Powershell
iwr -Method POST
-Uri http://localhost:7091/api/OnPaymentReceived
-Headers @{"Content-Type"="application/json"}
-Body '{}'
when running locally, function doesnt need the secret code
Compilation of projects will update the bin folder
function.json - details of http trigger
Demo - Queue output binding
we want func to post a message to queue which allows to generate license file async
message sent to azure queue storage (or service bus as well if needed)
nuget pkg to allow storage bindings for sending a message to queue- Microsoft.Azure.WebJobs.Extension.Storage
output binding - to write message to queue
>Add the nuget to project for storage
>add queue binding to func
[FunctionName("OnPaymentReceived")]//attributes
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get",
"post", Route=null)]HttpRequest req,
[Queue("orders", Connection="MyAppSetting")]:IAsyncColletor<Order> orderQueue,
ILogger log){
string requestBody= await new StreamReader (req.Body).ReadToEndAsync();
dynamic order =JsonConvert.DeserializeObject(requestBody);
await orderQueue.AddAsync(order);//connects/creates queues, serialize message and send it
return new OkObjectResult($"Thanks for your purchase");
}
How func knows which queue storage to connect to - If not mentioned, func loooks for default storage for func app. Else mentioned using Connection in Queue attribute
Go to storage account >Accesskeys >get the connectionstring>paste connectionstring to AzureWebJobStorage in local.settings.json
local.settings.json - shall not be placed in source control
Two types of C# function
C# script files (.csx)
C# class library (.dll)
Azure function core tools -
open source cross platform
function templates
allow to create functions easily
BUILDING A FUNCTION PIPELINE
Demo - Listen to a queue
in VS>FIle>New>Azure>Azure Functions to create a function projects
Add a new function - GenerateLicenseFile>Select Queue Trigger template>connectionstring setting>queue name
[FunctionName("GenerateLicenseFile")]
public static void Run(
[QueueTrigger("orders", Connection="AzureWebJobStorage")]Order order,//to listen to the queue
[Blob("licenses/{rand-guid}.lic")] TextWriter outputBlob,//To add binding to write license file to blob stroage , if blob container not present , it gets created
ILogger log)
{
outputBlob.WriteLine($"OrdereId:{order.orderId}");
.
.
.
var md5 = System.Security.Cryptography.MD5.Create();
var hash = md5.ComputeHash(
System.Text.Encoding.UTF8.GetBytes(order.Email+"secret"));
outputBlob.WriteLine($"SecretCode"{BitConverter.ToString(hash).Replace("-","")}"
}
Besides text, we can write stream, byte, string etc. to blob (check documentation)
{rand-guid} - special syntax to genernate random guid
orders - name of the blob storage, it not present it will be created
Demo -Blob trigger to send email to customer
Create a new func - EmailLicenseFile>Blob trigger template>ConnectionString=AzureWebJobStorage>Path=licenses (where we look for new blobs)
[FunctionName("EmailLicenseFile")]
public static void Run(
[BlobTrigger("licenses/{name}",
Connection="AzureWebJobStorage")]string licenseFileContents,//to listen to the blob entries
[SendGrid(ApiKey="SendGridApiKey")] out SendGridMessage message, //out used as the func is not aysnc. In that case we use IAsyncCollector
//api key comes from local.settings.json
string name,//gets mapped to {name} from blobtrigger
ILogger log)
{
var email = Regex.Match(input:licenseFileContents,
pattern:@"^Email\:\ (.+)$", RegexOptions.Multiline).Groups[1].Value;
messgae = new SendGridMessage();
message.From= new EmailAddress(Environment.GetEnvironmentVariable("EmailSender"));
message.AddTo(email);
var plaintTextBytes = System.text.Encoding.UTF8.GetBytes(licenseFileContents);
var base64 = Convert.Tose64String(plainTextBytes);
message.AddAttachment(filename:name, content:base64, type:"text/plain");
message.Subject...
}
Get Microsoft.AZURE.WebJobs.Extensions.SendGrid - 3rd party binding available to send emails
Input the blob trigger func can be string, stream, TextReader, byte[], ICLoudBlob etc.
You can always write your code if some binding are not available
Bindings are provided for convenience
Demo - Table Storage Output
Output Bindings
Azure Cosmos db
azure table storage
no binding for azure sql. SO write custom code or use EF
So, we will update the OnPaymentReceived func to add a row to table by adding another binding
[FunctionName("OnPaymentReceived")]//attributes
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get",
"post", Route=null)]HttpRequest req,
[Queue("orders", Connection="MyAppSetting")]:IAsyncColletor<Order> orderQueue,
[Table("orders")IAsyncCollector<Order> orderTable,
ILogger log){
string requestBody= await new StreamReader (req.Body).ReadToEndAsync();
dynamic order =JsonConvert.DeserializeObject(requestBody);
await orderQueue.AddAsync(order);//connects/creates queues, serialize message and send it
order.PartitionKey="orders";//jsut one partition for demo purpose
order.RowKey = order.OrderId;
await orderTable.AddAsync(order);
return new OkObjectResult($"Thanks for your purchase");
}
Table storage uses additional elements. Hence we need to update them.
public class Order{
public string PartitionKey{}
public string RowKey {}
.
.
.
}
Demo - IBinder and Table Storage
-IBinder:Contorl license filename
InputBinding
Lookup order in Azure Table Storage
Optional Email sending
Case 1 - Set the license file name as the orderid. Since orderId is not available at the time of function definition, we will used IBinder to create Blob binding at runtime to use orderId as the output file name
[FunctionName("GenerateLicenseFile")]
public static async Task Run(
[QueueTrigger("orders", Connection="AzureWebJobStorage")]Order order,//to listen to the queue
//Instead of guid we want to use orderId here,
IBinder binder, //binder will create blobbinding to write to blob storage
ILogger log)
{
//outputBlob is result of binding of textwrite and pssing in a blob attribute that has filename that we want
var outputBlob = await.binder.BindAsync<TextWriter>(
new BlobAttribute($"licenses/{order.Orderid}.lic")
{
Connection="AzureWebJobsStorage"
}
outputBlob.WriteLine($"OrdereId:{order.orderId}");
.
.
.
var md5 = System.Security.Cryptography.MD5.Create();
var hash = md5.ComputeHash(
System.Text.Encoding.UTF8.GetBytes(order.Email+"secret"));
outputBlob.WriteLine($"SecretCode"{BitConverter.ToString(hash).Replace("-","")}"
}
IBinder Interface
customize any binding at runtime
calculate attribute parameters on-demand in functoin body
Case 2 - validate licenseFile by matching with Order.Email in EmailLicenseFile and making email sending optional
[FunctionName("EmailLicenseFile")]
public static void Run(
[BlobTrigger("licenses/{orderId}.lic", //GenerateLicenseFile has added orderid as file name now. So the trigger will work on addition to blob when name is of format {orderId}.lic
Connection="AzureWebJobStorage")]string licenseFileContents,//to listen to the blob entries
[SendGrid(ApiKey="SendGridApiKey")] IColletor SendGridMessage sender, //ICollector same as IAsyncCollector but this is not asyc. This change is done to create a sender
//api key comes from local.settings.json
[Table("orders"<table name>,"orders"<partitionkey in row>,"{orderId}")]Order order,
string orderId,//gets mapped to {orderId} from blobtrigger
ILogger log)
{
//var email = Regex.Match(input:licenseFileContents,
//pattern:@"^Email\:\ (.+)$", RegexOptions.Multiline).Groups[1].Value;
var email = order.Email;
var messgae = new SendGridMessage();
message.From= new EmailAddress(Environment.GetEnvironmentVariable("EmailSender"));
message.AddTo(email);
var plaintTextBytes = System.text.Encoding.UTF8.GetBytes(licenseFileContents);
var base64 = Convert.Tose64String(plainTextBytes);
message.AddAttachment(filename:orderId, content:base64, type:"text/plain");
message.Subject...
if(!email.EndsWith("@test.com"))//TO MAKE EMAIL SENDING OPTIONAL
sender.Add(message);
}
DEPLOYING AZURE FUNCTIONS
-create the infra >
-app service plan to host function
-storage account
-application insights instance
-function app
using - Azure portal or visual studio
Infra as Code
Azure CLI
ARM templates
Once infra is up, one has to publish function code and set the settings
Manual publishing
Azure portal
Visual studio
Automated publishing
publish zip with kudu api
run from package - publish zip to storage account and settings tell where to look for code
Git repository
Azure functions core tools
func azure functionapp
AzureCLI
az functionapp deployment source config-zip
Azure DevOps pipelines
Cake - addons to publish func apps
Demo - Create func app using AzureCLI
az //helps with subcommands
az functionapp -h //shows all subcommands for functionapp
az login
az account set -h "<subscription name>"
az group create -n $resourceGroup -l $location//create resourceGroup
az sotrage account create -n $stoarageaccount -l $locaiton //create storage account
az resource create -g $resourceGroup -n $appINsights
--resource-type "Microsoft.Insights/components"
--properties "@props.json" // properties defined in props.json
az functionapp create -n $functionAppName
-g $resourceGroup--storage-account $stoarageaccount
--app-insights $appInsights
.....
az functionapp config appsettings set -n $functionAppName -g $resourceGroup
--setting "MySetting1=Hello" "MySetting2=world" //sets the app settings
Demo - Create func app using ARM template
refer documentation for azure-quickstart-templates
az group crate -n $res -l $locaiton
az group deployment create <paramenters> //create functionapp using ARM
Demo - Create and Publish using VS
Publish>Azure FunctionAPp>Select Existing/Create New
Check Run from package file>Next>select function app (if existing selected)>PUblish
IN APplication Settings>check the values >Insert vale fro Local>
Once published>Functions will start appearing in func app> Get url to test in postman
Demo -
Command line publishing
Azure function core tools
func azure functionapp publish pluralSighFunc2019<name of func app>
pushes zip to function app
zip got uploaded to storage account
its sas uri got stored in appsettings of func app (WEBSITE_RUN_FROM_APP)
Azure CLI
wont create zip package.
so create a zip - dotnet publish -c release
az functionapp deployment source config-zip
-g resourceGroup -n funcname
--src publish.zip
in func apps kudu, Data>SitePackages (packages from VS or AzureCLI)
Demo - Deploying azure func in docker container
core tools can generate file for usage
md dockerfuncs
cd .\dockerfuncs\
func init --docker
slelct worker:dotnet
cat .\DockerFile
we can create a docker image using the docker fiel
func new //create new func
docker version //
docker build -t dockerfuncs:v1//creates an image
u cna run this docker image on any docker host
WORKING IN PRODUCTION
HOW TO MONITOR - integrate with application insights
when did my function run
invocation history -
each func in func app has a monitor tab in blade. It shows the invocation history, log output etc
Run in application insights - link to open the query in AI insance
what did they output in logs
how much am i spending
func app >Platform Features>metrics>fucntion execution count, function execution units used for pricing calculation
func app >metrics>setup alert using Rule>Daily Usage Quota (func stops when limit reached till next day); to save cost
subscription >shows all the costs> click on one of the items on pie chart >
HOW TO SECURE
so that only authorized users trigger the function (especially in httptrigger)
function keys -
we can choose authorization level bw - anonymous (all), function(secret code for the func in code query string parameter or x-fucntions-key in http trigger) & admin(when one code for all functions;dont want separate keys for different fucntions)
cycle and revoke keys
enable easy auth
applices to entire func app
integrates with azure ad, google, fb and others
redirects unauthrized users to login page
perform own validation
e.g validate a JWT bearer token
danger!high risk of mistakes
Azure API mgmt
offers many features
proxies traffic to your func app
Demo - How to configure func keys
in Func>Manage>fucntion keys, hostkeys present >
in func > get func url contains options to which kind of url we want (default(function keys))
HOW TO CONFIGURE CORS
calling functions from javascript
func app>platform features>CORS
CORS - which urls are allowed for CORS
HOW TO INTEGRATE WITH OTHER AZURE SERVICES
Proxies
redirect incoming http requests to func app to other apps, SA etc
Demo -
proxies.json - stores proxies
func app>Proxies>No proxies by default>+ New Proxy>Route template=/>allowed http methods=GET>backend URL = where the url should get proxied to eg. storage account index.html>
request override (optional)>response override(optional)>Create
e.g. func app>proxies>route template=/images/[*restOfPath]>bahckend url = https://server/sdfdsfsdfdsf/images/[restOfPath]
Advanced Editor - shows files that makeup func app>shows proxies.json containing the proxies we created
Key Vault
to store secrets
access with managed identity
Demo -
func app>secrets>
in azure key vault, secrets have secret identifier > copy this identifier
key vault>platform features>identity>Status=On (func app id created in Azure AD)
This id of func app needs to be granted read on key vault
key vault>access policies>new>select principal (created in previous step>Create
func app > application settings>new setting>sendGridAPiKey =@Microsoft.KeyVault(SecretUri=https://my-key-vault.azure.net?secrets?my-seret?343rewfsdgrwrewfdsvsrwrwfsdffgdsg)>Save
Azure Devops Pipelines
automate func app deployment
Azure Event Grid
service that subscribe to events by any azure resource
e.g. deployment completed
API management
api gateway sits in front and add security
cahcing, usage quotas, rate limiting
serverless pricing tier
Demo -
Create a resource for API mgmt Service>
APIs>Add a new API>Select function app>import azure funcs by seleting ur func app>
Inbound policies>filter ip address>set headers>set response caching etc
Great security features>
Oauth configurable,
OpenId connect
client certificates
HOW TO BUILD WORKFLOWS
chaining of func app to create workflow. But it has following limitations -
how far through we are
how can we handle errors
how can we retry transient failutes
how can we wait for external events
how can we execute steps in paraller
Durable function helps solve it
orchstrator func - defines the steps in your workflow
activity func - implements a step in workflow
Demo -
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get",//signifies this is an HttpTrigger
"post", Route=null)]HttpRequest req,
[OrchestrationClient] DurabelOrchestrationClinet durableCLient,//starts durable workflow
ILogger log){
string requestBody= await new StreamReader (req.Body).ReadToEndAsync();
dynamie data =JsonConvert.DeserializeObject(requestBody);
var orchestrationId = await durableCLient.StartNewAsync(
nameof(NewOrderWorkflow), order);//id used to track the progress
//NewOrderWorkflow will call other activies in workflow e.g. generateLicenseFile, emailLicenseFile etc
var response = durableCLient.CreateHttpmanagmentpayload(orchestrationId);
return new OkObjectResult($"Thanks for your purchase");
}
//[ActivityTrigger] Order order // in activity funcs provide the trigger now and also helps tracking the workflow.
If you are interested in learning more about Azure Functions, there is a very good tutorial on Pluralsights - https://app.pluralsight.com/player?course=azure-functions-fundamentals&author=mark-heath&name=azure-functions-fundamentals-m0&clip=0&mode=live
Comments
Post a Comment