使用grpc远程调用服务

下载protobuf

需要把可执行程序,加入环境变量
官方文档地址:https://protobuf.dev/getting-started/gotutorial/

  • 下载地址https://github.com/protocolbuffers/protobuf/releases

安装两个代码生成插件

需要把可执行程序,加入环境变量

  • 下载地址:go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
  • 下载地址:go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

编写proto协议

文件类型一般是xxx.proto
注意文件头部要写版本、路径、包名,用来控制生成的代码用什么版本语法、放到哪里、包名叫啥。此处使用proto3版本,路径是当前路径./,即和xxx.proto同路径,包名为proto_demo
示例中,定义了一个Greeter远程服务,拥有SayHello (HelloRequest) returns (HelloResponse)签名的方法

syntax = "proto3";
option go_package="./;proto_demo";

message HelloRequest {
  string name = 1;
}

message HelloResponse {
  string message = 1;
  bool male = 2;
  repeated int32 scores = 3;
  map<string, int32> subject = 4;
}

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloResponse);
  // 加上stream,表示双向流
  // rpc SayHello (stream  HelloRequest) returns (stream  HelloResponse);
}

生成代码

  • 命令:protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative proto_demo/*.proto_demo

写一个服务端

远程调用服务的具体实现,注册后,给客户端调用
项目中使用grpcgo get google.golang.org/grpc

package main

import (
	"context"
	"fmt"
	"google.golang.org/grpc"
	"grpc_test/proto_demo"
	"net"
)

type HelloService struct {
	proto_demo.UnimplementedGreeterServer
}

func (receiver *HelloService) SayHello(ctx context.Context, a *proto_demo.HelloRequest) (*proto_demo.HelloResponse, error) {
	fmt.Println(a.Name)
	return &proto_demo.HelloResponse{
		Message: "hahah",
		Male:    true,
		Scores:  []int32{1, 2, 3},
		Subject: map[string]int32{"a": 1, "b": 2},
	}, nil

}
func main() {

	listen, err := net.Listen("tcp", "127.0.0.1:5555")
	if err != nil {
		panic(err)
	}

	s := grpc.NewServer()

	proto_demo.RegisterGreeterServer(s, &HelloService{})
	if err := s.Serve(listen); err != nil {
		panic(err)
	}

}

写一个客户端

远程调用服务

package main

import (
	"context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"grpc_test/proto_demo"
	"log"
	"time"
)

func main() {
	// 1. 创建 ClientConn(等同于旧版 DialContext,但不会立即 I/O)
	conn, err := grpc.NewClient(
		"localhost:5555",
		grpc.WithTransportCredentials(insecure.NewCredentials()), // 本地开发不加 TLS
	)
	if err != nil {
		log.Fatalf("failed to create client: %v", err)
	}
	defer conn.Close()

	// 2. 构造 gRPC 客户端
	client := proto_demo.NewGreeterClient(conn)

	// 3. 发起 RPC(同样用 Context+超时控制)
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()

	resp, err := client.SayHello(ctx, &proto_demo.HelloRequest{Name: "世界"})
	if err != nil {
		log.Fatalf("could not greet: %v", err)
	}

	log.Printf("Greeting from server: %s", resp)
}

测试

  • 先启动服务端,后启动客户端
  • 服务端先收到客户端的请求,后给客户端回复响应

posted @ 2025-06-19 15:14  rm-rf*  阅读(34)  评论(0)    收藏  举报