Hi Everybody,
Today we will see how to build gRPC based micro-services from scratch and how to communicate with each other.
In this example we will be writing two gRPC micro-services and RPC2 will communicate to RPC1 and vicer-versa can be extended later. gRPC requires at-least the basic knowledge of Protobuf, In order to deep dive into this example I suggest you to go through the basics of protobuf and gRPC here (in case if you are new to gRPC): https://grpc.io/docs/guides/
Now all set let us create our first micro-service in Go Lang and call it grpc_comm_1.go
Today we will see how to build gRPC based micro-services from scratch and how to communicate with each other.
In this example we will be writing two gRPC micro-services and RPC2 will communicate to RPC1 and vicer-versa can be extended later. gRPC requires at-least the basic knowledge of Protobuf, In order to deep dive into this example I suggest you to go through the basics of protobuf and gRPC here (in case if you are new to gRPC): https://grpc.io/docs/guides/
Now all set let us create our first micro-service in Go Lang and call it grpc_comm_1.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"net" | |
"os" | |
"os/signal" | |
"syscall" | |
"golang.org/x/net/context" | |
"google.golang.org/grpc" | |
log "github.com/sirupsen/logrus" | |
pb "rpc1/main/pb" | |
) | |
const servicePort = 17009 | |
type server struct{} | |
func (s *server) GetRpc1Msg(ctx context.Context, in *pb.RequestParams) (*pb.Rpc1Reply, error) { | |
return &pb.Rpc1Reply{ Rpc1Msg: "Message From GRPC1-->COMMUNICATION SUCCESS!" }, nil | |
} | |
func main() { | |
customFormatter := new(log.TextFormatter) | |
customFormatter.TimestampFormat = "2006-01-02 15:04:05" | |
log.SetFormatter(customFormatter) | |
//De-register the service on exit | |
signals := make(chan os.Signal) | |
signal.Notify(signals, syscall.SIGTERM) //Notify when app is terminated | |
signal.Notify(signals, syscall.SIGINT) //Notify when app is interrupted | |
// Shutdown channel to notify the running go-routines to stop when main exists | |
shutdownChan := make(chan bool) | |
go ShutdownHook(signals, shutdownChan) | |
log.Info("GRPC1 started!") | |
laddr := fmt.Sprintf(":%d", servicePort) | |
lis, lisErr := net.Listen("tcp", laddr) | |
if lisErr!= nil { | |
os.Exit(1) | |
} | |
s := grpc.NewServer() | |
pb.RegisterRpcCommunicator1Server(s, &server{}) | |
if err := s.Serve(lis); err != nil { | |
log.Fatalf("failed to serve: %v", err) | |
} | |
} | |
// ShutdownHook is called when service is stopped or aborted based on the OS signals | |
func ShutdownHook(signals <-chan os.Signal, shutdownChan chan bool) { | |
select { | |
case <-signals: | |
//Go the OS interrupt signal | |
log.Println("Deregistering the service") | |
//Stop all the routines listening to shutdown channel | |
close(shutdownChan) | |
os.Exit(3) | |
} | |
} |
Similarly let's create the second gRPC and call it grpc_comm_2.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"net" | |
"os" | |
"os/signal" | |
"syscall" | |
"golang.org/x/net/context" | |
"google.golang.org/grpc" | |
"time" | |
log "github.com/sirupsen/logrus" | |
pb "rpc2/main/pb" | |
pbRpc1 "rpc2/main/pb/rpc1" | |
) | |
const ( | |
servicePort = 17007 | |
rpc1Address = "localhost:17009" | |
) | |
type server struct{} | |
func (s *server) GetRpc2Msg(ctx context.Context, in *pb.RequestParams) (*pb.Rpc2Reply, error) { | |
return &pb.Rpc2Reply{ Rpc2Msg: "Message From GRPC2-->COMMUNICATION SUCCESS!" }, nil | |
} | |
func main() { | |
customFormatter := new(log.TextFormatter) | |
customFormatter.TimestampFormat = "2006-01-02 15:04:05" | |
log.SetFormatter(customFormatter) | |
//De-register the service on exit | |
signals := make(chan os.Signal) | |
signal.Notify(signals, syscall.SIGTERM) //Notify when app is terminated | |
signal.Notify(signals, syscall.SIGINT) //Notify when app is interrupted | |
// Shutdown channel to notify the running go-routines to stop when main exists | |
shutdownChan := make(chan bool) | |
go ShutdownHook(signals, shutdownChan) | |
log.Info("RPC2 Started") | |
getMessageFromRpc1() | |
laddr := fmt.Sprintf(":%d", servicePort) | |
lis, lisErr := net.Listen("tcp", laddr) | |
if lisErr!= nil { | |
os.Exit(1) | |
} | |
s := grpc.NewServer() | |
pb.RegisterRpcCommunicator2Server(s, &server{}) | |
if err := s.Serve(lis); err != nil { | |
log.Fatalf("failed to serve: %v", err) | |
} | |
} | |
func getMessageFromRpc1(){ | |
// Set up a connection to the server. | |
conn, err := grpc.Dial(rpc1Address, grpc.WithInsecure()) | |
if err != nil { | |
log.Fatalf("did not connect: %v", err) | |
} | |
defer conn.Close() | |
c := pbRpc1.NewRpcCommunicator1Client(conn) | |
ctx, cancel := context.WithTimeout(context.Background(), time.Second) | |
defer cancel() | |
r, err := c.GetRpc1Msg(ctx, &pbRpc1.RequestParams{}) | |
if err != nil { | |
log.Fatalf("could not communicate: %v", err) | |
} | |
log.Info(r.Rpc1Msg) | |
} | |
// ShutdownHook is called when service is stopped or aborted based on the OS signals | |
func ShutdownHook(signals <-chan os.Signal, shutdownChan chan bool) { | |
select { | |
case <-signals: | |
//Go the OS interrupt signal | |
log.Println("Deregistering the service") | |
//Stop all the routines listening to shutdown channel | |
close(shutdownChan) | |
os.Exit(3) | |
} | |
} |
Now both services are ready first run the service grpc_comm_1.go and then following that run grpc_comm_2.go and in the terminal you can see the output displaying the services interacting with each other.
I have hosted the complete source code in git: https://github.com/harishp8889/haritechtalk/tree/master/go-lang/GRPC
clone the GRPC folder which has all the code explained in the above example along with a gRPC client for testing purpose.
I have hosted the complete source code in git: https://github.com/harishp8889/haritechtalk/tree/master/go-lang/GRPC
clone the GRPC folder which has all the code explained in the above example along with a gRPC client for testing purpose.
No comments:
Post a Comment