8.11gRPC初步认识


title: gRPC初步认识
date: 2020/4/30
comments: true
categories:

  • 微服务
    tags:
  • 微服务
    permalink: “8.11”

gRPC简介

gRPC 是一个高性能、开源和通用的 RPC 框架,面向移动和 HTTP/2 设计。

gRPC 基于 HTTP/2 标准设计,带来诸如双向流、流控、头部压缩、单 TCP 连接上的多复用请求等特。这些特性使得其在移动设备上表现更好,更省电和节省空间占用。

在 gRPC 里客户端应用可以像调用本地对象一样直接调用另一台不同的机器上服务端应用的方法,使得您能够更容易地创建分布式应用和服务。与许多 RPC 系统类似,gRPC 也是基于以下理念:定义一个服务,指定其能够被远程调用的方法(包含参数和返回类型)。在服务端实现这个接口,并运行一个 gRPC 服务器来处理客户端调用。在客户端拥有一个存根能够像服务端一样的方法。

gRPC原理

gRPC 客户端和服务端可以在多种环境中运行和交互 - 从 google 内部的服务器到你自己的笔记本,并且可以用任何 gRPC 支持的语言来编写。所以,你可以很容易地用 Java 创建一个 gRPC 服务端,用 Go、Python、Ruby 来创建客户端。此外,Google 最新 API 将有 gRPC 版本的接口,使你很容易地将 Google 的功能集成到你的应用里。

gRPC相对于RESTful api的优势

gRPC和restful API都提供了一套通信机制,用于server/client模型通信,而且它们都使用http作为底层的传输协议(严格地说, gRPC使用的http2.0,而restful api则不一定)。不过gRPC还是有些特有的优势,如下:

gRPC可以通过protobuf来定义接口,从而可以有更加严格的接口约束条件。关于protobuf可以参见笔者之前的小文Google Protobuf简明教程
另外,通过protobuf可以将数据序列化为二进制编码,这会大幅减少需要传输的数据量,从而大幅提高性能。
gRPC可以方便地支持流式通信(理论上通过http2.0就可以使用streaming模式, 但是通常web服务的restful api似乎很少这么用,通常的流式数据应用如视频流,一般都会使用专门的协议如HLS,RTMP等,这些就不是我们通常web服务了,而是有专门的服务器应用。)

使用 protocol buffers

gRPC 默认使用 protocol buffers,这是 Google 开源的一套成熟的结构数据序列化机制(当然也可以使用其他数据格式如 JSON)。通常情况下我们用 proto files 创建 gRPC 服务,用 protocol buffers 消息类型来定义方法参数和返回类型。

关于protocol buffers的版本问题,虽然你可以使用 proto2 (当前默认的 protocol buffers 版本), 我们通常建议你在 gRPC 里使用 proto3,因为这样你可以使用 gRPC 支持全部范围的的语言,并且能避免 proto2 客户端与 proto3 服务端交互时出现的兼容性问题,反之亦然。

hello gRPC

安装

环境配置

1、安装protoc
到这里下载最新版的 protoc
并配置环境变量到path下

2、安装golang protobuf

go get -u github.com/golang/protobuf/proto // golang protobuf 库
go get -u github.com/golang/protobuf/protoc-gen-go //protoc --go_out 工具

3、安装gRPC-go

go get google.golang.org/grpc

编写protobuf接口

syntax = "proto3";

package mygrpc;

// define a service
service HelloWorldService {
    // define the interface and data type
    rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// define the data type of request
message HelloRequest {
    string name = 1;
}

// define the data type of response
message HelloReply {
    string message = 1;
}

编译protobuf,命令

protoc --go_out=plugins=grpc:./ *.proto

创建服务端程序

package main

import (
  "context"
  "fmt"
  "net"
  pt "server/mygrpc"

  "google.golang.org/grpc"
)

const (
  post = "127.0.0.1:8000"
)

type server struct{}

//实现SayHello接口
func (s *server) SayHello(ctx context.Context, in *pt.HelloRequest) (*pt.HelloReply, error) {
  return &pt.HelloReply{Message: "hello" + in.Name}, nil
}

func (s *server) GetMessage(ctx context.Context, in *pt.HelloRequest) (*pt.HelloReply, error) {
  return &pt.HelloReply{Message: "This is from the server "}, nil
}

func main() {
  ln, err := net.Listen("tcp", post)
  if err != nil {
   fmt.Println("网络异常", err)
  }

  //创建一个grpc句柄

  srv := grpc.NewServer()

  pt.RegisterHelloWorldServiceServer(srv, &server{})

  err = srv.Serve(ln)
  if err != nil {
   fmt.Println("网络启动异常", err)
  }
}

编写客户端程序

package main

import (
  pt "client/mygrpc"
  "context"
  "fmt"

  "google.golang.org/grpc"
)

const (
  post = "127.0.0.1:8000"
)

func main() {
  conn, err := grpc.Dial(post, grpc.WithInsecure())

  if err != nil {
    fmt.Println("连接服务器失败", err)
  }

  defer conn.Close()

  c := pt.NewHelloWorldServiceClient(conn)

  //远程调用
  r1, err := c.SayHello(context.Background(), &pt.HelloRequest{Name: "熊猫阿宝"})

  if err != nil {
    fmt.Println("can't get server", err)
  }
  fmt.Println(r1.Message)

}

首先运行server,然后运行client,就能看到 “hello熊猫阿宝”的输出了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值