Go 服务端与客户端开发
本章详细介绍如何使用 Go 语言开发 gRPC 服务端和客户端。
一、服务端开发
1. 实现服务接口
服务端需要实现 protobuf 定义的服务接口:
go
package main
import (
"context"
"log"
"net"
"google.golang.org/grpc"
pb "your_project_path/proto"
)
// server 实现 GreeterServer 接口
type server struct {
pb.UnimplementedGreeterServer
}
// SayHello 实现 RPC 方法
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
log.Printf("收到请求: %s", in.GetName())
return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}注意:必须嵌入 UnimplementedGreeterServer,保证向前兼容性。
2. 启动服务
go
func main() {
// 监听端口
lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalf("监听失败: %v", err)
}
// 创建 gRPC 服务
s := grpc.NewServer()
// 注册服务
pb.RegisterGreeterServer(s, &server{})
log.Println("服务启动,监听 :50051")
if err := s.Serve(lis); err != nil {
log.Fatalf("服务启动失败: %v", err)
}
}3. 优雅关闭
go
// 接收终止信号
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
log.Println("正在关闭服务...")
s.GracefulStop()
log.Println("服务已关闭")4. 服务端选项
go
s := grpc.NewServer(
grpc.MaxRecvMsgSize(1024*1024*10), // 最大接收 10MB
grpc.MaxSendMsgSize(1024*1024*10), // 最大发送 10MB
grpc.ConnectionTimeout(30*time.Second), // 连接超时
)二、客户端开发
1. 建立连接
go
conn, err := grpc.Dial("localhost:50051",
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithBlock(), // 阻塞等待连接建立
)
if err != nil {
log.Fatalf("连接失败: %v", err)
}
defer conn.Close()2. 调用服务
go
client := pb.NewGreeterClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
resp, err := client.SayHello(ctx, &pb.HelloRequest{Name: "World"})
if err != nil {
log.Fatalf("调用失败: %v", err)
}
log.Printf("收到响应: %s", resp.GetMessage())3. Context 超时控制
go
// 设置 5 秒超时
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
resp, err := client.SayHello(ctx, &pb.HelloRequest{Name: "World"})4. 客户端选项
go
conn, err := grpc.Dial("localhost:50051",
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithKeepaliveParams(keepalive.ClientParameters{
Time: 10 * time.Second, // 每 10 秒发送心跳
Timeout: 3 * time.Second, // 心跳超时
}),
)三、完整示例
完整的可运行代码请参考实战项目:
- 项目01:HelloWorld - 最基础的一元调用
四、最佳实践
- 错误处理:始终检查 error,使用
status.Error()返回 gRPC 错误码 - 连接管理:客户端连接可复用,不要每次调用都新建连接
- 超时设置:为每个 RPC 调用设置合理的超时时间
- 优雅关闭:服务端使用
GracefulStop()确保处理完已有请求 - 并发安全:服务实现必须保证并发安全