[go微服务-17] gRPC和 Apache Thrift 之间 如何进行选型?

Posted IT技术小屋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[go微服务-17] gRPC和 Apache Thrift 之间 如何进行选型?相关的知识,希望对你有一定的参考价值。

引言


上一课时已经对Go语言原生RPC的使用和具体实现原理进行了详细讲解

推荐使用gRPC

Facebook开源的Thrift框架也是业界较为流行的RPC方案


gRPC简介和使用



[go微服务-17] gRPC和 Apache Thrift 之间 如何进行选型?


[go微服务-17] gRPC和 Apache Thrift 之间 如何进行选型?


服务端和客户端需要依赖共同的proto文件

客户端可以十分方便地发送RPC请求

服务端也可以很简单地建立RPC服务器、处理RPC请求并且将返回值作为响应发送给客户端


[go微服务-17] gRPC和 Apache Thrift 之间 如何进行选型?

定义和编译proto文件

syntax = "proto3";
package pb;
service UserService{
rpc CheckPassword(LoginRequest) returns(LoginResponse){}
}
message LoginRequest {
string Username = 1;
string Password = 2;
}
message LoginResponse {
string Ret = 1;
string err= 2;
}


protoc --go_out=plugins=grpc:. pb/user.proto

客户端的本地定义方法

其方法名、参数和返回值与服务端定义的方法相同

gRPC生成的客户端代码会将请求转换为网络消息发送到服务端


客户端发送 RPC请求

func main(){
serviceAddress := "127.0.0.1:1234"
conn, err := grpc.Dial(serviceAddress, grpc.WithInsecure())
if err != nil {
panic( "connect error")
}
defer conn.Close()
userClient := pb.NewUserServiceClient(conn)
userReq := &pb.LoginRequest{Username: "", Password: ""}
reply, _ :=userClient.CheckPassword(context.Background(), userReq)
fmt.Printf("UserService CheckPassword : %s ", reply.Ret)
}


服务端建立RPC服务

func main(){flag.Parse()
lis, err := net.Listen("tcp","127.0.0.1:1234")
if err !=nil{
log.Fatalf("failed to listen: %v", err)
}
grpcServer := grpc.NewServer()
userService := new(user_service.UserService)
pb.RegisterUserServiceServer(grpcServer, userService)
grpcServer.Serve(lis)
}


type UserService struct{}
func (s * UserService) CheckPassword(ctx context.Context, reqpb.LoginRequest)(pb.LoginResponse, error){
if req.Username = "admin" && req.Password == "admin" {
response := pb.LoginResponse{Ret: "success"}
return &response, nil
}
response := pb.LoginResponse{Ret: "fail"}
return &response, nil
}


Thrift简介


Thrift

由Facebook开源的跨平台、支持多语言的成熟 RPC框架,通过定义中间语言(IDL)自动生成RPC客户端与服务端通信代码,可以在C++、Java .Python、php和Go等多种编程语言间构建无缝结合的、高效的 RPC通信服务


定义和编译Thrift文件


namespace go user
struct LoginRequest {
1: string username;
2: string password;
}
struct LoginResponse {
1: string msg;
}
service User {
LoginResponse checkPassword(1: LoginRequest req);
}


使用thrift工具将上述定义编译,生成对应的go代码


thrift -r--gen go user.thrift


客户端发送RPC请求


func main() {
tSocket, err := thrift.NewTSocket(net.JoinHostPort(HOST, PORT))
if err != nil {
log.Fatalln("tSocket error:", err)
}
transportFactory:=thrift.NewTFramedTransportFactory(thrift.NewTTransportFactory()
transport := transportFactory.GetTransport(tSocket)
protocolFactory :=thrift.NewTBinaryProtocolFactoryDefault()
client := user.NewUserClientFactory(transport, protocolFactory)
if err :=transport.Open();
err != nil {
log.Fatalln("Error opening:", HOST + ":" + PORT)
defer transport.Close()
req :=user.LoginRequest{Username:"admin", Password: "admin"}
res,err := client.CheckPassword(&req)
fmt.Println(res.Msg)
}


服务端建立RPC服务


func main(){
handler := &UserService}//类似上边的gRPC,是一个实现生成代码中接口的函数的结构体
processor := user.NewUserProcessor(handler)
serverTransport, err := thrift.NewTServerSocket(HOST + ":" + PORT)
if err != nil {
log.Fatalln("Error:", err)
}
transportFactory := thrift.NewTFramedTransportFactory(thrift.NewTTransportFactory())
protocolFactory :=thrift. NewTBinaryProtocolFactoryDefault()
server := thrift.NewTSimpleServer4(processor, serverTransport, transportFactory, protocolFactory)
fmt.Println("Running at:", HOST + ":"+ PORT)
server.Serve()
}


对于通信协议(TProtocol)


[go微服务-17] gRPC和 Apache Thrift 之间 如何进行选型?


对于传输方式(TTransport)

[go微服务-17] gRPC和 Apache Thrift 之间 如何进行选型?

对于服务端模型(TServer)

[go微服务-17] gRPC和 Apache Thrift 之间 如何进行选型?

Thrift 框架示意图

[go微服务-17] gRPC和 Apache Thrift 之间 如何进行选型?

gRPC和Thrift的区别和选择

[go微服务-17] gRPC和 Apache Thrift 之间 如何进行选型?

小结


本课时介绍了gRPC和Thrift的整体概念和示例,对二者进行了分析和对比

对比二者,会发现它们缺少了大量的功能

比如:连接池、服务框架、服务发现、服务治理、分布式链路追踪、埋点和上下文日志等


以上是关于[go微服务-17] gRPC和 Apache Thrift 之间 如何进行选型?的主要内容,如果未能解决你的问题,请参考以下文章

手撸golang GO与微服务 grpc

go微服务gRPC

go微服务gRPC

go微服务gRPC

《Go-micro微服务框架入门教程》学习笔记 | gRPC

Go使用grpc+http打造高性能微服务