+3

[Phần 1] Deep dive GRPC by Golang

Giới thiệu

Nội dung của series này sẽ giải thích, và đi sâu vào Grpc và sẽ thử cài đặt một vài mô hình đơn giản bằng Golang. Đây cũng như là một phần mình vừa tìm hiểu vừa viết lại để ghi nhớ cũng như các bạn có thể tham khảo để có thể biết về công nghệ này 😇

Nội dung

Hiểu cơ bản về Grpc là cái gì 😁

RPC (Remote Procedure Call) như cái tên thì mình có thể hình dung được phần nào. Thì kết quả sau khi mà mình setup tất cả mọi thứ về grpc là ở phía client sẽ có một cái stub , stub này sẽ có một vài function cho mình gọi vào (tạo cảm giác là mình chạy phần code đó tại client mặc dù là code đó được implement ở server). Đương nhiên đó là cách mà giúp cho người dùng dễ sử dụng thôi chứ cách thức hoạt động sẽ như sau.

image.png

Khi mà clien gọi vào thì sẽ có 1 cái protocol (protocol buffers) để có thể serialized và deserialized tức là chuyển từ dạng struct sang bytes và ngược lại. Cũng khá giống với http nhỉ 😁. Nhưng Grpc có một vài cơ chế mạnh mẽ hơn nhiều mình sẽ nói ở phần sau 😁

Đến đây các bạn có thể tìm hiểu sơ protocol buffer là cái gì? https://protobuf.dev/

Cài đặt

Thôi mình sẽ giao tiếp với nhau nhiều bằng code có vẻ sẽ hợp lý hơn 😄. Mỗi khi mình nói về một khái niệm nào đó thì mình sẽ tiếp tục code vì vậy lượng kiến thức của 1 bài viết của mình sẽ không nhiều tuy nhiên sẽ có phần code để x10 sử hiểu luôn 😅

Thì như nói ở trên thì có 1 thứ gọi là protocol buffer giải thích sơ thì nó giống như là một cái định nghĩa về service của mình. Request gồm những field nào, response sẽ có những gì balabala...

syntax = "proto3";

option go_package = "go_fundamental/grpc/helloworld"; // this field is using when generate to Go code, it is the package of this service

package helloworld;


// The greeting service definition. Defines all of the function signatures that the server will implement.
service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

Service này khá đơn giản nhỉ chỉ đơn giản là gọi SayHello(name) thì sẽ nhận được 1 cái message

# this command using to generate to Go code from .proto file
$ protoc --go_out=./code_gen --go_opt=paths=source_relative --go-grpc_out=./code_gen --go-grpc_opt=paths=source_relative helloworld.proto

Tiếp theo thì sẽ đến phần Server phần này chỉ đơn giản là cài đặt handler để reponse khi client gọi vào

package main

import (
	"context"
	"fmt"
	helloworld "go-fundamental/grpc/code_gen"
	"net"

	"errors"

	"google.golang.org/grpc"
)

type server struct {
	helloworld.UnimplementedGreeterServer // this is a must add	mustEmbedUnimplementedGreeterServer() function, you can try remove this line and see the error
}

func newServer() *server {
	return &server{}
}

// SayHello implements SayHello method from GreeterServer
// this function will be called when client call SayHello method
// it will reply with `Hello + name`
func (s *server) SayHello(ctx context.Context, in *helloworld.HelloRequest) (*helloworld.HelloReply, error) {
	return &helloworld.HelloReply{Message: "Hello " + in.Name}, nil
}

// main function will create new server and run it
func main() {
	server := newServer()

	grpcServer := grpc.NewServer()
	helloworld.RegisterGreeterServer(grpcServer, server)

	listen, err := net.Listen("tcp", ":8080")
	if err != nil {
		panic(errors.New("cannot create listener" + err.Error()))
	}

	fmt.Println("Server is running on port :8080")
	grpcServer.Serve(listen) // grpc just serve at specific endpoint
}

Tiếp theo, sẽ đến phần client, nhiệm vụ của client là gọi vào server để lấy respone

package main

import (
	"context"
	helloworld "go-fundamental/grpc/code_gen"

	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
)

func main() {
	cred := insecure.NewCredentials() // this cred is used for testing purpose, it will not check the server's certificate
	client, err := grpc.NewClient("localhost:8080", grpc.WithTransportCredentials(cred))
	if err != nil {
		panic("cannot create conn to localhost:8080" + err.Error())
	}

	greeterService := helloworld.NewGreeterClient(client)

	res, err := greeterService.SayHello(context.Background(), &helloworld.HelloRequest{Name: "John"})
	if err != nil {
		panic("cannot call SayHello" + err.Error())
	}

	println("Message: ", res.Message)
}

Bắt đầu bằng vài dòng code vậy thôi, để hiểu Grpc là cái gì. Ở những phần sau sẽ đi vào những tính năng sau nữa thì sẽ đi vào code implement của Grpc

Tóm tắt

Hiểu cơ bản, và cài đặt được một mô hình client-server cơ bản giao tiếp với nhau qua Grpc Repo: https://github.com/phanquocky/go-fundamental/tree/main/grpc/grpc-basic Đừng quên cài đặt lại mô hình trên nhé 😅. Hẹn ở những phần sâu hơn

Ref:


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí