golang grpc

golang grpc

rpc种类

1.支持多语言的rpc框架,例如Google的grpc,facebook thrift, 百度的brpc

2.支持特定语言的rpc框架, 例如新浪微博的Motan

3.支持服务治理微服务化特性框架,其底层仍是rpc框架,例如 阿里的Dubbo

目前业内主要使用基于多语言的 RPC 框架来构建微服务,是一种比较好的技术选择,例如netflix ,API服务编排层和后端微服务之间采用微服务rpc进行通信

grpc含义

gRPC是Google的RPC框架,开源、高性能、跨语言,基于HTTP/2通讯协议和Protocol Buffer 3数据序列化协议

    定义一个服务,指定其能够被远程调用的方法(包含参数和返回类型)。在服务端实现这个接口,并运行一个 gRPC 服务器来处理客户端调用。在客户端拥有一个存根能够像服务端一样的方法。

    直白的说就是调用的双方可以使用完全不同的两种语言来实现,分别实现client端和server端,按照约定的protobuf协议进行交互。client端会保存与server端的长连接对象或叫存根,通过这个存根可以直接调用服务端的方法。而服务端则实现了proto中指定的服务接口。

grpc 优势

1. 多语言
Grpc的多语言是他做的很牛逼的地方,特别是在设备端,客户端支持ios,android,而基于http2.0的多路复用也的确让设备真正的省了流量,省了电,也省了空间

2.基于Http2.0
采用HTTP2的好处在于,因为添加了头信息,可以方便在框架层面对调用做拦截和控制(比如说限流,调用链分析,安全认证等)而且http2为标准协议,也方便以后扩展兼容其它调用端

grpc 原理

1.gRPC消息由netty /http/2 协议负责接入,通过grpc 注册的Http2Framelister将解码后的Http header和Http body 发送到gRPC的NettyServerHandler ,实现netty http/2的消息接入

2.gRPC 的线程模型遵循 Netty 的线程分工原则,即:协议层消息的接收和编解码由 Netty 的 I/O(NioEventLoop) 线程负责;后续应用层的处理由应用线程负责,防止由于应用处理耗时而阻塞 Netty 的 I/O 线程 (因为分工原则,grpc 之间会做频繁的线程切换,如果在一次grpc调用过程中,做了多次I/O线程到应用线程之间的切换,会导致性能的下降 所以一些私有协议不太友好)

grpc 模型

异步非阻塞的线程模型

服务端线程模型主要包括
1.服务端的写入,客户端的接入线程(HTTP/2 Acceptor)
2.网络I/O的读写线程
3.服务接口调用线程

客户端线程模型主要包含
1.客户端的链接 (HTTP/2 Connector)
2.网络I/O读写线程
3.接口调用线程
4.响应回调通知线程

linux grpc 安装与使用示范

前言:
要编译proto文件生成go代码需要两个工具
    1.protoc :用于编译(其他语言只需要protoc足以)
    2.protoc-gen-go : 用于生成go语言的文件(go语言专用插件)

安装

1).安装grpc运行环境
    go get google.golang.org/grpc

2).安装protoc
    1. 去官网 (https://github.com/protocolbuffers/protobuf/releases) 下载对应的linux版本 例如我下载的protobuf-cpp-3.9.1.zip
    2.unzip protobuf-cpp-3.9.1.zip 
    3.cd protobuf-3.9.1/
    4. ./configure  // 加--prefix=/路径  指定安装位置
    5.make && make install

3).安装protoc-gen-go
    go get -v -u github.com/golang/protobuf/protoc-gen-go

    go get -v -u github.com/gogo/protobuf/gogoprot

使用

1). 编写proto文件

示例:

//testHello.proto
syntax = "proto3";

package protos;

// 定义服务 也可以不定义 后续再用其他方法
service Devops {
    // 定义服务 接收参数类型 返回参数类型
    rpc SayHello (HelloRequest) returns (Response) {
    }
}

// 定义接受请求参数
message HelloRequest {
    string name = 1;
}

// 定义次一级返回格式
message HelloReply {
    string message = 1;
}

// 也可以定义第二级返回格式
message Tdata {
    string address = 1; //允许字符串      后续数字仅仅表示为标识符而已
    int64 telphone = 2; // 允许int
    float money = 3; // 允许浮点
    bool live = 4; //允许布尔
    bytes person = 5; // 允许字节码
}
// 定义次一级返回格式
message Datas {
    int32 id = 1;
    string number = 2;
    repeated Tdata tdatas = 3; //repeated 为允许多个 Tdata 也可以继续套接
}

//还能定义更复杂的套接
message DBS {
    repeated Datas dbs = 1;
}

