gRPC Golang | Build a Unary Service Method - Part 1

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey what's up everybody my name is moss and in this video i'm going to give you a quick introduction to grpc using the go programming language grpc is google's implementation of the rpc protocol and in this video we're going to write a very simple rpc service using grpc and i'll walk you through implementing a unary grpc service method in later videos we'll expand our grpc service definition to include additional service methods before we get started though you should have completed the prerequisites i expect that you're already somewhat familiar with the concept of remote procedure calls in this tutorial i'll be using protocol buffers so i expect that you already have proto-c installed on your machine in addition to proto-c you'll also need to install the proto-c plug-ins that allow proto-c to automatically generate code in the go programming language in order to fulfill the installation requirements i've linked to a quick start guide in the video description below if you haven't already go ahead and grab a coffee and let's get started okay so first i want to give a little context around the service that we're about to write it's going to be a very simple user management service where a client can send a request to the user management service to create a new user and the user management service will create that user and essentially send the created user details back to the client the initial functionality of the user management service will be limited to just creating users but in future videos we'll expand that functionality to include other service methods so now let's take a look at the directory structure of the user management service in the project's root directory i have three sub directories the first is user management and inside of user management will store our service definition inside of the proto file and we'll also store the protobuf files that are automatically generated from compiling this protofile using proto-c in the user management client directory we will store the client code and then in the user management server directory we will store our server code and the first thing that i want to do before writing the service definition is initialize a new go module so i'm going to open up my terminal here and i'll say go mod init example.com forward slash we'll call it a go user management grpc so now we can begin writing the service definition in the user management proto file which i already have open and inside of the proto file i'll first declare the syntax as usu using proto three so we'll be using version three and then we're going to declare the user management package and then i'm going to specify an option go package is equal to the name of my module so this is going to be example.com forward slash go user management grpc semicolon go user management grpc and after specifying that option we can start defining the service so i'm going to say service user management and the user management service will have for now only a single service method and that service method will be for creating new users and to declare that service method i'll just say rpc and then i'll call it create new user and then we need to specify the input for the service method and the input is going to be a new user and a new user is just going to be a message type that contains that new user's details specifically we're going to include name and age of that user then we need to specify what this service method returns when it gets a create new user request so what it should return is the generated users details which will include the name and age but also include a user id that is generated by the server and we'll define that as user and close out the service method so in the service method we've defined new user as input and user as the output of the create new user service method but we haven't actually defined new user or user so to do that we need to define a new message in this service definition and the first message that we will define is new user and as i mentioned before a new user will only contain a couple of details about the new user specifically it will contain a string which is the name of the user and then it will also include the age of the user and we'll define that as a 32-bit integer and then the last message that we need to define is the user message so i'll define a new message down here and we'll call it user and this will also contain the name of the user as well as the age and then what we'll do on the server side is we'll generate a random id uh essentially representing that user's unique id uh id in the database okay so this will also be a 32-bit integer and we'll call it id and now that we've defined new user and user messages that basically completes our service definition and remember that this uh this create new user service method is an example of a unary service method where the server receives a single request and returns a single response and with our service now defined we can generate the protobuf files using the proto compiler program so in my terminal i'm going to invoke protoc along with several uh uh several options and the first option is going to specify the uh out directory of the first protobuf file and that's that option is going to be dash dash go underscore out equals and then we'll specify the user management directory actually we'll we'll specify current directory because we're going to specify a second option that will generate the files relative to the source and the source being the user management dot proto file okay so the second option here is going to be go underscore opt equals paths equal source relative and then we'll also specify for the second protobuf file the grpc protobuf file we'll specify the out directory for that file as well by using dash dash go grpc underscore out equals current directory and then we'll specify dash dash go grpc underscore opt equals paths equal source relative okay and then finally we just need to specify uh the uh the directory where the protofile is stored okay and i got an error from from that command so it looks like i'm missing a semicolon so let's take a look and i'm missing a semicolon after declaring the syntax okay and then i'm also missing a semicolon after line five as well and i just noticed that i think this um this isn't declared correctly so these should be go underscore user management underscore grpc okay so let's let's try that see if it generates the files correctly and it looks like it did generate the protobuf files you can see under the user management folder now we have a user management underscore grpc.pb.go and we also have a usermanagement.pb.go the usermanagement.pb.go file is responsible provides the logic for serializing and unserializing the the messages that we defined in the service definition in the user management underscore grpc protobuf file includes the generated client and server code that we need to implement in our own client and server programs so once we've generated these protobuf files we can then begin writing our client and server code to implement the functions that we defined in the proto service definition file so let's first start by writing the user management server and i've already created a file for the user management grpc server it's called user management underscore server dot go and i've placed that under the user management underscore server subdirectory i'll navigate to the user management server file and we will define package main and then we'll begin our import statements so we're going to import context we'll import log then we'll import math rand so that we can generate random integers that will be used as the user ids and then we'll import net after that we'll import the protobuf module and that's going to be example.com go hyphen user management hyphen grpc forward slash user management and the final module will be grpc so that will just be dot golang dot org forward slash grpc and after our import statement we're going to set a single constant variable so i'll set that now and that will be the port that the grpc server is going to run on so port equals in this case we'll set it to a very high port number 50 051 and after defining the port we'll then define a new type and this type is going to be called user management server and inside of the user management server we will embed uh protobuf unimplemented user management server so this user management server is our implementation of the grpc service and to register this type with grpc we have to embed the unimplemented user management server inside of the type and besides that we don't really need to do anything else with the user management server so we can begin defining our service method that we defined in the proto file remember in the proto file we defined this rpc service method create new user so now we're going to implement that as a receiver function in the user management server file so here i will define a new function with a receiver pointer of type user management server and it will be called create new user and it will take as input a context as well as a protobuf new user okay just like we defined in the proto definition the service definition the input is a new user a protobuf new user okay and then as we define in the service definition it will return a pointer to a protobuf user and an uh an error and the first thing that we're going to do in this function is simply log the name of the new user that we received from the client and to do that i'll invoke log dot printf and then we'll say received and then we will reference the input protobuf new user and we'll invoke one of the auto-generated functions in this case we'll invoke get name which will return the name of the input new user okay so this will return this should return the name of the new user that was passed to us by the client the next thing we want to do is define a new variable and we're going to call it user underscore id and it'll be of type int 32 and we're going to generate a random integer and it will be assigned to that user as the user's unique identifier okay so invoke rand dot int and then we'll say out of a thousand just to make it sort of unlikely that we'll have a collision with another user id in this small use case and then i'm going to cast this as a 32-bit integer and then finally we will return a protobuf user and we'll define it in line here so i'm going to reference the address and then we'll say pb.user and the first attribute that we have to define is the name of the user and we'll actually just reference the input the name of the input new user so this is going to be in dot get name and then we'll define the age and again we can reference the input protobuff new user so i'm going to say in dot get age and finally we'll set the user id which was generated by the server so this is going to be id and then user underscore id and then we'll also return nil and that's all we really need inside of our create new user function so we can define our main function so i'm going to go down here and define a new main function and the first thing that we're going to do in the main function is utilize the net.listen uh function to begin listening on the uh on the port that we specified up here uh thousand fifty one okay so i'll define two new variables and then i will invoke net.listen and then pass in the port then we'll check if net.listen returns an error so if uh error is not equal to nil we will log fatal message along with the air and after we check the error we will define a new variable s for server and we will invoke the new server function from the grpc module so i'm going to say grpc dot new server and after we initialize this new server we are going to register the server as a new grpc service okay and to do that we'll invoke protobuf dot register user management server and we're going to pass in s and then we'll also pass in the address to the user management type and then we will log that the server is listening on localhost so i'm going to do log printf and then server listening at lis dot address and finally we'll start the server by invoking s dot serve so i'll say if error equals s dot serve and error is not equal to nil then we'll log a fatal message here and that wraps up all of the code that we need to write for our grpc server and now we can go ahead and write the client the client code so i'm going to navigate to the user management uh underscore client file and the first thing that we're going to do is define package main and then we will define our imports so imports and then first will be context and then log we'll also import time and then we'll import our protobuf module so that'll be pb and then i'll just copy it from the server here and actually you know what we'll copy that entire lines 9 and 10 there since they'll be the same and after we define the imports we'll set a new constant variable and this is going to be the address of the grp uh the grpc server which will be posted at localhost and then port 5051. and after defining that constant we can begin writing the main function so this is going to be funk main and the first thing that we're going to do in the main function is dial a connection to grpc server so i'm going to define two new variables here connection and error and i will invoke the grpc function dial and we'll pass in first the address of the server and then we'll specify uh insecure connection so insecure and then uh grpc dot with block okay and the with block option simply means that uh this function will not return until the connection is made so this will be a blocking call to dial we'll then check if there was an error so if error is not equal to nil log.fatal did not connect error and then we will defer connection close and now using that connection we'll create a new client we'll call it c equals protobuf dot u new user management client okay and we'll pass our connection to that function after that we'll define a new context and we'll invoke context with timeout and we will invoke context dot background and then time in seconds all right and then we'll defer cancel and then what we'll do is hard code a couple of new users that we will provide as input to the create new user function for our grpc service so i'm going to first define a new users map and i'll invoke make and then map with a key of type string and a value of uh 32-bit integer and then let's create the uh the users inside of this map so the first user will be alice and we will set their age to be 43 and then the second user will call bob and their age will be 30. and once we define those new users we'll then call to create new user function by looping over the new users map so i'll say for name and age in range new users i'm going to define two variables here r for the response from the grpc server and then error equals client dot create new user and then we'll pass in the the contacts and then we'll pass in the address of a new protobuf new user okay and then the name will be the name key from the map and then age will be the value from the map after we call the function we'll check if there is an error so if error is not equal to nil we'll log log.fatal f could not create user and then error otherwise if there wasn't an error then we'll print the user details that we received from the grpc server to the console using log okay so i'll say log.print f and then i'll actually use backtick so that this can be a multi-line statement user details and then name and that'll be a string age and then id okay and then we'll pass in the response so we'll say r dot get name so r should be a user that was passed back that should be the user message that was passed back from the server remember that in the uh proto protofile we defined the return type to be of type user a user message right so we should get back the name age and then the generated id of the user okay so i'm going to reference i'm going to invoke the get name function of that user and then i'll also invoke the get age and then finally we'll invoke get id and set these like that okay and then i'll also do a back tab here okay so this prints out correctly and that should be all we need for our client code so let's first um install the modules that we imported in the server and client code and then we'll run the program so in the terminal i'm going to invoke go mod tidy and it's going to download all the packages uh all of the modules that we imported in our code and the first program that we want to run is of course the grpc server so i'm going to invoke go run and then user management underscore server and then user management server and then let's run the program and it looks like it's working correctly it says server listening at uh localhost 5051. and in a second terminal i'll invoke the client program so i'll open a a second terminal and i will say go run user management client and then the client program and let's see if this runs correctly and it looks like i have a syntax error on line five so let me take a look here and i it looks like i imported grpc here at the top and then i also added an s there for the import statement which was unnecessary okay so let's try and rerun that client program again and see what happens this time it looks like the client ran and if i expand the terminal out i get the user details message back from the grpc server as we intended and it prints out uh that new user's details including uh the user's id so the id of the first user alice is 81 and then we have 887 for new user bob so as you can see it's not too difficult to set up a simple grpc service in our case we only have a single unary service method but we could expand this user management serv service a lot further and i'd like you to brainstorm uh additional service methods that we could create for this user management service because in future videos that's exactly what we're going to do we're going to expand the functionality of this user management grpc service i hope you enjoyed this video and that you learned something following along with the tutorial and if you did please consider throwing a like on the video and subscribing to the channel for more videos like this i'd also like to point out that all the code that we wrote today is available in a github repo that i've linked in the video description below hopefully i'll see you in the next video and thanks for watching
Info
Channel: Tech and Beyond With Moss
Views: 6,693
Rating: undefined out of 5
Keywords: golang tutorial, golang grpc tutorial, grpc golang, grpc tutorial, protobuf tutorial, go grpc server, golang grpc, go grpc, grpc go, go lang, grpc vs rest, golang crud, golang microservices, golang grpc microservices, golang microservices grpc
Id: YudT0nHvkkE
Channel Id: undefined
Length: 29min 47sec (1787 seconds)
Published: Fri Jul 09 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.