go rpc实战
什么是rpc以及rpc的原理就不加以阐述了,wiki-rpc对其进行了说明。本文 以登录过程为例,使用go作为开发语言,使用grpc库实现了登录接口。具体过程及代码如下所示。
环境准备
- 在
app的同级目录创建appGoPath目录,在goland的File->Settings中配置GOPATH为appGoPath目录所在路径,然后执行下列命令准备grpc环境go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28 go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2 - 创建目录:
app/cmd/componentTest/pb,存放登录相关的rpc相关的文件 pb目录下创建登录服务的grpc服务文件login.protosyntax = "proto3"; package login; option go_package = "../pb"; message LoginRequest{ string username=1; string password=2; } message LoginResponse{ int32 code=1; string msg=2; } service LoginService{ rpc Login(LoginRequest)returns(LoginResponse); }pb目录下创建build.sh文件,增加如下内容protoc --go_out=. --go_opt=paths=source_relative \ --go-grpc_out=require_unimplemented_servers=false:. --go-grpc_opt=paths=source_relative \ login.protorequire_unimplemented_servers=false作用: 在LoginServiceServer中不生成mustEmbedUnimplementedLoginServiceServer接口- 在
pb目录所在路径下执行build.sh文件,会自动生成以下两个文件login.pb.gologin_grpc.pb.go
- 生成的上述两个文件在goland中提示
Cannot resolve symbol 'protobuf',使用goland的Sync dependency of机制进行同步即可 - 在
app/cmd/componentTest目录下创建test目录,创建rpc_login_test.go文件,添加代码如下:package test import ( "context" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "log" "app/cmd/componentTest/pb" "net" "os" "os/signal" "syscall" "testing" "time" ) type LoginServiceServerImpl struct{} func (l LoginServiceServerImpl) Login(ctx context.Context, request *pb.LoginRequest) (*pb.LoginResponse, error) { username := request.Username password := request.Password if username == "leebai" && password == "123456" { return &pb.LoginResponse{ Code: 200, Msg: "success", }, nil } else { return &pb.LoginResponse{ Code: 201, Msg: "fail", }, nil } } func StartRpcServer() { s := grpc.NewServer() pb.RegisterLoginServiceServer(s, new(LoginServiceServerImpl)) port := ":8081" listener, err := net.Listen("tcp", port) if err != nil { log.Printf("listen port %s failed,err=%v\n", port, err) } s.Serve(listener) } // TestRpcLoginService 启动Rpc登录服务 func TestRpcLoginService(t *testing.T) { go StartRpcServer() ch := make(chan os.Signal, 1) signal.Notify(ch, os.Interrupt, syscall.SIGTERM) exitCode := <-ch log.Printf("Exit Code:%v", exitCode) } // TestRpcClientLogin Rpc登录客户端,连接启动的Rpc登录服务,发送请求,获取响应 func TestRpcClientLogin(t *testing.T) { targetHost := "localhost:8081" conn, err := grpc.Dial(targetHost, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { log.Printf("Dial %s failed,err=%v\n", targetHost, err) } defer conn.Close() // 构建一次用户名和密码匹配的rpc请求 c := pb.NewLoginServiceClient(conn) t1 := time.Now() rpcReply, err := c.Login(context.Background(), &pb.LoginRequest{ Username: "leebai", Password: "123456", }) log.Printf("spend time:%v", time.Now().Sub(t1).Milliseconds()) if err != nil { log.Printf("login failed,err=%v\n", err) } else { log.Printf("login response: %v\n", rpcReply) } //// 构建一次用户名和密码不匹配的rpc请求 //c2 := pb.NewLoginServiceClient(conn) //rpcReply, err = c2.Login(context.Background(), &pb.LoginRequest{ // Username: "zhangsan", // Password: "123456", //}) //if err != nil { // log.Printf("login failed,err=%v\n", err) //} else { // log.Printf("login response: %v\n", rpcReply) //} }以上
func (l LoginServiceServerImpl) Login(ctx context.Context, request *pb.LoginRequest) (*pb.LoginResponse, error)是
需要实现login_grpc.pb.go中的接口type LoginServiceServer interface, - 先运行
TestRpcLoginService方法启动rpc服务程序 - 再运行
TestRpcClientLogin方法启动rpc客户端程序,向启动的rpc服务程序发起一次rpc调用,结果如下所示:=== RUN TestRpcClientLogin 2023/05/05 14:15:08 spend time:11 2023/05/05 14:15:08 login response: code:200 msg:"success" --- PASS: TestRpcClientLogin (0.03s) PASS - 至此就完成了一个登录请求的远程rpc服务调用
本文通过一个登录过程的例子,展示了如何使用Go语言和grpc库来实现RPC服务。首先介绍了环境准备,包括设置GOPATH和安装必要的工具。接着,创建了`login.proto`文件定义服务和消息类型,并使用`protoc`生成Go代码。然后,实现了LoginServiceServer接口并启动RPC服务器。最后,编写了测试用例来验证客户端的RPC调用,成功模拟了匹配和不匹配的登录请求。
504

被折叠的 条评论
为什么被折叠?