// 定义最后返回参数
message Response {
    // 定义固定返回状态吗类型 采用枚举
    enum StatusCode {
        TEST = 0;
        SUCCESS = 200;
        REDIRECT = 300;
        UNDEFINED = 404;
        FAILURE = 500;
    }

    // 综合定义返回
    StatusCode status = 1;
    HelloReply msg = 2;
    Datas data = 3;
    DBS db = 4;
}

2).在终端自动生成pb.go

语法: protoc -I <需要编译的proto文件存放的路径> --go_out=plugins=grpc: . <读取编译文件的绝对路径/*.proto>

示例:protoc -I /Users/liuxinMAC/go/src/workspace/gc/ --go_out=plugins=grpc:. /Users/liuxinMAC/go/src/workspace/gc/testhello.proto

缩写: protoc -I . --go_out=plugins=grpc:. testhello.proto

参数说明:
--go_out-plugins-grpc: 固定格式 输出golang相关文件

3).编写服务端

示例:
package main

import (
    "context"
    "fmt"
    "google.golang.org/grpc"
    "log"
    "net"
    pb "workspace/test/protos"
    //pb "workspace/testwork/protos"
)

const (
    port = ":50051"
)

type myserver struct{}

//这里myserver实现了SayHello
func (s *myserver) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.Response, error) {
    fmt.Print("receive " + in.Name)

    ///////下面这一段也可以不用的 演示而已
    //也可以定义很多返回
    d1 := &pb.Datas{
        Id:     1,
        Number: "111",
        Tdatas: []*pb.Tdata{ // 直接取最底层
            {Address: "北京", Telphone: 1333333333, Money: 88888888.88, Live: true, Person: []byte("路人甲")},
            {Address: "上海", Telphone: 1444444444, Money: 9999999999999.88, Live: false, Person: []byte("路人乙")},
        },
    }
    d2 := &pb.Datas{
        Id:     2,
        Number: "222",
        Tdatas: []*pb.Tdata{ // 直接取最底层
            {Address: "广州", Telphone: 15555555555, Money: 66666666666.88, Live: true, Person: []byte("路人丁")},
            {Address: "成都", Telphone: 1666666666, Money: 9999999.88, Live: false, Person: []byte("路人丙")},
        },
    }

    //可以创建一个数据集合 继续复杂点
    ds := *&pb.DBS{}
    ds.Dbs = append(ds.Dbs, d1)
    ds.Dbs = append(ds.Dbs, d2)

    //定义返回数据
    return &pb.Response{
        Status: pb.Response_SUCCESS,
        Msg:    &pb.HelloReply{Message: "receive " + in.Name},
        Data:   &pb.Datas{Id: 99999, Number: "{'liuixn':'123456789987654321'}"}, //可以就 指定一个返回
        Db:     &ds,
    }, nil
}

func main() {
    //绑定端口
    lis, err := net.Listen("tcp", port)
    if err != nil {
        log.Fatal("fail to listen")
    }
    s := grpc.NewServer()
    pb.RegisterDevopsServer(s, &myserver{})
    s.Serve(lis)
}

4).编写客户端

示例:
package main

import (
    "context"
    "fmt"
    "google.golang.org/grpc"
    "log"
    pb "workspace/test/protos"
    //pb "workspace/testwork/protos"
)

const (
    address = "localhost:50051"
)

func main() {
    conn, err := grpc.Dial(address, grpc.WithInsecure()) // 链接grpc
    if err != nil {
        log.Fatal("err;;;;;;;;;;", err)
    }
    c := pb.NewDevopsClient(conn)                                                                         // 生成grpc客户端
    res, _ := c.SayHello(context.Background(), &pb.HelloRequest{Name: "liuxintest first protobuf  hhhh"}) // 发送约定的数据
    fmt.Println(res)

}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,711评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,079评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,194评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,089评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,197评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,306评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,338评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,119评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,541评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,846评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,014评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,694评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,322评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,026评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,257评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,863评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,895评论 2 351

推荐阅读更多精彩内容

  • gRPC介绍 gRPC 是一个高性能、开源、通用的RPC框架,由Google推出,基于HTTP/2协议标准设计开发...
    莫名FCJ阅读 1,915评论 1 6
  • gRPC 是一个高性能、通用的开源RPC框架,基于HTTP/2协议标准和Protobuf序列化协议开发,支持众多的...
    小波同学阅读 19,482评论 6 19
  • 再次重新按这个教程操作时发现中间遇到一些报错,所以重新写了一个细节补充的Golang-grpc 加 gateway...
    正为疯狂阅读 5,873评论 0 10
  • 1.简介 在gRPC中,客户端应用程序可以直接调用不同计算机上的服务器应用程序上的方法,就像它是本地对象一样,使您...
    第八共同体阅读 1,872评论 0 6
  • 趟子手陈七道:“白…白…白二死了。” 唉,害一个兄弟白白丢了性命。 在【老头貌似吃惊的,问:“是谁杀的?你们赌钱打...
    少叔夜阅读 519评论 0 5