Grpc 介绍 | 青训营笔记

98 阅读2分钟

Grpc 介绍

1. 什么是 grpc

gRPC 是一个高性能、开源和通用的 RPC 框架,面向移动和 HTTP/2 设计。目前提供 C、Java 和 Go 语言版本,分别是 grpc, grpc-java, grpc-go。gRPC 基于 HTTP/2 标准设计,带来诸如双向流、流控、头部压缩、单 TCP 连接上的多复用请求等特。这些特性使得其在移动设备上表现更好,更省电和节省空间占用。

2. grpc 的优势

  • 简单易用,基于 ProtoBuf 定义接口,自动生成代码,使用起来非常方便。
  • 支持多种语言,目前支持 C、Java、Go,分别是 grpc, grpc-java, grpc-go。
  • 基于 HTTP/2 标准设计,带来诸如双向流、流控、头部压缩、单 TCP 连接上的多复用请求等特性。

3. grpc 的缺点

  • 由于是基于 HTTP/2 标准设计,所以只能在 HTTP/2 上使用,不能在 HTTP/1.1 上使用。
  • 由于是基于 ProtoBuf 定义接口,所以只能使用 ProtoBuf 序列化,不能使用 JSON 等其他序列化方式。

4. grpc 的应用场景

  • 服务间通信,比如微服务之间的通信。
  • 客户端与服务端通信,比如移动端与服务端通信。

5. grpc 的使用

5.1 安装

5.2 定义接口

syntax = "proto3";

package helloworld;

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

5.3 生成代码

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

5.4 实现接口

package main

import (
    "context"
    "log"
    "net"

    pb "github.com/zhengyscn/golang-doc/grpc/helloworld"
    "google.golang.org/grpc"
)

const (
    port = ":50051"
)

// server is used to implement helloworld.GreeterServer.
type server struct{}

// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
    return &pb.HelloReply{Message: "Hello " + in.Name}, nil
}

func main() {
    lis, err := net.Listen("tcp", port)
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }
    s := grpc.NewServer()
    pb.RegisterGreeterServer(s, &server{})
    if err := s.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}

5.5 启动服务

go run server/main.go

5.6 调用接口

package main

import (
    "context"
    "log"
    "os"
    "time"

    pb "github.com/zhengyscn/golang-doc/grpc/helloworld"
    "google.golang.org/grpc"
)

const (
    address     = "localhost:50051"
    defaultName = "world"
)

func main() {
    // Set up a connection to the server.
    conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
    if err != nil {
        log.Fatalf("did not connect: %v", err)
    }
    defer conn.Close()
    c := pb.NewGreeterClient(conn)

    // Contact the server and print out its response.
    name := defaultName
    if len(os.Args) > 1 {
        name = os.Args[1]
    }
    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    defer cancel()
    r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name})
    if err != nil {
        log.Fatalf("could not greet: %v", err)
    }
    log.Printf("Greeting: %s", r.Message)
}

5.7 运行客户端

go run client/main.go