[Серия] Go gRPC Hello World

Go gRPC

Обзор

Запустите gRPC, в этой статье рассказывается, как использовать gRPC для вывода Hello World.

  • Внедрите сервер gRPC в Go.
  • Клиент для gRPC, реализованный на Go.

gRPC поддерживает 4 типа методов обслуживания, на этот раз мы реализуем одноэлементный RPC и потоковый RPC на стороне сервера.

Четыре типа методов обслуживания

Один RPC

Сервер отправляет запрос на сервер и получает ответ от сервера, как при обычном вызове функции.

rpc SayHello(HelloRequest) returns (HelloResponse){}

Потоковая RPC на стороне сервера

Клиент отправляет запрос на сервер, чтобы получить поток данных для чтения серии сообщений. Клиент читает из возвращенного потока данных до тех пор, пока не останется сообщений.

rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){}

Клиентская потоковая передача RPC

Клиент пишет и отправляет серию сообщений на сервер, используя предоставленный поток данных. Как только клиент заканчивает писать сообщения, он ждет, пока сервер прочитает сообщения и вернет ответ.

rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse) {}

Двунаправленный потоковый RPC

Обе стороны могут отправлять серию сообщений через поток данных чтения и записи соответственно. Операции с двумя потоками данных независимы друг от друга, поэтому клиент и сервер могут читать и записывать в любом порядке, который они хотят, например: сервер может ждать всех клиентских сообщений, прежде чем писать ответ, или он может сначала прочитать сообщение Записать другое сообщение или какое-либо другое сочетание чтения и записи. Порядок сообщений в каждом потоке данных сохраняется.

rpc BidiHello(stream HelloRequest) returns (stream HelloResponse){}

Установить

Установите компилятор protobuf

brew install protobuf

проверять:

protoc --version

//输出:libprotoc 3.7.1

Установите плагин Go protobuf

go get -u github.com/golang/protobuf/proto

go get -u github.com/golang/protobuf/protoc-gen-go

Установить grpc-go

go get -u google.golang.org/grpc

Написать сервис Hello World

  • сервер записи.protoдокумент
  • сгенерировать сервер.pb.goфайл и синхронизировать его с клиентом
  • Напишите код, обеспечивающий интерфейс на стороне сервера
  • Напишите код, который клиент вызывает интерфейс

Структура каталогов

├─ hello  -- 代码根目录
│  ├─ go_client
│     ├── main.go
│     ├── proto
│         ├── hello
│            ├── hello.pb.go
│  ├─ go_server
│     ├── main.go
│     ├── controller
│         ├── hello_controller
│            ├── hello_server.go
│     ├── proto
│         ├── hello
│            ├── hello.pb.go
│            ├── hello.proto

Этот каталог создан для того, чтобы впоследствии go_client и go_server можно было разделить на два проекта.

Напишите серверный файл hello.proto.

syntax = "proto3"; // 指定 proto 版本

package hello;     // 指定包名

// 定义 Hello 服务
service Hello {

	// 定义 SayHello 方法
	rpc SayHello(HelloRequest) returns (HelloResponse) {}

	// 定义 LotsOfReplies 方法
	rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){}
}

// HelloRequest 请求结构
message HelloRequest {
	string name = 1;
}

// HelloResponse 响应结构
message HelloResponse {
    string message = 1;
}

Чтобы узнать больше о синтаксисе Protobuf, см.:

Developers.Google.com/protocol - нет...

сгенерировать сервер.pb.go

protoc -I . --go_out=plugins=grpc:. ./hello.proto

также будет генерироватьhello.pb.goкопировать клиенту.

Просмотрите дополнительные параметры команды, выполните protoc и просмотрите OPTION .

Напишите код, обеспечивающий интерфейс на стороне сервера

// hello_server.go
package hello_controller

import (
	"fmt"
	"golang.org/x/net/context"
	"hello/go_server/proto/hello"
)

type HelloController struct{}

func (h *HelloController) SayHello(ctx context.Context, in *hello.HelloRequest) (*hello.HelloResponse, error) {
	return &hello.HelloResponse{Message : fmt.Sprintf("%s", in.Name)}, nil
}

func (h *HelloController) LotsOfReplies(in *hello.HelloRequest, stream hello.Hello_LotsOfRepliesServer)  error {
	for i := 0; i < 10; i++ {
		stream.Send(&hello.HelloResponse{Message : fmt.Sprintf("%s %s %d", in.Name, "Reply", i)})
	}
	return nil
}
// main.go
package main

import (
	"log"
	"net"
	"hello/go_server/proto/hello"
	"hello/go_server/controller/hello_controller"
	"google.golang.org/grpc"
)

const (
	Address = "0.0.0.0:9090"
)

func main() {
	listen, err := net.Listen("tcp", Address)
	if err != nil {
		log.Fatalf("Failed to listen: %v", err)
	}

	s := grpc.NewServer()

	// 服务注册
	hello.RegisterHelloServer(s, &hello_controller.HelloController{})

	log.Println("Listen on " + Address)

	if err := s.Serve(listen); err != nil {
		log.Fatalf("Failed to serve: %v", err)
	}
}

бегать:

go run main.go

2019/07/28 17:51:20 Listen on 0.0.0.0:9090

Напишите код для интерфейса запроса клиента

package main

import (
	"hello/go_client/proto/hello"
	"io"
	"log"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
)

const (
	// gRPC 服务地址
	Address = "0.0.0.0:9090"
)

func main() {
	conn, err := grpc.Dial(Address, grpc.WithInsecure())
	if err != nil {
		log.Fatalln(err)
	}
	defer conn.Close()

	// 初始化客户端
	c := hello.NewHelloClient(conn)

	// 调用 SayHello 方法
	res, err := c.SayHello(context.Background(), &hello.HelloRequest{Name: "Hello World"})

	if err != nil {
		log.Fatalln(err)
	}

	log.Println(res.Message)

	// 调用 LotsOfReplies 方法
	stream, err := c.LotsOfReplies(context.Background(),&hello.HelloRequest{Name: "Hello World"})
	if err != nil {
		log.Fatalln(err)
	}

	for {
		res, err := stream.Recv()
		if err == io.EOF {
			break
		}

		if err != nil {
			log.Printf("stream.Recv: %v", err)
		}

		log.Printf("%s", res.Message)
	}
}

бегать:

go run main.go

2019/07/28 17:58:13 Hello World
2019/07/28 17:58:13 Hello World Reply 0
2019/07/28 17:58:13 Hello World Reply 1
2019/07/28 17:58:13 Hello World Reply 2
2019/07/28 17:58:13 Hello World Reply 3
2019/07/28 17:58:13 Hello World Reply 4
2019/07/28 17:58:13 Hello World Reply 5
2019/07/28 17:58:13 Hello World Reply 6
2019/07/28 17:58:13 Hello World Reply 7
2019/07/28 17:58:13 Hello World Reply 8
2019/07/28 17:58:13 Hello World Reply 9

Посмотреть исходный код:GitHub.com/Бессердечный не…

Рекомендуемое чтение

Джин каркас

Основы

Эту статью можно переслать, пожалуйста, укажите автора и источник для пересылки, спасибо!