使用Golang搭建一个简单的gRPC服务

背景

因为业务需要,需要一个跨语言调用的RPC框架,gRPC是Google发布的基于HTTP 2.0传输层协议承载的高性能开源软件框架,本文使用Golang实现一个简单的gRPC服务端。

环境

环境 版本
系统 CentOS7
Golang 1.19
libprotoc 22.0

安装golang和grpc相关的依赖

golang安装见golang官方
安装 protoc见官方
将相应软件下载下来, 然后将 bin 文件夹添加到 $PATH
项目中安装grpc

go get google.golang.org/grpc

安装protoc-gen-go

go install google.golang.org/protobuf/cmd/protoc-gen-go@latest

安装protoc-gen-go-grpc

go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

安装protoc-gen-grpc-gateway

go install github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway@latest

安装protoc-gen-swagger

go install github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger@latest

go install的文件会安装在$GOPATH/bin下,所以将$GOPATH/bin添加到$PATH

echo 'export PATH=$PATH:$GOPATH/bin' >> ~/.bashrc
source ~/.bashrc

创建hello.proto文件

生成的golang代码存放在./hello
生成golang包名为hello
注册的服务为名称为Hello
调用方法为PrintHello
传入的结构体为HelloRequest
带有一个string类型参数:name
返回的消息结构体为HelloReply
带有一个string类型参数为:message

syntax = "proto3";

option go_package="./hello;hello";

package hello;

service Hello {
    rpc PrintHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
    string name = 1;
}

message HelloReply {
    string message = 1;
}

其中option go_package = "path;name";

path 表示生成的go文件的存放地址,会自动生成目录
name 表示生成的go文件所属的包名

使用protocol buffer编译器生成golang代码

执行

mkdir -p pb
protoc -I ./ hello.proto --go_out=./pb --go-grpc_out=./pb

就会在pb目录下生成hello/hello.pb.go文件和hello/hello_grpc.pb.go,其中包含golang中的服务和消息类型

编写server.go实现gRPC服务端

go mod init server
package main

import (
	"context"
	"fmt"
	"net"

	"server/pb/hello"

	"google.golang.org/grpc"
)

const (
	port = ":1234"
)

type server struct {
	hello.UnimplementedHelloServer // 必须加的结构体
}

func (s *server) PrintHello(ctx context.Context, in *hello.HelloRequest) (*hello.HelloReply, error) {
	fmt.Printf("客户端消息:: %v", in.Name)
	return &hello.HelloReply{Message: "Hello " + in.Name}, nil
}

func main() {
	lis, err := net.Listen("tcp", port)
	if err != nil {
		fmt.Printf("无法监听端口: %v", err)
		panic(err)
	}
	s := grpc.NewServer()
	hello.RegisterHelloServer(s, &server{})
	fmt.Println("服务启动于", port)
	if err := s.Serve(lis); err != nil {
		fmt.Printf("无法提供服务: %v", err)
		panic(err)
	}
}
go mod tidy
go run server.go

显示如下,则gRPC服务端在1234端口启动

服务启动于 :1234

编写client.go连接gRPC客户端

package main

import (
	"context"
	"fmt"

	"server/pb/hello"

	"google.golang.org/grpc"
)

func main() {
	// 建立GRPC连接
	conn, err := grpc.Dial("localhost:1234", grpc.WithInsecure())
	if err != nil {
		fmt.Printf("无法建立连接: %v", err)
		panic(err)
	}
	defer conn.Close()
	c := hello.NewHelloClient(conn)
	r, err := c.PrintHello(context.Background(), &hello.HelloRequest{Name: "hello"})
	if err != nil {
		fmt.Printf("无法发起gRPC请求: %v", err)
		panic(err)
	}
	fmt.Printf("返回的消息: %s", r.Message)
}
go run client.go

最后显示gRPC服务端返回的消息:

返回的消息: Hello hello

你可能感兴趣的:(Linux,golang,网络)