Hello Devs! Recently I started learning Protocol buffers & gRPC, and gotta tell you, this tech is amazing!
THIS POST REQUIRES A PRIOR KNOWLEDGE OF GRPC, GOLANG, AND PYTHON
Follow along with this post to get a hands-on demo on how to establish communication between different microservices that are running on different codebases using gRPC.
Find the code for this post here.
Directory Structure
fastapi-and-golang-grpc-demo
|-fastapi
|-app
|-env
|-requirements.txt
|-protobufs
|-auth.proto
|-main.go
|-Readme.md
|-go.mod
Create the auth protobuf file
Open the auth.proto
file on your favourite code editor, and add the following code to it
syntax = "proto3";
package auth;
option go_package = "auth.utils/auth";
message AuthenticationRequest {
string token = 1;
}
message AuthenticationResponse {
int64 user_id = 1;
bool token_valid = 2;
}
service Auth {
rpc Authenticate (AuthenticationRequest) returns (AuthenticationResponse);
}
Read more about protocol buffers here.
Add the Go service
1. Initialize the go application with
$ go mod init auth-ms
2. Generate the gRPC code
$ protoc --go_out=. --go-grpc_out=. protobufs/auth.proto
3. Update the dependencies
$ go mod tidy
4. Let's create our gRPC server for golang, add the following code in the main.go
file
package main
import (
"context"
"flag"
"fmt"
"log"
"net"
pb "auth-ms/auth.utils/auth"
"google.golang.org/grpc"
)
var (
port = flag.Int("port", 50051, "port to run the server on")
)
type server struct {
pb.UnimplementedAuthServer
}
// extend the rpc service created in auth.proto
func (s *server) Authenticate(ctx context.Context, req *pb.AuthenticationRequest) (*pb.AuthenticationResponse, error) {
token := req.GetToken()
log.Printf("Received: %v", token)
// add some logic to verify token
return &pb.AuthenticationResponse{UserId: 1, TokenValid: true}, nil
}
func main() {
flag.Parse()
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
if err != nil {
log.Fatalln("Unable to start the server on port", *port)
}
grpc_server := grpc.NewServer()
pb.RegisterAuthServer(grpc_server, &server{})
log.Println("Started server at", lis.Addr())
if err := grpc_server.Serve(lis); err != nil {
log.Fatalln("Failed to start server at", lis.Addr())
}
}
5. Start the gRPC server and keep it opened
$ go run main.go -port 8080
2022/11/06 16:26:39 Started server at [::]:8080
Add the FastAPI Service
1. Install the dependencies
$ pip install fastapi uvicorn grpcio-tools~=1.30
2. Generate the gRPC code
$ cd ./fastapi/app/
$ python -m grpc_tools.protoc -I ../protobufs --python_out=. --grpc_python_out=. ../protobufs/auth.proto
3. Create the FastAPI server
from fastapi import FastAPI
import grpc
from compiled_pb.auth_pb2_grpc import AuthStub
from compiled_pb.auth_pb2 import AuthenticationRequest
app = FastAPI()
@app.get("/token/verify/")
def verify_token(token: str):
# gRPC client for making RPC calls to the server
channel = grpc.insecure_channel("localhost:8080")
client = AuthStub(channel)
request = AuthenticationRequest(token=token)
response = client.Authenticate(request)
data = {
"user_id": response.user_id,
"is_token_valid": response.token_valid
}
return data
4. Start the FastAPI sever
uvicorn main:app --host 127.0.0.1 --port 8000 --reload
INFO: Will watch for changes in these directories: ['/home/ankit/practice/golang_gRPC/fastapi/app']
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [8652] using StatReload
INFO: Started server process [8654]
INFO: Waiting for application startup.
INFO: Application startup complete.
Now, go to, http:127.0.0.1:8000/docs and hit the, /token/verify/
route.
VOILÀ, As soon as you hit the api request, there will be an internal RPC call to the go gRPC server.
Happy Coding!😊😇
Top comments (0)