S204 - Azure Durable Functions for serverless .NET orchestration - Jeff Hollan

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
everyone welcome back to dotnet Kampf I'm very excited to be here today my name is Jeff Hollen and I'm going to be talking a little bit more continuing on if you just saw the last talk talked about visual studio and some Azure services we're gonna be going deeper into a specific service which is as your functions and we're going to talk about a new framework that as your functions provides called as your durable functions now these are functions that allow you to do things that are stateful and long-running even though you're running inside of a service environment so to get started a little bit about myself I am on the Azure functions engineering team I'm one of the senior program managers on that team I was one of the original members of the Azure server list team and that's a phrase that you've been hearing a little bit about already today that I'll spend some time explaining and going deeper into as well so I've been working with server list technology for quite some time and I'll even tell you some of my experiences and some of the reasons that I love serverless now I personally knew that dotnet was my favorite language and my true love in around 2013 when I decided I wanted to write a mobile app and so I worked with Windows Phone and Visual Studio at the time and it was a breath of fresh air so you can quote me on this don't tell don't tell others because I do write functions in JavaScript and Python and Java as well dotnet that's where it's at that's why we're all here so that's what we're gonna be focusing on today and if you're interested to learn more about some of the projects that I've been working on as your functions you're more than welcome to follow me on Twitter or I've got a blog that I post some of the things that we're working on now to get started let's just spend a few minutes understanding what serverless means because I think an important part about as you're durable functions and these stateful orchestrations that you can use for any dotnet process it's kind of important to understand what the environment looks like so what is serverless the first part is that there's an abstraction of servers right it's kind of in the name and it's a terrible name I'm very aware of the fact that there are servers behind the scenes that are powering serverless it is my team that is often woken up in the middle of the night to make sure that those servers are running so yes it's it's a gimmicky term but there is an abstraction of servers so that you as a developer aren't having to burden yourself with keeping things up to date making sure that you have the latest security fixes making sure that things are available making sure that things are secured all of that is managed automatically for you so those are abstracted away allowing you as a developer to just write the code that you care about now for serverless another interesting aspect of it is that your VM your computer your machine isn't running 24/7 in fact with serverless what actually happens is we spin up resources for you on demand so if you think about a really simple function and this is one will actually show in a little bit I might want to do some processing whenever somebody places an order like I need to charge the credit card maybe I'm going to need to send them a receipt I don't need to have that function running all of the time in fact what I actually probably want is don't run this function until somebody places the order now that means that there needs to be some event there needs to be some signal to the cloud to let us know that you want your code to run so one of the pillars of server lists is that it is event-driven and we use those events to spin up your compute for you automatically run your code and then spin them back down now this is awesome though because it comes with an incredible cost savings because one of the cool parts about serverless is you're only paying when your code is actually running one of the projects that I worked on recently we're actually some Azure functions that run whenever somebody comes to my house I've got an IOT doorbell I only get like two or three visitors a day like somebody will come drop off some snacks that's an invitation anyone who knows where I live mail whatever but I'm not having to pay for some VM or some server that's running all of the time just for those three visits a day in fact what happens is my function just wakes up when someone comes to my house it does its job and then goes back to sleep so those are some of the pillars of server lists some of the characteristics about them that will help us understand kind of the power of durable functions but as well as some of the reasons that it's important so it's a little bit apparent with the definition but why is this exciting for a developer with serverless you're not managing infrastructure you're not having to deal with patches and updates and scaling out and scaling in all of that infrastructure is managed automatically for you and there's no wasted resources you're only paying for what you're using so there's a reason and if you if you haven't already been following server lists there's a reason there's so much excitement around this space because these are all benefits that hopefully we're all getting excited about and in many ways server list takes care of all the pieces that aren't really the fun parts of building an app and just let us focus on building the fun parts so at the center of server lists there's a few different flavors in ways that service applications can run but really at the center is what is called faz or functions as a service these are little bite-sized pieces of code that spin up in the cloud and spin back down now functions have a few characteristics that can sometimes be burdensome so the first is that usually a function only does one job you want it to be reusable just like other best practices in programming so if I need to do 10 tasks I very likely will need 10 separate individual functions an addition function execution should be very short-lived part of that kind of breaking them up into single responsibilities is I don't want one function that charges the credit card then sends the email receipt then updates the database and has 20 tasks that it has to do each of those tasks should be very short-lived and separate the other part with functions is it is just running code there's no actual state involved either completely stateless so in some ways when you have a problem that requires state that can be tricky as well and then I mentioned I've already gone into a little bit about how these are event-driven and scalable so the reason I want to highlight some of these characteristics is because often times we are faced with problems where we need multiple responsibilities to happen we can't necessarily have it be short-lived there's a lot of data that has to be processed there's a lot of work that has to be done and I need some state hanging around so specifically durable functions which is a new framework released from Azure last year helped solve a lot of these problems now just one more thing about why I love serverless I talked about how some of my first apps were on Windows Phone this is actually my first cloud app that I'm sharing here in some ways it was interesting because this both written for Windows Phone and it was written as an app specifically to interface with the Microsoft band so unfortunately I don't have a lot of users now because there hasn't been a new version of the band for a while but that's okay I still got the great experience of writing this and as I think back of that experience back in 2015 when I was looking to write my first app and you can see here in the picture what it was is a way for you to have your Microsoft band give you score updates because I'm into sports and at the time the NBA playoffs were happening and I wanted to know you know what's the score of the current game so I wrote this app which would sink the scores to that to that watch now this app took me about a month to build and even though at the time I didn't have any users I was still spending $80 a month to host the back-end services for my application because I needed to have enough compute enough virtual machines so that if all of a sudden I did get a lot of traffic my application could run so even with zero users I was still spending a bit of my MSDN credits at the time to host this thing and the screenshot I'm actually showing here was from a article written in Windows Central which you might be familiar with and at the time when this article got posted I went from you know a couple dozen downloads to thousands of downloads overnight because a lot of people became aware of this app then they had a Microsoft band in a Windows Phone well now I had to figure out what I was going to do about it because my app wasn't really equipped to deal with those spikes and traffic so that was really painful for me as a developer like I'd spent this time writing this app and now I was trying to figure out well what do I do with all these users who were coming in and they need their sports scores synced to their band and then the only other item is initially I only had score sports scores for you know basketball and football and when I say football I mean American football in this case and one of the first requests I had was hey we want soccer Storrs scores well I had to go in and kind of peel apart my monolith of an application and try to figure out how it works now I only bring this up because if I was to build this application again today in.net was serverless I wanted a ban paying any money a month when I had no users when I got those spikes in traffic my application would automatically scale to be able to handle that extra peak and that extra like in traffic without me having to get woken up or they even know that it was happening necessarily and then finally if I needed to add new elements if I need to add new features hopefully it's as easy as just popping some new functions into my subscription I don't have to peel a part of monolith anymore so this is one of the reasons I love serverless is that the different ways in the benefits that you can get and building applications and then moving forward into durable functions some of those powerful patterns that you can get so let's bring it back now and let's introduce kind of durable functions we've spent some time hopefully we have a good feel for what serverless means and the the meat behind the hype so the question is you know what if my task isn't short-lived simple and stateless what if it doesn't fit neatly into one of these things that we say our characteristics of serverless and that's where we still get durable functions so here's a few patterns that are steered difficult to solve in a service platform world or at least are until you bring in durable spoiler alert we're gonna have to solve all of these so I have some sequencing that needs to happen right this is the the store example that I've kind of been alluding to my first function might be charging the customers credit card the second function might be sending them an email letting me know that the charge was successful the third function might be creating a shipping notification whatever it might be well now I need to chain all of those together and if I'm not working with the framework it becomes kind of difficult to do that I have to go and have queues or some storage and I've got to make sure that everything is connected together pretty soon I have all these individual functions scattered around I don't really know what's listening to which queue and how they fit sequentially so this can be painful in a service world especially when I care about things like error handling what do I do if step three fails what does that mean about steps one and two here's another interesting problem which is fanning out and fanning in so if you think about an example where you have a bunch of data that needs to be processed it might be more efficient for me to paralyze all of that work to go and break it into individual pieces and process them one at a time we're going to go through an example later in the presentation about doing this with ordered history like I want to know all of the orders to happen in the last seven days and go do some work for each individual order well fanning out and service isn't terrible I could have something like a queue and just create a thousand queue items and say hey I need each of these items processed what sometimes gets trickier is how do I know when all of those are done how am i how am i managing and maintaining so I know hey all 1,000 tasks have been completed now you can send the summary email now you can aggregate the results and make some conclusions that comes really tricky it's very hard to pull parallelized compute back into a single thing when you're distributed across all of these different nodes of the external events is another one right what if I'm waiting for a human interaction what if I'm waiting for some event to let me know something can continue on long-running processes there's a pattern that we often talk about called like The Watcher pattern one of the ones I've used this for personally and I've written about in my blog is I wanted to watch the price of a specific currency in this case it was cryptocurrency so I was like hey let me know if this hits above or below a certain threshold within the last 24 hours well I can't have a function running for 24 hours because it's got to be short-lived but so what do I do when I need something that's constantly watching constantly monitoring something that might go over the course of a day or over a week long running HTTP requests this is an interesting one too so I might have a function that runs for 5 minutes or 10 minutes or a process that runs over the course of an hour there's some customers I've worked with who have to go process some document it might take an hour to complete well let's pretend you have a web page and that web page is going to kick off this job to go process well I can't keep that single web request open for an hour wait for the response to come back in and then send the response back to my website the internet just doesn't work that well right usually you need to break things up you need to send a request immediately get back a response and then check back every now and then you know usually you'll see like the check back in a few moments or where's processing your order or whatever it might be we can't just keep an HTTP connection open for that long so in a service world what do I do if I have a task that has to happen for that how do I know when it's completed how do I keep track of that state and then the final one which I kind of mentioned a little bit with the external events what if I have some human steps in the middle what if you know the last step before my purchase process is completed I need somebody to actually package up the product and put it in the mailbox that means that my application needs to be smart enough to know when does that human go and take their step and then continue on with the rest of the flow how do you correlate those events in a service world or even just in a distributed computing world like these problems are especially magnified because of what service is and that you don't have any long run in compute but really these are difficult problems to solve regardless these are problems we've been working to solve and make easier in different ways for a long time they've become more difficult once we start talking about the cloud and distributed computing so now let's talk about durable functions I've teased it so much you already know all the problems that solving so let's define it a little bit durable functions is a framework a free open-source framework for Azure functions that allows you to write long-running orchestrations as a single function and maintain state for all of the calls that need to happen so you can write a single orchestration that might last the duration of an entire week or a month that might call multiple functions that might be very long-running that might have to wait for human interaction but I can write all of that as a durable function and it just works and still runs in a serverless way this is awesome to simplify these complex transactions and coordinations so that you can very easily map and understand the whole end-to-end system that's happening now all durable functions is completely written in code in fact you'll see in a second we're actually gonna write this in dotnet code so I'm not dealing with JSON schemas or workflow definitions or some of the other ways that often orchestration is solved I'm doing this all right within dotnet in fact you'll see in just a little bit you can do things like a try-catch block you can do things like a weight you can do these concepts that you're likely familiar with but now you can just automatically have this power and this long-running that's taken care of from the framework and durable functions is generally available we announced you availability in May of this year at the Microsoft build conference and it does support multiple languages so dotnet c-sharp is the one that I'll be showing today we have some community members who've done some work to write durable orchestrations in F sharp and we have JavaScript which is actually in preview today but if you're interested in writing terrible orchestrations in JavaScript that's an option as well so I'm gonna talk about some of the components of a durable function and then we'll show what our first durable function looks like so there's often times we talk about three different components that make up an overall durable function now the first piece is that starter function the starter function is kind of whatever's going to trigger off this long-running process very often this starter function is something like an HTTP endpoint you want to be able to start off some report you want to be able to go place that order when somebody makes a web request or when somebody drops an item in a queue or when some event happens you just have a function that's going to start off this orchestration now once that starter function gets triggered and it knows it needs to start its orchestration it's going to go ahead and send a message through the framework to the orchestrator now the orchestrator is where all the state is managed where all of the calls to different components are taken care of the orchestrator is really the heart of the durable function that's where you're going to put your orchestration logic and we'll see that in a few moments and the last piece is you likely have different activities that need to happen again going back to the example we've been kind of following with I might need to charge the credit card send the email these are all individual activities they could be written as separate as your functions so the orchestrator is actually going to call all of those activities for you and it's gonna enable you to decide do I want to do these activities in parallel do these activities need to bun sequentially or maybe I just need at least one of these activities to complete before I continue on all of that's possible with endurable functions so let's kind of solidify this a little bit and see what the code looks like now that we've seen the components this is an example right here on my slide of an orchestration function so this is the orchestrator function in the heart okay so some functions going to start this orchestration and you'll see here I have some other functions that I have written that I'm going to be calling okay so the first step I'm going to call function f1 once that's completed I'm going to be calling function f2 and I'm even going to pass it some data I'm gonna pass it the result of my first function and chain that to my second function and then finally I'm going to call function f3 once this function is done and I'm gonna pass it a result of that so I'm kind of starting with f1 and I'm passing through sequentially the data from all of my different calls until finally I'm going to return the result so here in a very logical way in dotnet I've described this chaining and passing data between different functions and what's nice here I mentioned this before I have nice familiar concepts like a try-catch block so that I can catch of exceptions happen and decide you know what do I want to do where did the exception occur what was the type of exception to have some resiliency in this as well so the other pieces again kind of mapping it back to there one this trigger this is our Orchestrator function it's saying hey this is a durable orchestration context is the type and it will have the context of the orchestration I'm gonna be calling my three activity functions and finally we're turning those back now I'm actually gonna go out of order here because I want to do this one now I'll do this one first so before I do a quick demo I do want to show you one important aspect which is how durable functions actually behaves so if you look at this example again this is a very simple function the next one we're gonna look is very simple to it call function one then function to then function three it's very possible that calling all three of these functions might take a very long time so we have to do some work in the framework to make sure that this is durable that you have at least once guaranteed execution and that everything executes in the order that you expect it to in order to do that we're using a thing called event sourcing and I'm going to show you through an example of what's happening behind the scenes so before I do I have a very simple orchestration here just to illustrate the point because this is very critical to understand honestly if there's anything you gain from this talk if you understand this slide you will be much more successful in writing durable functions so I here an orchestration some sample code up here I'm going to create a new list it's a list of strings and all I'm going to do is I'm going to add to that list some call to a function okay so I'm going to call a function and the functions name is say hello and I'm gonna pass it the value dot-com okay that's all I'm doing I'm calling a function say hello I'm passing it the value net conf whatever it returns back which is going to be a string I'm gonna add that to my list okay so very simple all I want to do call this function stick the outputs into my list which is a string now how do we actually do that from the framework perspective so what happens is we have this other component here I haven't mentioned this is our execution history this is the state this piece is how we store and know how far in the process your execution has gone so the execution history here and I'll show you through an example in a second is as your storage and that execution history is going to be very important in to how this functions and how this works so the first thing that happens someone calls the orchestration our starter function gets the request and it says hey somebody wants this orchestration to run so now what's going to happen is our Orchestrator functions going to wake up and it's going to start at the very top of the code and it's going to say hey I need to create a new list so it's going to create a new list then it's going to come down to this next line and it's going to see that there's a no wait here and it's going to see the await is to call another activity now what happens here is instead of just automatically calling the activity function the orchestration the orchestrator functions actually going to go to the execution history it's going to look I've visualized it here with this log it's going to look in the logs of the state of this function and is going to say hey have I already done this did I already tell say hello to Netcom did I redo this piece and in this case the execution histories came back no you you haven't done this yet and sort of your critters can be like cool that means I need to do it so it's going to queue some work it's going to say hey hey say hello function whenever you get a second you need to say hello to net comp and then the orchestrator function completes it just goes away it's done with its job for now this is how it can work in a server this way that orcas raishin function after it schedules the work is now scaled to zero in this case so you're actually not getting charged for that orchestration piece anymore it's gone away and instead what's happened is our activity function wakes up and it's like oh hey I have some work to do and it looks at the it looks at its work and it's like hey I need to say hello to net comp so it says hello to net comp hello net comp and it goes ahead and it updates the execution history so it's like hey I did my job so now what happens this is the most important part okay so the orchestrator knew it needed to get some work done the activity function did the work and it let the orchestrator know that it's finished with its work now what happens when the orchestrator wakes back up is extremely important to understand when you're writing in debugging these the orchestrator function is not going to pick up from where it left off in fact what's going to happen is it's going to start from the very top of the orchestrator again when it wakes back up so it starts at the top it does that first line of code hey I need to have a new list of strings it goes to the second thing and it says that a wait word and it says that it's supposed to await an activity and this time it's going to go to the execution history and say hey have I already done this thing and in this case the execution history is like yeah the the say hello function already said hello to net comp you've done this part so now the orchestrator is like cool well let me go on to the next step and it's going to go ahead and continue on with its execution which in this case is just returning that that list of one but you can imagine here if I had other calls that needed to happen at that point our Orchestrator would continue on to the next call schedule the work go back to sleep wake up continue on to the next call schedule some work go back to sleep and this can happen with some really complex patterns too like you might have when we do this fan out fan in pattern that might schedule thousands of work items that need to complete before the orchestrator can wake back up so the main reason I wanted to show this illustration which is an awesome by the way this is my favorite slide of all the slides for functions written by one of our developers katie is you know it's important to understand that this is following replay through event sourcing to be able to manage these long-running and stateful tasks that might be happening in a completely distributed way it's very possible that the activity function happened on a completely different virtual machine a completely different node than your Orchestrator function but it doesn't really matter because you're just scheduling this work across all right so let's see what this looks like from a development experience we've kind of talked about the concepts and how this is powered but I did want to get you a feel for what it's like to write one of these so I'm here in Visual Studio 2017 in this case and Andrew showed some of this to you before how about hi can go ahead here and create a brand new as your functions project okay so I'm just gonna create this and we'll say hello durable functions just a simple solution so using the crowd work loud workload I'm gonna say alright I want a new Azure functions project there's a few QuickStart templates up here in fact we should add one for durable on this top list but I'm going to go ahead and select just an empty project for now now this is an important piece to note it's asking me where I want to keep my state while idle it develop locally and I'm just gonna use the Azure storage emulator but if I wanted to I connect this to an actual storage account in the cloud but I don't need to right now ok so I want a new Azure function I want the state to be the storage emulator and now let's go ahead and add in a new function to this project ok so this is pretty empty now I've got my local settings which has telling me that I'm using my development storage there's not a lot here so let's go ahead and add there it is new as your function and we'll just leave this called function 1 that's fine and here when I add a new function there's actually this really handy template for getting started which is hey I want to use the template for creating a durable functions orchestration ok so let's go ahead and choose that template now this is going to add to this function app my durable functions orchestration and this is just a really nice hello durable function sample okay so let me break down the three parts I'm actually going to start at the bottom here so the first part this is our starter function in this case I'm exposing an HTTP trigger I'm going to get a request it's C there going to be an HTTP GET or an HTTP POST both are acceptable and all the code is really saying Hey right away go start a new instance of in this case it's called function one okay so go start a new instance of the function one Orchestrator it's going to create a log and it's going to return back some status endpoints okay so my starter function gets an HTTP request it says go start an orchestration called function 1 and return back your response now that brings us here to our orchestration here's our Orchestrator called run Orchestrator it's actually function 1 known from the function runtime ok and this is very similar to the example we saw it's going to create a new list of outputs called strings it's going to call 3 what's going to call the same function 3 different times it's going to call the function 1 hello and pass in Tokyo function 1 hello and pass in seattle function 1 hello and pass in london and it's going to add each of those outputs to the list and then it's eventually going to return that whole list and you can see here from the comment we expect when it's done it's going to have hello Tokyo hello Seattle hello London now the last piece what is function 1 hello well that's our third as your function right here okay so this is function 1 hello it's just going to create a log and then return back hello name using some beautiful string interpolation my favorite feature of c-sharp all right so we'll return this outputs hopefully that's simple enough those are all the components my starter function HTTP request starter orchestration which is going to call the hello function 3 times now one of the awesome things about Azure functions but is specific specifically durable functions is I can actually run and debug this all locally so let's go ahead right here and set a breakpoint on this first call to function 1 actually I'm gonna do it on my second call I think the data will be more interesting now before I run this I want to open up the Azure storage Explorer Andrew showed this off a little bit in the previous session if you saw but this is just a really nice way for me to look at my storage account and in this case I'm connected to my storage emulator or mu let an emulator according to my typos and you can see here I have a totally empty storage account so there's nothing that's stored currently all right so let's check this out let's click here and run this function it's going to spin up the Azure functions runtime here inside a visual studio this is the exact same runtime that will be running once I publish my function to the cloud it's going to spin up and it's going to see that I've written these few different pieces and you'll see here in just a second it should actually give us this endpoint okay so it's it logged a few things it's like yep I found all your functions it looks good it's actually going to give us this nice endpoint this is our starter function so here all locally let's go ahead and call this starter function so let me copy that URL will open up postman which is a really convenient HTTP client for debugging I thought I had it open before sorry about that so here we come in let's go ahead and make a request to that URL okay so that kicked off our starter function our starter function at this point should wake up the orchestrator the orchestrator called our first function and you'll see right here I actually hit a breakpoint and I hit this breakpoint right before it called the step hello Seattle now I want to keep it on this breakpoint because I want to show you something let's come back over here to our storage account and refresh it because we should see that a few things got created the first thing that got created is in our table storage and I'll zoom in here a little bit so you can see a little bit better durable functions framework actually created some tables to store things so one of them is a table that keep track of all of the instances and their status and the other one is that execution history so that the durable function knows what it's doing and when so let's go ahead and open up that execution history and this should look very familiar to that last slide and in fact I can see here and usually when you're running in production I don't really recommend that you dig in here to your tables to try to debug it it can get very messy but for the purpose of understanding you can see here all of the different pieces that are happening so here the execution went ahead and started its scheduled some tasks to be completed you can see orchestration completed in fact if I step through a little bit more and let the storage update oops not that one let's go ahead and continue this call across and let it say hello to everything Oh that's right that was one of the replays let's come back here and refresh this and you'll see here that it actually scheduled one of our tasks and the task function one completed and all of these things are being updated and function ones result way over here you can actually see the result was hello Tokyo so all of this state is being stored in the execution history and you'll notice I actually hit my breakpoint again because it's replaying itself and regenerating the state and it's replaying again and regenerating the state and a tree playing again and regenerating the state until finally it's replayed all of the times it's called all of the tests it needs to at which point it can return back to our function that called it okay so I just wanted to show you the development experience but also show you like there is no magic here this is this is the same stuff that I showed in my other slide we have this table store that's being used for all of our states you'll see there's actually a number of cues that are created so that it can control the work that needs to be required the orchestration the orchestrator can have its cue the activity functions can have their cues I'm not going to go a whole lot into that today and I even have a thing to have leases so all of this is locked and managed in stateful but again I didn't have to write code for all of this awesome state management the durable functions framework just gave it to me all for free ok so hopefully that is a good hello functions demo the only other thing and you saw this in the last slide if I wanted to make this a little bit more error resilient I could add things like a try-catch block and just put you know try-catch right over here this is totally valid right just just my regular old c-sharp it's all good okay I could I could do things like a weight all and you'll see that in just a second alright so that's our first hello durable function trigger the last thing I'll show you once this is working how I want it to locally I can just simply come in here and publish it to the cloud and once I publish this as an azure function now I could call this orchestrate it at any time and this will be able to run and scale completely server lessly either in a new or an existing app alright let's come back here now that we've seen that and talked about some of these constraints so most of these constraints stem from the fact that this is using event sourcing with replays to work so let's check out some of these constraints Orchestrator code must be deterministic and when you understand how durable functions works this makes a lot of sense if in my orchestration logic I say get the current time and generate a random number and based on what that random number is and what the current time is do this or that now the problem with that approach is every time that function replays every time that orchestration replays the result might be different which means I might be replaying down different code paths and I started down things are gonna get corrupt and they're gonna blow up into an ax massive fire eruption don't do it okay so just make sure your code is deterministic so a few things don't use random numbers don't say get the current date time don't generate new grids also don't do IO directly in an Orchestrator don't go read files or polling files directly from the orchestrator and I love this one I I this is my favorite bullet point of the slide don't write infinite loops there's actually yeah so let me spoil it with this one never writing infinite loops is really never a great a great idea okay almost never alright so the good news is we have workarounds for all of these constraints because there might be scenarios where I care about what the current time is there might be scenarios where I need to read in file data and there might be scenarios where actually want this thing to run indefinitely so in some ways I do want it to loop indefinitely so we have some recommended workarounds the first one for random numbers in date time that orchestration context that's passed into the orchestrator we actually provide some helper methods here like get the current time now what's cool about this is that we'll get a current time but we'll do it in a way so that when we replay it we make sure that we reget the same time that we got if that makes sense so you won't get a different time every time it replays you'll get the same time from the first time it ran so we get some nice helpers there do your i/o and activity functions you can do whatever you want in an activity function activity functions have no constraints into what they can do into how they can be run random numbers or not so if you need to move things into your activity function that's totally cool and then you do need something to loop indefinitely excuse me we have this concept called continue is new now the main reason looping indefinitely can get tricky and durable is because if you think about that execution history if that execution history has been repeating and re looping for days your history is going to be massive and every time it tries to replay it's going to have to pull that apart and redo all the infinite loops so there's this concept called continuous new which will take a snapshot start the instance over from the beginning but it's not going to have to replay every single interation of the of the infinite loop so we've got some good workarounds here for you but it's important to know as well some of those constraints all right so let's show one more demo now this one is a little bit different what I have here and I've teased this one already this is a a website it's actually powered by serverless functions this was created by one of the cloud developer advocates Sarah Dresner who is a rock star I will say I'll take every excuse I can to say she's a rock star so I could do something here like add a few items to a shopping cart go ahead and check out of the shopping cart here to let me just type in my very real credit card number being broadcast for the world and in this case it's actually calling an azure function to process that payment request kay yay I just bought however much I just bought I didn't even look probably like $200 worth of stuff now the problem that I want to solve has to do with this store shopper T and that's that the business comes to me and they say hey Jeff you're so productive you're using all this awesome net stuff you're using Visual Studio and server lists you can do anything we know you can now my problem is I want to have a report I need to know every seven days what's the current status of all of our orders okay and we're a really popular store we might have thousands of orders that have occurred in the last seven days so I need you to give me a report so that you can look at all of the orders to happen in the last seven days and tell me what's the current shipping status how many of those orders have been delivered how many of those orders are being processed how many of those orders are in transit now I love server lists and I'm like I want this to be super efficient and scalable and not worry about infrastructure but this can be a hard problem to solve in a server list way because if you look at the diagram here of what I actually need to happen I have my orders database which for shop ATI's cosmos DB and I'm gonna go say hey give me the last seven days of orders and there might be 10,000 orders there 1000 orders I don't know it's it's gonna be indeterminate it's gonna change every time I run the report and what I need to do is for each individual order for each order I need to go call some shipping API maybe it's the FedEx API or the UPS API I don't know it could be anything and that API is not super fast it might take a second or two for every single order so how do I do this like if I just try to write a single c-sharp application it's very possible that this thing's gonna take two hours to run like it's got to make all of these individual calls I can't just write that as an as your function and publish it to the cloud as is so that's where I'm going to bring in durable functions to help orchestrate these different calls paralyze the work and do it all for me so I'm going to show you what that solution looks like this is also on github if you want to check it out let's open where's my open recent recent right here I'm crazy right here I know my name is not Cory everything here just happens to be named Cory for undisclosed reasons all right so here is that report generator as a durable function so I'm actually going to start here from the bottom again to peel this apart I have here my starter function same as before I'm gonna get an HTTP request that says hey go generate for me the report okay that starter functions going to call the durable generate report Orchestrator so it's gonna say hey go start this orchestration that's all this code right here I'm gonna create a new list of tasks and I'm gonna create a new list of order totals because I'm gonna need to calculate some totals at the end of the day now the first thing I'm going to call is this as your function called durable get transactions or I'm gonna say go get me the last set of transactions so it's a simple as your function you could actually see the thing down here it's going to call cosmos DB and it's going to ask it for all of the most recent stripe charges that's using the stripe API to make these charges really simple as your function just go get me the last seven days of striped charges now once I get all those charges this is where the magic happens I'm gonna say for each one of those stripe transactions go get the current order process but I'm actually not awaiting it right here I'm just adding that task to my tasks list and what's cool here is that I can say after I add all those tasks wait for all of them to complete and here's where I put my await now what this is going to do from a durable function standpoint and this is going to paralyze all of those different calls it's going to allow all of these activities to potentially scale out across multiple nodes wait for all of them to complete then when all have completed I have this simple link statement here which is going to generate for me a nice summary report okay this is really cool that I'm doing a lot of heavy lifting but I'm writing it completely in Azure functions this is all gonna run Server lessly but it could be doing some heavy lifting over a really long period of time and this is how it's represented is a beautiful c-sharp app it's awesome it's very exciting it's really cool stuff so let's see it in action okay so let's come back here to our store and I've got here the function that I want to call I have the HTTP endpoint right here right here HTTP start so we're gonna kick off that function now I didn't call this out before when we were debugging it you'll notice right away I got back a response I'm not having to wait two hours for this thing to complete the durable orchestrations kicked off I'm gonna talk too long so I'm gonna have to run this thing again because I want you to see it running but it gives me back some things so the first one it gives me the orchestration instance ID so I can use this to track the orchestration I get a status endpoint so I can view the current status of the orchestration I get an endpoint here called send event post URI now this is a web hook that I could actually call if I needed to add some data to the orchestration if I needed to wait for some event this is the endpoint that I could call to send at that data so I can raise events and add that to the orchestration while it's waiting for the right event I have a URL here that I could post to to terminate and we have this new URL here which is actually really cool this will allow me to rewind my registration if something happened and I want to rewind it I could call this URL right now now I'm actually going to call this one again because I talked for so long so I'm gonna get a new instance and let's follow this status endpoint no I don't know if I am I need to I think my cache is not actually calling it again okay that's a different instance maybe it is maybe this is just too fast well what I want what I wanted to show you before I got confused in chrome land is so here's the Status endpoint now if this was still running I would get the endpoint status running and I could keep pulling this endpoint until it was completed but you can see here in this case it's actually completed and here is my report out so I have seven orders that have shipped four orders that have been delivered ten that are other and five that are processing now if this was a thousand orders or 10,000 orders this would still work it might just take a little bit longer to paralyze and complete all that work but the orchestration logic is the same so really cool that I can do this fanning out and fanning back in all right so let's show just a few more things really quickly the last piece I want to touch on is you know how do you monitor and manage these different durable orchestrations I'm doing some complex stuff here what if something goes wrong how do I make sure that things are behaving how I want them to so the first one that I would recommend is use as your application insights we actually prompt you to create this automatically on new function creates and this is going to be a source that you can use to manage how your functions are behaving and how your instances are working so I actually want to show you that here very quickly this is that store function app that we just called to generate the report I'm going to go ahead here and open up application insights and I can see here you know response time statistics and server requests and all these other fun things let's come directly into our analytics now I'm going to run a query which will give me the status of one of my instances through as your application insights and then I'm gonna show you how I got that query because it's gonna look really complex and then you'll be like wow Jeff's such a cheater he just he just cheated to get this so let me zoom in here a little bit this is the query I'm gonna run this is called the application insights query language extremely powerful I have here my instance ID that I care about I'm gonna look for all logs within the last two days and then I have this really long query which pretty much just gets all of the instant stuff for me it's actually pulled straight from our documentation so no one has to recreate this on their own but when I run this you actually be able to see here in application insights at the bottom here is the history of this instance I can see that I got transactions it's scheduled that tasks and then completed it and then it scheduled a bunch of get the order status tasks and I can see exactly when those tasks started when those tasks completed some of them started and completed in different orders until finally my orchestration itself completed somewhere on the next page of these logs so really cool here I get the sequence of exactly what happened all of this happening in parallel right here in app insights and again I know this looks a little overwhelming if you come over here this is the Azure functions documentation there's a whole section on durable functions this is incredibly written documentation it was mostly written by the dev lead for durable functions Chris Gilliam but right here I actually have some really helpful queries so you know here's the single instance query that I just used I just copied that and pasted it in tap insights there's one that gives you instant summaries there's more information here on how you can log and add your own logs all this is right here in Doc's that I'd encourage you to check out okay so that's one really important no the other one in terms of monitoring and management there's also an API that your function host will expose to do some instance management see the current instances update instances terminate instances the only last piece which is important too and then we can switch to some QA version your durable function very consciously you have to remember the whole has to be deterministic it might be replaying if I made some breaking change to my Orchestrator logic and just published it willy-nilly to the cloud and there was an existing orchestration that was in flight it's very possible when it starts doing its next replay it's going to be pulling in the new version of the code and as it starts evaluating that code and doing a bent sourcing it might be like oh wow this is totally different and being a very corrupt state now maybe that's okay but there are strategies you should be aware of so there's kind of three big ones our documentation calls out first one you can just do nothing maybe you're okay with some instances becoming corrupt maybe you know that this is very infrequently executed just deploy as you will it might not be what you want though the other one is wait for your Orchestrator to drain maybe you have a scenario where you can actually wait and make sure that everything completes before you start the next one and then you can just publish an update once there's no running instances but the third one is the recommended way is actually there's a way to do side by side deployments so there's a way in your durable functions project it's actually from this host JSON file that I didn't go into yet where I can give my task hub a unique name so if I publish a new version of my function I could actually give it a new name for a new task hub and then it will create new execution histories for new instances and that task hub would be running independent as my other one as long as the codes still available for the other tasks up so you might need to rename some things there too again this is all in in Docs as well okay so with that I do want to make sure I give enough time for Q&A because I know there's been some good questions so I'm just going to do one last plug check out that documentation I preview just a little bit ago it's really really good the other one too which is cool durable functions is a completely open source it's actually built on top of another open source technology called the durable task framework I've done links here to both the durable functions extension for Azure functions and the durable tasks framework with our branch for the changes that we've made for as your functions what's awesome about this from Azure function standpoint I've actually come here to the project we have a lot of contributors given how relatively new this is they are not on the azure functions team there's a lot of people here too and shout outs to them who've come in they've engaged with us on open issues they've opened pull requests they've helped bring this extension forward and this framework to make it accessible for every developer in every single scenario so I'd encourage you if you're interested in in contributing at all this is a really good as your functions repository to check out there's a great contributor guide everything here that you need so that you can jump in if you want to see some changes we've got some really cool community additions to this so with that I do want to give some time for questions because I see if you coming in so we've got a few minutes here so the first one is from our awesome community in Miami is there any guidance available for testing as your functions in the various types of durable functions yeah so the only one I'll say in addition to the kind of tests I just ran you can write unit tests for durable functions and I encourage you to so that you could use dot net test and make sure that your unit tests work it gets a little tricky with durable functions because you might need to mock that orchestration context but it is possible there's a doc here I believe in the durable function stock that might go into it even a little bit more so it's something we're aware of we want to improve but you can definitely do that today for sure ok so the next question have there been any thoughts on doing service discovery for serverless functions so have various function apps how to know that where they are health checks it's a good question durable functions provide some level of calling other functions in that app but it's not really at the point where you say like I want to call the function that resizes images and that's automatically resolved and directed for you automatically I guess I would say it is something we've thought about we do plan to do some work in the future to call functions potentially in different applications there are some patterns to do that today but having a central that or a central service repository where you could kind of register services it's still a little early but it's definitely something we've talked about before ok so are there going to be options to set more compute or RAM in the consumption plan so today a consumption instance is about a gig and 1/2 of RAM and one core of CPU there is some stuff we're chewing on right now that would enable you to run on premium hardware I guess I would just say stay tuned there's some big conferences coming up where we'll have some answers to this so that's about it as non subtly as I can answer that one oh this is a really good question from Sam something I meant to go into can we use durable functions in Microsoft flow and if so how so if you're not familiar Microsoft flow is another kind of sass orchestration technology it's actually built on top of as your logic apps which is a visual orchestration tool within Azure and answer is definitely yes in fact I have a sample here it's almost like I knew this question would be answered so I have here what what an example of a logic app looks like so this is also doing orchestration but in this case it's a visual designer that you're working with and behind the scenes it's actually generating this JSON workflow definition which some people love and some people are like just give me the dotnet stuff well here in this flow or logic app in this case I'm calling a function now this function could be a durable function and in fact durable function works really great with logic apps that pattern that I showed before where you call it in an immediately rescinds back a status endpoint and then you have to check that status endpoint till it's done logic apps in Microsoft flow will actually follow that pattern for you automatically so if you have a durable function and you use the HTTP action in Microsoft flow or the Azure functions action and logic apps everything actually just works the only change you actually need to make is you need to make sure you're returning a retry after header in your starter function but it all works great so definitely try that that's a really good combination to get some of the best of both worlds like some of those out-of-the-box connectors from flow and logic apps okay we've got a few more minutes here so what causes the orchestration function to wake up again after the activity functions completes what if there were multiple activity functions that's a really good question I might answer this slightly incorrectly so I invite Chris Gilliam or Katie or anyone I'll probably poke them after this to correct so the orchestration function from my understanding has its own queue and when activity functions are done they let them know the activities done and it's up to some job I don't know if it's direct orchestration function to go and see if it has any work items and to see if the criteria is completed for it to wake back up I don't know exactly how many times it wakes up like in the fan out fan an example but it does work and it's very performant like there's very low latency there so I don't fully know all the magic behind the scenes that's making this happen but it works and for the most part it's powered by queues storage queues that wake things up ok can we assume that if an activity is in progress the orchestrator will see that when it wakes up every time also on the fan out will the orchestrator fire all activities at once or after going to sleep waking up for each line yeah so I think we've kind of answered this throughout the both the other questions the orchestrator function likely won't wake up if there's only a single activity and it wouldn't wake up until that activity is completed at least as far as I understand and for fanning out if you saw from my Log example of application insights will actually you you have the ability to do them all in parallel so it doesn't have to do line by line you can paralyze a bunch of work with durable functions too so hopefully we've cleared that one up through some of the other questions - Devon sir - so we've got another one here we've got time for for a question or two more could this be used for TCP sockets not web sockets is a scalable socket server or client that's a good question I'm not familiar enough with TCP sockets and how they're different than web sockets I don't know if that's like an HTTP to thing or whatever but I can at least speak to web sockets I know one of the challenges with a web socket is usually it requires a persistent connection so if I have something like a asp net app that's talking to a signal our server that signal our hub needs to be persistently available now durable functions even though we're able to run in persistent apearing ways most of that compute is still very ephemeral and the orchestrator will wake up and go back to sleep and activities will wake up and go back to sleep so there's not a persistent connection there so it's an often not a great fit for those WebSocket scenarios we require persistence the one I've actually seen paired most with just matter-of-factly for server this is actually the new signal our service where there is a signal our service we actually have signal our service bindings for Azure functions also community contributed those will give you a persistent connection so that's something to look at as well and then the last one can we pass authentication headers and tokens between functions I definitely know your starter function can have authentication headers passed in I don't know if there's a way to authenticate to activity functions but I don't know if it's really required because they're almost internal calls anyway excuse me but for Azure functions all up you can absolutely put authentication in front of your function and say hey I need an azure active directory token or a github or I'm sorry a Google token or a Microsoft account token to authenticate before I kick off an Orchestrator so great questions everyone thank you so much for participating hopefully this was helpful if you have any more questions feel free to reach out to me or follow some of those links that we shared earlier I'll pop them up one last time and I hope you enjoy the rest of your conference today so thanks so much
Info
Channel: Microsoft Visual Studio
Views: 22,450
Rating: 4.987988 out of 5
Keywords:
Id: UQ4iBl7QMno
Channel Id: undefined
Length: 55min 58sec (3358 seconds)
Published: Fri Sep 14 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.