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.
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: