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)