Making the cloud event-driven, and orchestrated

Making the cloud event-driven, and orchestrated

402476a4ba88f9ef948a17ee96d1f360?s=128

Ivan Čuljak

December 01, 2018
Tweet

Transcript

  1. 2.

    Who am I? • Ivan Čuljak • .NET freelancer in

    love with Azure, and Xamarin.Forms • Developing distributed cloud systems with serverless for over 2.5 years • Spent the last 1.5+ years migrating, and developing serverless stuff on a cool & quirky SaaS project • Tested, and sometimes deployed, a whole lot of scenarios that probably weren’t intended to be ran on serverless ☺
  2. 6.

    First of all – let’s get something straight ☺ •

    Serverless != FaaS (Functions as a Service) • Serverless is great WHEN you really need it • Serverless is MORE expensive when you have a constant load • Breaking down your monolith into functions is hard, and might even slow down your system if you do it wrong • Functions enable you to shoot yourself in the foot without any proper tool to warn you about it
  3. 8.

    A really simple „console” app First step • public static

    class Class1 { public static void Method1() { } } Second step • public static class Class1 { public static void Method1() { //Do some stuff Method2(); } public static void Method2() { //Do some stuff } }
  4. 9.

    After some change requests Third step • public static class

    Class1 { public static void Method1() { //Do some stuff Class2.Method2(); } } public static class Class2 { public static void Method2() { //Do some stuff } } Fourth step • public static class Class1 { public static void Method1() { //Do some stuff Class2.Method2(); } } public static class Class2 { public static void Method2() { //Do some stuff Class3.TriggerUpdateOneUI(); Class4.TriggerAnotherUpdate (); } }
  5. 11.

    Why is this even a problem? • Spaghetti code <3

    • It’s out of the methods scope • A crash or delay in the called method might set everything to fire • Extremely hard to maintain, and debug
  6. 12.

    Let’s introduce some messages Fourth step • public static class

    Class1 { public static void Method1() { //Do some stuff Class2.Method2(); } } public static class Class2 { public static void Method2() { //Do some stuff Class3.TriggerUpdateOneUI(); Class4.TriggerAnotherUpdate (); } } Fifth step • public static class Class1 { public static void Method1() { //Do some stuff Class2.Method2(); } } public static class Class2 { public static void Method2() { //Do some stuff MessagingCenter.Send("done"); } }
  7. 13.

    How do we solve this problem in the cloud? •

    Introducing Azure Event Grid
  8. 15.

    Why is this even a problem? • Your code isn’t

    clean, and it’s outside of the methods scope • The caller of your method might timeout because a method down the chain is taking too long • Hard to see the workflow without manual inspection / some cool tools in your IDE • Implementing a change is an adventure
  9. 16.

    Let’s introduce a „function orchestrator” Fifth step • public static

    class Class1 { public static void Method1() { //Do some stuff Class2.Method2(); } } public static class Class2 { public static void Method2() { //Do some stuff MessagingCenter.Send("done"); } } Sixth step • public static class Main { public static void HandleProcess1() { Class1.Method1(); Class2.Method2(); } } public static class Class1 { public static void Method1() { //Do some stuff } }
  10. 17.

    How do we solve this problem in the cloud? •

    We create yet another service/function/something that will group all the „business logic”
  11. 19.

    Why is this even a problem? • It’s blocking some

    resources (a thread, an FaaS instance, something...) • Those resources cost money... more noticeable on serverless than anywhere else
  12. 20.

    Let’s make them async and await them Sixth step •

    public static class Main { public static void HandleProcess1() { Class1.Method1(); Class2.Method2(); } } public static class Class1 { public static void Method1() { //Do some stuff } } Seventh step • public static class Main { public static async void HandleProcess() { await Class1.Method1(); await Class2.Method2(); } } public static class Class1 { public static async Task Method1() { //Do some stuff } }
  13. 21.

    How do we solve this problem in the cloud? •

    We start using queues ☺ • But... We could benefit from using queues that support „transactions”, so that we can return something • That’s one of the reasons we should choose Service Bus Queues over Storage Queues • The challenge of getting data back depends on the type of infrastructure on which the „orchestrator” runs
  14. 22.

    Why are we mixing events and messages? (because of different

    concepts and features) Azure Event Grid • low latency • capable of receiving and processing millions of events per second • at least once delivery Azure Service Bus • reliable asynchronous message delivery (enterprise messaging as a service) that requires polling • advanced messaging features like FIFO, batching/sessions, transactions, dead-lettering, temporal control, routing and filtering, and duplicate detection • at least once delivery • optional in-order delivery
  15. 24.

    Why is this even a problem? • It’s not if

    you won’t benefit from the values that get returned ☺ • Whenever a calling method „returns” you might need the context/results from the previous methods • Something might crash and you might need to resume/restart the process
  16. 25.

    Let’s return some values Seventh step • public static class

    Main { public static async void HandleProcess() { await Class1.Method1(); await Class2.Method2(); } } public static class Class1 { public static async Task Method1() { //Do some stuff } } Eight step • public static class Main { public static async void HandleProcess() { var a = await Class1.Method1(); var b = await Class2.Method2(); var c = await Class3.Method3(a); } } public static class Class1 { public static async Task<int> Method1() { //Do some stuff and return an int } }
  17. 26.

    How do we solve this problem in the cloud? •

    Introducing Azure Durable Functions • Framework built on top of Functions to enable long-running tasks • They automatically checkpoint their progress whenever the function awaits. • Local state is never lost if the process recycles or the VM reboots.
  18. 27.

    Now, let’s completely move to the cloud (except for those

    on-prem machines doing resource intensive processing)
  19. 29.

    Why is this a challenge? • Durable Functions are designed

    to call... well... other functions • You might do an HTTP(S) request to an external service, but you might not want to do it • You could easily trigger an event, or add a message to a queue, but how do you get the result back?
  20. 30.

    How do we tackle it in the cloud? Task<bool> approvalEvent

    = ctx.WaitForExternalEvent<bool>("ApprovalEvent"); • We send the request down the queue, and await for an external event
  21. 32.

    Why is this a challenge? • It’s not a huge

    deal to fan-out something – you just send out a bunch of messages to a queue in the worst case • The challenge is awaiting all those parallel „pipelines” to finish, and collect their result
  22. 33.

    How do we tackle it in the cloud? • We

    await all of them ☺ for (int i = 0; i < workBatch.Length; i++) { Task<int> task = ctx.CallFunctionAsync<int>("F2", workBatch[i]); parallelTasks.Add(task); } await Task.WhenAll(parallelTasks);
  23. 37.

    There’s so much left to say, but we’re out of

    time  Feel free to ping me if you’ll need me