grpc安装
- 1.1 核心依赖安装
# 1. 安装 Protobuf 核心库
go get google.golang.org/protobuf@latest
# 2. 安装 gRPC 核心库
go get google.golang.org/grpc@latest
# 3. 安装 Protobuf 代码生成插件
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
# 4. 处理 gRPC 代码生成
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
- 1.2 编写protobuf文件
syntax = "proto3"; // 指定proto版本
package hello_grpc; // 指定默认包名
// 指定golang包名
option go_package = "/hello_grpc";
//定义rpc服务
service HelloService {
// 定义函数
rpc SayHello (HelloRequest) returns (HelloResponse) {}
}
// HelloRequest 请求内容
message HelloRequest {
string name = 1;
string message = 2;
}
// HelloResponse 响应内容
message HelloResponse{
string name = 1;
string message = 2;
}
- 1.3 基础 Protobuf Go 代码
protoc -I . --go_out=.\grpc_proto .\grpc_proto\hello.proto
- 1.4 gRPC 核心 Go 代码
protoc -I . --go-grpc_out=.\grpc_proto .\grpc_proto\hello.proto
生成输出
- 服务端, 定义一个的结构体,使其实现 Protobuf 生成的服务接口的所有方法,随后将该结构体实例注册为 gRPC 服务并启动端口监听,以接收客户端请求。
package main
import (
"fmt"
"grpc-study/grpc_proto/hello_grpc"
"net"
"golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/grpclog"
)
type HelloServer struct {
hello_grpc.UnimplementedHelloServiceServer
}
func (HelloServer) SayHello(ctx context.Context, request *hello_grpc.HelloRequest) (pd *hello_grpc.HelloResponse, err error) {
fmt.Println("入参:", request.Name, request.Message) // 打印客户端传入的参数
pd = new(hello_grpc.HelloResponse) // 创建响应对象(初始化指针)
pd.Name = "Server" // 设置响应中的 Name 字段
pd.Message = "OK" // 设置响应中的 Message 字段
return // 返回响应对象和 nil 错误(表示成功)
}
func main() {
// 监听端口:创建 TCP 监听,绑定到 8080 端口
listen, err := net.Listen("tcp", ":8080")
if err != nil {
grpclog.Fatalf("Failed to listen: %v", err) // 监听失败则打印日志并退出
}
// 创建一个 gRPC 服务器实例(可配置拦截器、tls 等,这里用默认配置)
s := grpc.NewServer()
// 实例化自定义的服务端结构体
server := &HelloServer{}
// 将服务端结构体注册到 gRPC 服务器:告诉 gRPC 框架,这个服务器实现了 HelloService 服务
hello_grpc.RegisterHelloServiceServer(s, server)
fmt.Println("grpc server running :8080") // 打印服务启动信息
// 启动 gRPC 服务器:开始监听并处理客户端请求(阻塞当前进程)
err = s.Serve(listen)
if err != nil { // 若服务启动失败(如端口被占用),打印错误
grpclog.Fatalf("Failed to serve: %v", err)
}
}
- 客户端, 建立 gRPC 客户端与服务端的连接后,通过该连接调用 Protobuf 生成的客户端存根对应的方法,以发起服务请求并获取响应。
package main
import (
"context"
"fmt"
"grpc-study/grpc_proto/hello_grpc"
"log"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
func main() {
address := ":8080"
// 1. 创建客户端连接选项
opts := []grpc.DialOption{
grpc.WithTransportCredentials(insecure.NewCredentials()), // 非安全连接(测试用)
}
// 2. 使用 NewClient 创建客户端连接
conn, err := grpc.NewClient(address, opts...)
if err != nil {
log.Fatalf(fmt.Sprintf("grpc connect addr [%s] 连接失败 %s", address, err))
}
defer conn.Close()
// 3. 创建客户端并调用方法
client := hello_grpc.NewHelloServiceClient(conn)
result, err := client.SayHello(context.Background(), &hello_grpc.HelloRequest{
Name: "Client",
Message: "OK",
})
fmt.Println(result, err)
}
proto文件
- 一个proto文件存在多个服务
syntax = "proto3"; // 指定proto版本
// 指定golang包名
option go_package = "/more_proto";
service VideoService {
rpc Look(Request)returns(Response){}
}
message Request{
string name = 1;
}
message Response{
string name = 1;
}
service OrderService {
rpc Buy(Request)returns(Response){}
}
- 服务端
package main
import (
"context"
"fmt"
"grpc-study/grpc_proto/more_proto"
"log"
"net"
"google.golang.org/grpc"
)
type VideoServer struct {
more_proto.UnimplementedVideoServiceServer
}
func (VideoServer) Look(ctx context.Context, request *more_proto.Request) (res *more_proto.Response, err error) {
fmt.Println("video:", request)
return &more_proto.Response{
Name: "Video_Server",
}, nil
}
type OrderServer struct {
more_proto.UnimplementedOrderServiceServer
}
func (OrderServer) Buy(ctx context.Context, request *more_proto.Request) (res *more_proto.Response, err error) {
fmt.Println("order:", request)
return &more_proto.Response{
Name: "Order_Server",
}, nil
}
func main() {
listen, err := net.Listen("tcp", ":8080")
if err != nil {
log.Fatal(err)
}
s := grpc.NewServer()
more_proto.RegisterVideoServiceServer(s, &VideoServer{})
more_proto.RegisterOrderServiceServer(s, &OrderServer{})
fmt.Println("grpc server程序运行在:8080")
err = s.Serve(listen)
}
- 客户端
package main
import (
"context"
"fmt"
"grpc-study/grpc_proto/more_proto"
"log"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
func main() {
addr := ":8080"
// 1. 创建客户端连接选项
opts := []grpc.DialOption{
grpc.WithTransportCredentials(insecure.NewCredentials()), // 非安全连接(测试用)
}
// 2. 使用 NewClient 创建客户端连接
conn, err := grpc.NewClient(addr, opts...)
if err != nil {
log.Fatalf(fmt.Sprintf("grpc connect addr [%s] 连接失败 %s", addr, err))
}
defer conn.Close()
orderClient := more_proto.NewOrderServiceClient(conn)
res, err := orderClient.Buy(context.Background(), &more_proto.Request{
Name: "orderClient",
})
fmt.Println(res, err)
videoClient := more_proto.NewVideoServiceClient(conn)
res, err = videoClient.Look(context.Background(), &more_proto.Request{
Name: "videoClient",
})
fmt.Println(res, err)
}
