CNCF实践——gRPC

gRPC简介

参考文档

  • gRPC 是一个高性能、开源、通用的RPC框架,由Google推出,基于HTTP/2协议标准设计开发,默认采用Protocol Buffers数据序列化协议,支持多种开发语言。gRPC提供了一种简单的方法来精确的定义服务,并且为客户端和服务端自动生成可靠的功能库。

  • 在gRPC客户端可以直接调用不同服务器上的远程程序,使用姿势看起来就像调用本地程序一样,很容易去构建分布式应用和服务。和很多RPC系统一样,服务端负责实现定义好的接口并处理客户端的请求,客户端根据接口描述直接调用需要的服务。客户端和服务端可以分别使用gRPC支持的不同语言实现。

特性

  • 强大的IDL
    gRPC使用ProtoBuf来定义服务,ProtoBuf是由Google开发的一种数据序列化协议(类似于XML、JSON、hessian)。ProtoBuf能够将数据进行序列化,并广泛应用在数据存储、通信协议等方面。

  • 多语言支持
    gRPC支持多种语言,并能够基于语言自动生成客户端和服务端功能库。目前已提供了C版本grpc、Java版本grpc-java 和 Go版本grpc-go,其它语言的版本正在积极开发中,其中,grpc支持C、C++、Node.js、Python、Ruby、Objective-C、PHP和C#等语言,grpc-java已经支持Android开发。

  • HTTP/2
    gRPC基于HTTP/2标准设计,所以相对于其他RPC框架,gRPC带来了更多强大功能,如双向流、头部压缩、多复用请求等。这些功能给移动设备带来重大益处,如节省带宽、降低TCP链接次数、节省CPU使用和延长电池寿命等。同时,gRPC还能够提高了云端服务和Web应用的性能。gRPC既能够在客户端应用,也能够在服务器端应用,从而以透明的方式实现客户端和服务器端的通信和简化通信系统的构建。

配置环境

gRPC-go

官网给的安装方式

$ go get -u google.golang.org/grpc

但是centos虚拟机上并没梯子!!!
那么换个方式,从github上拉下来咯~ 参考

$ git clone https://github.com/grpc/grpc-go.git $GOPATH/src/google.golang.org/grpc
$ git clone https://github.com/golang/net.git $GOPATH/src/golang.org/x/net
$ git clone https://github.com/golang/text.git $GOPATH/src/golang.org/x/text 
$ git clone https://github.com/google/go-genproto.git $GOPATH/src/google.golang.org/genproto

$ cd $GOPATH/src/
$ go install google.golang.org/grpc

but 还不够!因为是采用Protocol Buffers数据序列化协议,所以还得安装protobuf(简称)!

protobuf

下载protobuf-3.6.1,解压文件后,进入解压后的文件夹,执行下面的命令

$ ./configure
$ sudo make
$ make install
# 验证是否安装成功
$ protoc --version

Golang protobuf插件

$ go get -u github.com/golang/protobuf/{proto,protoc-gen-go}

小试牛刀

惯例从examples中的helloword开始尝试

# 打开
$ cd $GOPATH/src/google.golang.org/grpc/examples/helloworld
# 运行服务端
$ go run greeter_server/main.go
# 开启另一个终端作为客户端,同样进入这个文件夹
$ cd $GOPATH/src/google.golang.org/grpc/examples/helloworld
$ go run greeter_client/main.go

服务端结果

2019/01/18 20:25:47 Received: world

客户端结果

2019/01/18 20:25:47 Greeting: Hello world

样例分析

helloworld.proto

syntax = "proto3";

option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";

package helloworld;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

声明了服务SayHello,请求的参数信息HelloRequest,返回的信息HelloReply。利用.proto文件定义gRPC服务,通过 protoc 编译器生成 .pb.go 文件。
编译命令:

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

运行后生成helloworld.pb.go

服务端main.go

package main

import (
	"context"
	"log"
	"net"

	"google.golang.org/grpc"
	pb "google.golang.org/grpc/examples/helloworld/helloworld"
	"google.golang.org/grpc/reflection"
)

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) {
	log.Printf("Received: %v", in.Name)
	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{})
	// Register reflection service on gRPC server.
	reflection.Register(s)
	if err := s.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}

实现了服务sayHello,注册protobuf服务端,注册gRPC服务端,并且对端口50051进行监听。

客户端main.go

package main

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

	"google.golang.org/grpc"
	pb "google.golang.org/grpc/examples/helloworld/helloworld"
)

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

func main() {
	// Set up a connection to the server.
	conn, err := grpc.Dial(address, grpc.WithInsecure())
	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)
}

建立和服务端的连接,建立protobuf客户端
,在客户端调用sayHello。

你可能感兴趣的:(服务计算)