引入gRPC
官网:https://grpc.io/
在 gRPC 中,客户端应用程序可以直接调用不同机器上的服务器应用程序上的方法,就像它是本地对象一样,使您可以更轻松地创建分布式应用程序和服务。与许多 RPC 系统一样,gRPC 基于定义服务的思想,指定可以通过参数和返回类型远程调用的方法。在服务器端,服务器实现了这个接口并运行一个 gRPC 服务器来处理客户端调用。在客户端,客户端有一个存根(在某些语言中简称为客户端),它提供与服务器相同的方法。
gRPC 客户端和服务器可以在各种环境中运行和相互通信 - 从 Google 内部的服务器到您自己的桌面 - 并且可以用任何 gRPC 支持的语言编写。因此,例如,您可以轻松地使用 Java、Go、Python 或 Ruby 中的客户端创建一个 gRPC 服务器。此外,最新的 Google API 将具有其接口的 gRPC 版本,让您可以轻松地将 Google 功能构建到您的应用程序中。
Go使用grpc协议通信实战
安装protocol环境
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1
设置环境变量,如MAC环境下
xxx bin % pwd
/Users/xxx/go/bin
xxx bin % ls
protoc-gen-go protoc-gen-go-grpc protoc-gen-validate
编辑配置文件~/.bash_profile
export GOPATH=$HOME/go
export PATH=$PATH:$GOPATH/bin
简述使用流程
具体应用代码
1 项目结构
2 proto文件
syntax = "proto3"; //指定语法格式,注意 proto3 不再支持 proto2 的 required 和 optinal
package proto; //指定生成的 user.pb.go 的包名字;
//service 定义开发调用 的服务, 即UserInfoService 微服务
service UserInfoService {
//rpc 方式;定义GetUserInfo 远程调用
rpc GetUserInfo(UserRequest) returns (UserResponse){}
}
//定义客户端请求的数据格式
//message 对应 生成的代码中的struct
message UserRequest{
// [修饰符] 类型 字段名 = 标识符
string name = 1;
}
message UserResponse{
int32 id=1;
string name=2;
int32 age =3;
repeated string title = 4; // 可变数组,即 slice 类型
}
3 编译proto文件
在protoc目录下执行命令:
protoc -I . --go_out=plugins=grpc:. user.proto
4 服务端代码
package main
import (
"context"
"fmt"
"go-grpc-server/proto"
"google.golang.org/grpc"
"log"
"net"
)
//定义服务端 实现 约定的接口
type UserInfoService struct{}
var u = UserInfoService{}
//实现 interface
func (s *UserInfoService) GetUserInfo(ctx context.Context, req *proto.UserRequest) (resp *proto.UserResponse, err error) {
name := req.Name
if name == "YMX" {
resp = &proto.UserResponse{
Id: 1,
Name: name,
Age: 22,
Title: []string{"Java", "Go"},
}
}
err = nil
return
}
func main() {
//1 添加监听的端口
port := ":6666"
l, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("端口监听错误 : %v\n", err)
}
fmt.Printf("正在监听: %s 端口\n", port)
//2 启动grpc服务
s := grpc.NewServer()
//3 将UserInfoService服务注册到gRPC中
// 注意第二个参数 UserInfoServiceServer 是接口类型的变量,需要取地址传参
proto.RegisterUserInfoServiceServer(s, &u)
s.Serve(l)
}
5 客户端代码
package main
import (
"context"
"fmt"
"go-grpc-server/proto"
"google.golang.org/grpc"
"log"
)
func main() {
//1 配置grpc服务端的端口作为客户端的监听
conn, err := grpc.Dial(":6666", grpc.WithInsecure())
if err != nil {
log.Fatalf("正在监听服务端 : %v\n", err)
}
defer conn.Close()
//2 实例化 UserInfoService 服务的客户端
client := proto.NewUserInfoServiceClient(conn)
//3 调用grpc服务
req := new (proto.UserRequest)
req.Name = "YMX"
resp, err := client.GetUserInfo(context.Background(), req)
if err != nil {
log.Fatalf("请求错误 : %v\n", err)
}
fmt.Printf("响应内容 : %v\n", resp)
}
6 测试
服务端:
参考文章
https://blog.csdn.net/u013862108/article/details/103808011/