 On today's Visual Studio Toolbox, Sohrab is going to show us how to build a GRPC service from scratch. Hi, welcome to Visual Studio Toolbox. I'm your host Robert Green, and joining me today is Sohrab Shahadi. Welcome to the show. Thanks, Rob. I'm happy to be here. We're going to talk about GRPC. You've been on on.net talking about it. You've been on Cloud Native talking about it. It's my turn to get you on my show to talk about it. But we're going to take a slightly different approach. We are going to talk about what it is. But I want to approach it from the angle less about the underlying technology and plumbing, and more from I'm a Visual Studio developer. I've been building services for a long time. I've built WCF services, I've built Web API services. Now, this looks like a new way to build services. Why? What does it do? Why? What are its advantages? Then what should I do? Should I convert my existing services? Then how do you actually build one? Because so far, the only demos I've seen, the service has already been built. It turns out, I did not know this until recently, and in 20 minutes, all of our viewers are going to know this too. Did you can actually do this inside Visual Studio, File, New Project, create a GRPC service? That's right. Cool. That's what we're going to do. So why was it invented? So GRPC is a RPC framework, and for as long as I've been alive, people have been trying to make computers talk to each other and invoke methods on some other computer. It lends itself well to distributed systems, things like that. It is a requirement to scale artificially. So GRPC comes from this project that was internally developed at Google called Stubby. Stubby. Right. GRPC is the rewrite slash public version of it. So we chose to build GRPC support, like first-class GRPC support in .NET, because it's one of the most popularly used RPC technologies today. One of the key things to keep in mind is when you are talking with other machines and other computers, not only do you want a rich and robust ecosystem for your language of choice, you also want to be able to interoperate between other language tags. So while we could have picked something like say WCF, which is limited to the .NET ecosystem, good luck getting that to work with a microservice that didn't go running in Kubernetes. So the benefit of GRPC is it's like a fundamentally good protocol, as well as it's popular and adopted by many other languages. So does it lend itself to one type of service versus another? So I could think of a service that you build a web API, a Rustful service to return the weather or the time. I enter a city and I get the time back. Or a lot of WCF services were written to do crowd support for databases, select insert update delete. If I'm doing those types of services, would I use GRPC for those? So GRPC is a low-level protocol, so it doesn't lend itself better to say weather updates than crowd applications for LOB like Epic. It lends itself well to both. There are four fundamental types of calls you can do with GRPC. You have Unary calls, which would be I send a request as a client, to get back a single response. We have both server and client streaming. So I can send as many requests as I want, then get back one final response from the server. Or on the flip side, I can send an initial request and get back multiple responses from the server. It also has support for full bi-directional streaming. So with those primitives, you can pretty much build most applications. So you could do the, just get the single value back or the crud, but it's potentially more optimized for these other scenarios. Is that a true statement? I would hesitate to say that. I would say it depends on your domain and what your application does. If I want the weather and the weather is good for about an hour, there's no point in me asking for it every 10 seconds, no matter how good the streaming protocol is. So do what's best for your application. Okay, but if you want to call a service that tells you number of people that have walked through the door, right? Like I want a service that tells me when the stadium's half full and there's people streaming in, literally streaming in, right? It would be perfect for something like that, right? That sounds like a use case. Okay, all right. Cool, let's build one. All right, so I'm going to hop over to Visual Studio. I'm actually using your computer, so you know there are no hacks going on. To prove that there are no tricks behind the scenes. This is not an internal build. This is my machine running public, latest version of Visual Studio. So we ship JPC templates in the box, right? And so I've gone ahead, I picked JPC. I'm just going to, what's called it, JPC service for toolbox. Okay, I hit the name, but just to disambiguate. So you see the JPC demo. So this actually, the Visual Studio new project dialogue discovers templates installed by the.NET SDK. The ships is part of the SDK, even though today we're focusing on the Visual Studio support and how to do it. If you were using a Mac like I do, then you'd be able to do the same thing, albeit from the command line. Okay, and you could put it in a container I see. Yeah, so let's just keep it simple for now. Yeah, keep it simple, but that's not good to know. And it says something about supporting.NET Core. Right, so the JPC library that we're talking about here is JPC.NET. There's actually another implementation of JPC for.NET. This is one of the original libraries authored by a couple of folks at Google. While they both work, we're going to be focusing on JPC.NET because we think that's the more defined experience. However, this is limited to.NET Core 3.0 and above. So keep that in mind. If you want some interoperability, maybe you need some Xamarin support, you may be forced to take a look at those other libraries. Some of the tooling that I'm going to show you works irregardless of which JPC library you use. It may prod you in the direction of using libraries we think are better, but some of these pieces will work. Okay, cool. So right off the bat, if you're familiar with ASP.NET Core, you would recognize this is an ASP.NET Core application. We have start-up CS, program CS. It looks like a regular ASP.NET application. I do want to bring your attention to this directory here called Protos, right? So in here we have a file called greep.proto. So this is a ProtoBuff file. What is a ProtoBuff? So ProtoBuff is short for protocol buffers. It's the IDL, the Interface Definition Language, used for JPC. So it defines the service and what it's expecting and what it's going to return. Exactly. Okay. So as you can see, let me highlight an area of interest. That's the actual service definition with the RPCs. This is a Unity RPC call. So single request, single response. And you can see it's defined in terms of message types. You'll also see that the message type definitions are contained here. Okay. So see, the way you start with the JPC service is you probably first author your interface definition, right? Once you do that, you want to hook it up into MS build and say, hey, use this to generate stubs that I can use to go write a service or a client, right? So on the service you get these service stubs that you can fill out the implementation for. On the client, you get a full functional client that you can go and invoke calls on. So once we have authored this file, what we go ahead and do is, I'm going to get your attention to this menu. I'm going to go into, right-click on my project, I click Add and there's an option called Service Reference, right? So you can see that this document is already referenced. It says, hey, this was greek.proto. It's a reference to a document and the type of code generation was a server. Because in this project, I'm implementing the service side of it. What we'll do after this is go implement a client as well that actually invokes the service implemented by this, right? Then points to the location. You could easily go point it, create a new proto file and hook it up. If this is the pretty UI over it, if we actually drop down to the project file, you can actually see what's happening. So we're actually linking to this directory proto slash greek.proto, and we're saying generate service. So you can generate only the message types, server, client, or both. So once we've done all that, let's actually go look at our startup. So our program remains pretty much unchanged. We go to startup, you'll see a couple of things. You'll see in configure services, I make a call to add gRPC. You need to do that. Then the other thing in my configure method, and I'm actually building my appfunk out. In my endpoint routing, I have this endpoints are mapped gRPC. We haven't done any reflection magic like we do in the case of MVC, but we do controller discovery. We've suggested that you create a directory called services and put your service implementation in there. But that's just a convention. But what you do need to do is actually register each of these services in your application. Then speaking of this, like I've obviously registered. So I do want to point out one more thing. You do not see any path or URL, because gRPC is an opinionated protocol. So based on my- Because I've been accused of being opinionated, but I don't think it means the same thing. I think it tries to take a lot of ceremony away from you. And in a lot of scenarios, that's extremely helpful because it makes you more productive quickly. Like when I map this in, I didn't have to think about what's the path on which it's going to be served, right? What's the path base? How do I communicate that to a client? As long as the client knows that this is where my gRPC endpoint exists, everything else is built into the protocol. So let's go in and actually look at this service definition. Oh, shoot. Oh, sorry. I realized you didn't have function lock on. Okay. So now we're in the actual service implementation. The greater service. Okay. So one thing you will notice right off the bat is this gRETA base. So there's some of this magic that we skipped over, but when you did the entire gesture in Visual Studio to add a service reference to a prototype and ask it to generate stuff, it actually did some magic and generated stuff. So this actually lives in my object folder. I can go over into this, but this is generated code. Yeah. Okay. So not only do I have generated code for the service, I also have it for the message. So it also contains code on how to serialize DC-alized messages. So when I come over, my experience as a developer is I go to my service definition and I can just override the RPC methods that I want. Let me show you an example of if I hop back over here, let's do this. I'm going to create another RPC. Let's call it say hello to so we don't have any conflicts. All I did is I hit save. Now we have the design time build in Visual Studio happening under the covers and I save. So if I come back over into this file, I'm going to go, do you see this? I do. There it is. So I get say hello to and I already have the override. So that was the integrated design time build experience in Visual Studio. That allows you to be super productive when you're quickly iterating. It knew to do the task hello reply for you. You didn't have to type that sweet. So that's some fun stuff we did. So now, after having looked at all this code, the thing you'd be curious is how do I run this, how to see what's going on. So I'm just going to go ahead and run this project. So this is also a point for us to sanity check, make sure I didn't click around and mess something up. So you ran by. I just hit F5. Okay. Because I noticed there wasn't a run button. Right. So if you look at the logging again, very similar to what we see in ASME.Core says now listening on localhost 5001. Okay. So let me copy that. And is it safe to use this press? It is safe to use edge. Yes, it is. The new edge. Okay. So if you can read what it says here. Well, good news is it talked to it. Yeah. It says communication with JRPC and points must be made through a JRPC client. Okay. Which makes sense, right? I open it in the browser, but this isn't web app. Right. But because we were built on top of ASME.Core, it's just a friendly thing we put in the templates to warn you. So for folks who are trying this, I would highly implore you actually go to this FW link. What we'll do in the rest of the videos walk through how creating a client looks like. But for folks trying it at home, that the tutorials are up to date and they should follow that. Cool. All right. So now that we have this running and we've established that we need a JRPC client, let's actually go through the experience of creating a new project, adding in a client, and then making it run. So there is a run button. Yeah. Okay. I don't know why I missed that. So I'm going to go into my solution. I'll add a new project. We don't need it to do anything fancy. So I'm just going to add a console, who nearly clicked on that VB there for a second. Okay. So far everything is good. Now we're going to make use of that service reference experience that I spoke about. Because it is a service and you want to reference it. So I'm going to go ahead and service reference. Because it's in the same solution, it should know about it? No. So you have to explicitly point. Okay. So I have to point to the proto file. I just want to show you one thing before I click on this. You see there's also URL. I do. So if your company publishes your proto files at a central location, or you're taking a dependence on somebody else's service, like you have a microservice team and you need to call somebody else's service, you can actually point it to URL, and Visual Studio will keep the URL handy and then you can refresh it if need be. Okay. So I'm actually going to point. So we've got to walk up this directory and then in the proto's directory. So again, this is convention based. If you want, you can move it as a solution item that both the project, excuse me, utilize. Yeah. Point it at that. And then remember how I mentioned you can do any of these. Since we're going to use this as a client, let's actually go ahead and generate a client. So we need a couple of packages. So the tooling is intelligent. It adds the service reference as well as brings in the package dependency. So it says this is good. Let's actually go ahead and look at the CS projects to see what exactly happened. So you can see it brought in Google Proto above, GRPC, Netline Factory, and GRPC Tools. Okay. So this is everything that we need to actually make a client call, right? So should we go ahead and write some code to actually make a client call? Yeah. So the first thing we need is a channel. So think of channel as the underlying connection. So I'm going to, I'm using the using bar syntax because it's really nice. And I believe we have a static helper method that hangs off of, oops. It's always hard getting used to somebody else's keyboard. Okay. So I might not have gone into great detail, but I know the service is listening on localhost 5001. At least that's what we configured it to, right? So let's do that. And now once we have a channel, we can new up a client and give it the channel. So I will do, and now we pass it the channel. And now once we have a channel, we can actually, let me show you what hangs off the channel. So we can actually invoke, like HelloAceing. You see a HelloAceing 2 as well because we've added it to the prototype. Obviously it's not implemented. And then let's just go look at this method definition, right? What do we have to pass to HelloAceing? We need to pass it a request, right? It needs a Hello request. Okay. And that was, if we go back to our message file just to remind ourselves, Hello request just took a name. So I'm gonna jump back over to my code. Before I do that, I'll do, oops. It's not finding Hello request. There you go. And let's do Robert, if I can spell your name. All right. And then I should just be able to do a call, make this call. This actually is an async. I mean, we generate both the synchronous and asynchronous methods. It's a recommendation that you do this. And so it's probably gonna look like, oops. That also means I can use the. In the semicolon at the end. Yes. C sharp. Is it eight or 7.2 has async main? So that makes, oops. Yeah. Yeah. The challenges of using someone else's machine. All right. Well, that's why I gave you a mouse. Talking to someone who uses a Mac. And I'm just gonna put in a, oops. Console.read key at the end. So it just doesn't close on me. All right. Okay. So things look good to me. You can go ahead and build. All right. So let me go ahead and, so this should start debugging the service. All right. Now we also want to launch the client. Let me go into the client. All right. There we are. And here you should see the request finished. Executed endpoint. Greta Greta say hello. This is also the thing I was talking about. Like how the URLs are convention based. So it's package name, service name, and then RPC method. I didn't have to, you know, figure all that out. It's worked for me. The other thing which might be like worth looking at is just remind ourselves, right? We're actually calling a method from one application into another one. Right. And we're able to call it as if it was in the same thing. And that's the goal of RPC if you will. So I can actually go ahead and, you know, maybe say put a breakpoint in here. As well as put a breakpoint in my service. Just to show you what that feels like. Okay. So I go ahead and run this again. And let me debug this as well. If you're doing more development, you can use Visual Studio and set multiple startup projects. This is just since we did a couple of executions. So you can see, I hit the breakpoint on my client. Yep. If I hit continue, you should see now I hit the breakpoint on my server. All right. So it's a, you know, a nice experience for developing services. So, you know. And then now that this is perfect, it's been tested rigorously. We're ready to go. We just publish it to Azure and we move on, right? There are certain challenges there. So while GRPC builds on existing technologies like Protobuf and HTTP2, it actually uses, let's say, the full gamut of features supported by HTTP2, something that not all HTTP2 implementations support today. And which means if you're running anywhere in a hosted service where you go through a proxy or something like that, you really need to make sure that everyone up into that point supports full fidelity HTTP2. Okay. So we're currently working closely with the Azure team. You know, we hope to get there soon. But it is a change because it requires a change to the kernel more HTTP driver in Windows, like HTTPSys, and then we have to work our way up the stack. So I think takeaway for people is we're working on it, but it is a big project and I can't tell you when it'll be done. All right, fair enough. But you can deploy it to Azure Kubernetes service. Right, okay. It's just not Azure App Service because they have some proxying going on in front for you. Okay, great. So we accomplished what we wanted to accomplish. We reviewed what GRPC is, talked a little bit about some of the scenarios, and then most importantly, saw that right now you can build one from File New Project and Visual Studio. Awesome. I do want to show one more thing because you have that voice like we're about to wrap up. So. That is my, we're about to wrap up voice. But. I just want to go over to the docs and point out that we have docs for a more procedural app. So this has a full introduction and tutorials. Nice. It covers a lot of things, you know. Practices, patterns, things like that. So please check out the extensive documentation. Absolutely. We'll put a link to that in the show notes. Thanks so much. All right, thank you. Hope you guys enjoyed that and people should try these out and start experimenting with them, get used to them because this is coming, this is here, and this will get more and more powerful. I mean, you did say coming, but these are production quality libraries that have been shipping as, with a non-previewed moniker as you will, since 3.0. So we're about like more than six months in, I guess. All right. So this is here. This is a viable option. Absolutely. People should check it out. Thanks. And we will see you next time on Visual Studio Toolbox.