 This is Reactive Microservices with .NET Core. My background is in Distributed Systems. I wrote a free book called Beyond the 12-Factor App on building cloud-native apps. I've also written a couple of books on .NET. Most recently is the Microservices with ASP.NET Core. I wrote a book on Go, and if you're into that sort of thing, I also wrote a couple of fantasy books. So what I want to do today is try and figure out how to cram this all into half an hour. But mostly, since every microservice presentation is mandated by law to have a custom definition of what is a microservice, I'll have my own. Then I'll talk about distributed transactions in the cloud microservices world, and talk about how we can try and work around some of the limitations that we get from moving from monoliths to microservices. I have what was a fully buzzword compliant demo. Unfortunately, the Kafka buzzword is broken. I ran an update this morning, and that's obviously not what you're supposed to do before demo. So first question, this is a trick question. So just letting you know, is this a microservice? Yes. Nope. This is a protocol handler. It's a facade. This is something that responds to an endpoint. The microservice is what's inside. So my definition starts with some microservices are restful, not all restful services are micro. When building microservices, most of us tend to start with the idea that we build from the rest endpoint inward, and it's been my experience that doing that tends to cause more problems than it's worth. So I wanted to describe the microservices onion, and on the inside of this is the service, which is your real business logic, and then we have some of the non-functional requirements like logging, metrics, monitoring, security, the protocol handler which I just showed, and a bunch of other things like storage, discovery, tracing. A lot of the things that we're talking about at the summit here, these are all things that are important, but we should not have to write code for them, and these things aren't in our service. So as promised, my custom definition of a microservice is that it is a unit of functionality that it hears to the single responsibility principle. Asks nothing of its host. There's an asterisk there because there are some basic requirements like being able to be deployed in a container and so on. Like I said, we have a whole bunch of things that we have to worry about, but these are not things that I want in my code, or I don't want them to affect the core of my business logic. So we need to do service discovery. There's a bunch of demos this week on doing SteelTow. You can also use console, DNS, other things. We all have to monitor our services. They need security. We need to interact with our services. Most of us do it with HTTP or REST, but I'm going to show using GRPC. We need configuration. We need to be able to do zero downtime deployment, fault tolerance, all of that stuff that our platform provides that our service code should not care about. Again, focus on coding your service and not the non-functional requirements. Stand on the shoulders of giants. If your core business is not building all of these non-functional requirements, then you shouldn't be spending the majority of your time writing that code. Since we are at CF Summit, Cloud Platforms are designed to do these things for you, whether you're using Kubernetes or Cloud Foundry or a combination of both. They're designed to run and host your service, so you should be able to take advantage of those features. I think the biggest key point here is that if your core business logic and your core service is faulty, none of the things that your Cloud Platform provides is going to be able to fix that for you. If you have to choose where to spend your effort, spending it on the inside of your service is the best place to go. Like I said, we should be spending our time worrying about our service and not the- can you hear that? Okay. That's what it sounds like when your code is bad. One of the other things that people do in order to take care of some of the non-functional requirements or offload the platform functionality out of their service is sidecars. We can create or reuse containers that are designed to take care of these things and just deploy them alongside our app, and again, not have to worry about it. Now that I've got my custom, fully debatable definition of microservice out there, I want to talk about distributed transactions. In a classic distributed transaction, I get a request into my monolith, and my monolith then can create an order, it then reduces the inventory that I have on hand, and then updates some ledger, and this happens transactionally, and if it fails in any one of these steps, it rolls back and everything's great. But since I no longer have a monolith, I'm Cloud native and I'm building microservices the way people tell me I'm supposed to because microservices are the thing. I don't have access to distributed transactions. So what do I do? I distribute my failure across microservices, and I try and do the same transaction across three different services, and as the slide says, this is a pretty guaranteed way to fail, and the problem here is I'm taking a tightly controlled transaction and trying to distribute it where I have no control, and in a microservices world, if one of these fails, I don't have automatic compensation, so I have two choices. I can either build in a whole bunch of complicated code to compensate for transaction failure, or I can not do distributed transactions at all, and it's my strongly held opinion that we should not do distributed transactions at all. There's a better way. So that better way is immutable events and a concept called shared nothing. At the bottom here, there's a link to probably one of the best papers I've ever read by Pat Heland on it's called Life Beyond Distributed Transactions. The idea here is instead of giving my system imperatives, do this, do that, and if this fails undo this, my system reacts to events. So I might have an order accepted event, and then I'll have inventory reserved events, and the ledger might also see an order accepted event, and then when my product is shipped, I get inventory shipped events. And if I cancel an order, there's an order canceled event. I release the inventory from the previously held order, and then the ledger sees an order canceled event. I have in this diagram here, I've got an order service, inventory service, and a ledger service, but there's no transaction. I can still model the real time flow of events through my system, and I can still compensate for failure, but I'm doing it by treating the events in my system as immutable facts. So what this brings up is I now have this list of facts that are things that have occurred in the past in my system. So I've got an order created, a couple of inventory reserved facts, order canceled, and so on. And facts will eventually produce state. So rather than having services that maintain their own state, I have stateless services, and I'm calculating my state based on the list of facts or events that have occurred in the system. So rather than having a transaction that rolls itself back as part of a distributed transaction system, if there's a failure, the failure is an event. And so I can see when that failure happened and I can deal with it accordingly. So the other philosophy that I have here is that being right five seconds from now is better than being wrong right now. And that leads into eventual consistency. The sample application that I have that is somewhat demoable today is a distributed system with a couple of microservices that is designed to model an online store and it has an order service, an inventory service, and a couple other components to it. Basically, it is a event sourcing and CQRS. So there's no distributed transactions. Everything is dealt with in terms of commands that come into my services and the state is calculated based on aggregating the events. There's the durable message broker here is apparently non-durable if you run APT update on Linux the day of your demo. So I wanna take a quick look through some of the code. The first is I have an inventory service and let's see if I can find the stupid file here. This inventory service is a GRPC service. It's not an ASP.NET core service. By show of hands, who's familiar with GRPC? Okay, that's much more than yesterday. Maybe because some of you people were in the demo yesterday. GRPC is a RPC protocol with a binary serialization format on the wire and it runs on top of HTTP too. And one of the reasons, there are a number of reasons why I'm using it but most of it is because this is my service definition and this definition can generate code, it can generate documentation and one of the other benefits that I talked about yesterday is I get bi-directional streaming on this service so I can send and receive data at the same time and the implementation of this service is fairly simple. You just implement the abstract base class that you get from the code generator and you just handle the request and response patterns. So just a quick demo. One of the other things that I get from GRPC is the ability to interrogate the services that I'm running. So you can see that I've got my inventory management service running as well as reflection. And I can also invoke the GRPC service directly from the command line, even though I'm not using Curl or Postman or whatever but whenever I talk to people about using GRPC versus rest the big complaint is I don't have access to Postman, I can't query my service but if you use reflection then any tool written in any language can interrogate your service and invoke all the methods. And who is familiar with the JQ command line tool? Okay, so a couple. JQ lets me take the ugly spam that I just got from my service and format it so that it's legible. In addition to being legible, I can also run queries through JQ so I can filter my results, I can order them and so on. So all of the query power that I get from Postman, I also get from GRPCurl in the command line. And again, like I said, I only had a half hour and this is usually an hour long session with a pretty in-depth demo. So what I wanted to do is try and get through the slides so that I could get to Q&A and looks like I, okay. Looks like I, okay. So the architecture for the application is there's a RESTful API gateway at the front that an application that doesn't speak GRPC can consume. I can either write that API myself or I can use a standard GRPC, essentially a reverse proxy that converts my GRPC methods into a RESTful interface. I have my command service, the create new orders, which submits them to Kafka. Let's just pretend you saw that part of the demo. And then the order management service is responsible for listening to events and inventory and ledger allow me to query the state based on the aggregate of the events in my system. Like I said, don't worry about all the code. It's all sitting in GitHub. You can download it and run it all. So, like I said earlier, not all microservices are RESTful JSON services. I think we can get some benefit from trying to decide upfront whether we want to use REST or something a little more powerful or a little more flexible. By modeling the entities in the flow through our system as immutable distributed activities, we can get a simple set of code to solve a complex problem without having to use explicit distributed transactions. A lot of times in event sourcing, you'll see a whole bunch of complicated strategies for doing materialized views where you're taking your events and then producing some sort of cache of the state. What I found is that's a layer of complexity we don't always need. So, I'll build the system first and then based on the actual usage of the system by monitoring and getting real metrics, then I can decide which parts of the system would benefit from materialized views. Containerize your workloads, that's pretty much a given. And then, finally, microservices is a pattern, not just a framework or a library. So, a lot of people, a lot of the Java folks will equate microservices with Spring Boot and it's not really the analogy we should be making. Spring Boot is an implementation that allows you to build microservices.net core, allows you to build microservices and there are libraries in there that give you some functionality that you need, but microservice is a concept and a pattern and we should try and decouple that from the implementation. I tried very hard to get a logo for the sample application and I still haven't found a good one, so. Okay, so I'd like to open it for questions and we've got a few minutes, but if there is a specific aspect of the code you want me to go through or show or the architecture, please feel free to ask and I'll go through that. No questions? Okay, yeah. Yeah, so the event store that I have or the event broker that I was using for the demo is Kafka. I would have been able to demo creating an order and watching it go through Kafka, but as I said, I ran a software update this morning and that was obviously a terrible idea. Any other questions? Yeah, yeah, so in a situation where if the transaction itself starts and finishes all within the same bounded context of a single service, then you probably don't need to try and expand that out into an event sourcing type thing, but as soon as a transaction needs to span across bounded contexts, the knee-jerk reaction is to have two services talk to the same database so that they can cheat and peek into the status of that transaction. That's obviously a terrible idea, but when you do that, then instead of trying to figure out, well, how can I take the transaction that I used to have and model that as microservices, take a step up higher and figure out what the event flow looks like in the system that generated the original transaction and then that set of events can become the immutable activities that you're in your system and like I said, one of the important parts is being able to model failure as an event. Any other questions? Like I said, all the code is in the GitHub repo here. This all works on .NET 2.0. I've tried it on 2.1 and I didn't have any compilation problems so you should be good to go there and if your system is not my laptop, you should have no problem with the Kafka part of it. All right, well, thanks for coming. Appreciate it. Thank you.