科技改变生活 · 科技引领未来

  • 首页
  • 资讯
  • 技术
  • 百科
  • 问答
  • 学习
  • 看看
  • 站长
  • 生活
  • 快讯

首页 > 学习 > 科技政策

op7s手机多少钱(学习grpc文件)

时间:2022-10-08 10:11 作者:李熙

1、wikipedia概念在分布式计算,远程过程调用(英语:RemoteProcedureCall,缩写为RPC)是一个计算机通信协议。该协议允许运行于一台计算机的程序调用另一个地址空间(通常为一个开放网络的一台计算机)的子程序,而程序员就

1、wikipedia概念

在分布式计算,远程过程调用(英语:Remote Procedure Call,缩写为 RPC)是一个计算机通信协议。该协议允许运行于一台计算机的程序调用另一个地址空间(通常为一个开放网络的一台计算机)的子程序,而程序员就像调用本地程序一样,无需额外地为这个交互作用编程(无需关注细节)。RPC是一种服务器-客户端(Client/Server)模式,经典实现是一个通过发送请求-接受回应进行信息交互的系统。

如果涉及的软件采用面向对象编程,那么远程过程调用亦可称作远程调用或远程方法调用,例:Java RMI。

RPC是一种进程间通信的模式,程序分布在不同的地址空间里。如果在同一主机里,RPC可以通过不同的虚拟地址空间(即便使用相同的物理地址)进行通讯,而在不同的主机间,则通过不同的物理地址进行交互。许多技术(常常是不兼容)都是基于这种概念而实现的。

op7s手机多少钱(学习grpc文件)

2、http和rpc的区别

1、http指的是一个应用层协议,它提供的只是一个传输协议

2、rpc讲的是一个远程过程调用,它是一个过程,一个rpc架构包含了多个层级,以dubbo的架构来

rpc其实架构很简单,就是下面一图,但是具体实现上差异还是有点,比如我们所了解的 http + json 只能说是dubbo 只能说是dubbo的最下层实现,所以 rpc相对来说偏向于服务治理这一块

3、为什么我们需要rpc框架,http1.1 提供的rest api不行吗

1、不支持长连接,keepalive

2、http1.1 ping-pang client - server http , 建立很多个连接 (http tcp 连接慢,传输/窗口)

3、rpc 多路复用能力 (http2/3) client - server (io) ,server 包 (二进制) -> go 顺序 http2 奇偶

4、并发性

5、rpc tcp 传输 -> http1.1 纯文本 头部, rcp hello 行头体

5、 json rpc

4、比较出名的rpc框架

  • Java: JNI , WebService , Dubbo ,HSF ,spring的Feign那一套,grpc
  • Golang: gorpc ,grpc 等
  • C++:Svrkit ,grpc 等

大厂用的吧,各大厂都有自己的轮子,比如 thrift,gprc,Tars,brpc ,motan, dubbo 还有很多吧

其实论生态的话,绝对是开源项目的生态比较好,所以开源项目中生态比较好的就是 grpc,thrift,dubbo ,使用难度上来看 dubbo是最简单的,如果你们全Java的话它是个不错的选择!

2、grpc介绍

gRPC 是一个现代的开源高性能远程过程调用(Remote Procedure Call,RPC)框架,可以在任何环境中运行。它可以高效地连接数据中心内部和跨数据中心的服务,并为负载平衡、跟踪、健康检查和身份验证提供可插拔的支持。它也适用于最后一英里的分布式计算连接设备,移动应用程序和浏览器的后端服务。

1、开源的grpc官方,主要提供的能力

  • 服务调用(提供有stream流,请求响应类型的)
  • 负载均衡 (提供xsd协议)
  • 权限(安全方面)

2、grpc主要采用的技术

  • 传输层:http2协议
  • 序列化层:protobuf
  • 负载均衡:xsd

3、推荐学习文章,其实grpc是奔着一个规范去走了,所以在开源项目中所使用grpc的项目有很多,云原生中大量的项目使用grpc

关于序列化和反序列化的思考

关于HTTP2相关知识

XDS标准引入GRPC

关于xsd的学习

➜  grpc-go git:(master) ✗ tree -L 2 . ├── api ## pb 项目(不同业务组名称是不一样的,像我们组直接叫项目名字直接叫api) │   ├── Makefile ## 脚本 │   ├── bin ## protoc / protoc-gen-go/ protoc-gen-gofast 脚本用来生成pb文件 │   ├── dto ## 传输层数据 │   ├── go.mod │   ├── go.sum │   └── third ## rpc接口,我们这里叫做third └── service ## 业务项目     ├── client.go     ├── common ##common     ├── go.mods     ├── go.sum     ├── lbs-service.go     ├── service ## 具体业务层     └── user-service.go

3、protobuf介绍

1、介绍和文档

Protocol Buffers 是一种与语言无关、平台无关、可扩展的序列化结构数据的方法,它可用于(数据)通信协议、数据存储等。Protocol Buffers 是一种灵活,高效,自动化机制的结构数据序列化方法-可类比 XML,但是比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更为简单。你可以定义数据的结构,然后使用特殊生成的源代码轻松地在各种数据流中使用各种语言进行编写和读取结构数据。你甚至可以更新数据结构,而不破坏由旧数据结构编译的已部署程序。

  • wiki: https://en.wikipedia.org/wiki/Protocol_Buffers
  • protobuf是 Google 的语言中立、平台中立、可扩展的结构化数据序列化机制
  • 编译器使用 c + + 编写,高性能!
  • 支持各种开发语言,有效解决了跨平台问题,跨平台开发
  • 其实就是 pb 核心的一点:高性能、高压缩率、兼容性比较高
  • 语法简单,学习难度较低
  • github官方地址:https://github.com/protocolbuffers/protobuf
  • protobuf go support (golang):https://github.com/golang/protobuf
  • protobuf go support (gogo):https://github.com/gogo/protobuf
  • 官方文档:https://developers.google.com/protocol-buffers/
  • 相当的火热,在c/cpp/java/go/云原生/Native App 中火热程度很高,使用范围也很广, 学习只有好处没有坏处

2、基础学习

1、基本格式

syntax = "proto3"; // 默认走的是 proto2,所以需要强制指定,pb3比pb2语法上简单 package dto; //当前文件的package,我们项目不喜欢使用前缀类似于 project-name.dto,因为根本不会存在多个项目互相引用!根据你们需求去决定 import "dto/demo.proto"; // import 其他文件,相对于--proto_path 路径的相对路径  option java_multiple_files = true; option java_package = "com.grpc.api.third"; //java包的路径 option go_package="api/dto";// go的包路径(切记一定要写全,和go的import有关系,如果写 dto,那么别人引入你就是 dto了,显然是引入不到的,一定要写全)  message SearchRequest { // 每个字段都有四块组成: 字段规则,类型,名称,编号   string query = 1;   int32 page_number = 2;   int32 result_per_page = 3;   repeated string hobby = 4; }

2、类型

  • 字符串:string ,(默认为"")
  • 整型:int32,int64,uint32,uint64 (默认为0)
  • 浮点:double,float (默认为0)
  • 字节流:bytes (默认为nil)
  • 布尔类型:bool ,(默认false)
  • 枚举:enum (默认为0,枚举的第一个值必须是0)
  • map类型: 比如map (默认为nil)
  • oneof 类型,它是一个结构体,但是它定义你结构体中只能赋值一个字段,就算你有多个字段!(默认为nil)

3、编号

​ 消息定义中的每个字段都有一个唯一的编号。这些字段编号用于以消息二进制格式标识字段,在使用消息类型后不应更改。注意,范围1到15中的字段编号需要一个字节进行编码,包括字段编号和字段类型。范围16到2047的字段编号采用两个字节。因此,应该为经常出现的消息元素保留数字1到15。记住为将来可能添加的频繁出现的元素留出一些空间。

  • 大小限制:1-2^29-1 , 19000 through 19999 不能使用

4、字段规则

  • singular,默认类型就是这个,不需要申明
  • repeated, 类似于数组,go里面默认就转换成了数组,是个list所以不会自动去重

5、注释

两种格式,和java/c++/go保持一致

  // 注释

6、删除/保留字段

message SearchRequest {   string query = 1;   int32 page_number = 2;   int32 result_per_page = 3;   repeated string hobby = 4;    reserved  15, 9 to 11;   reserved "foo", "bar"; }    

7、其他

1、支持任意的结构体嵌套

message Outer {                  // Level 0   message MiddleAA {  // Level 1     message Inner {   // Level 2       int64 ival = 1;       bool  booly = 2;     }   }   message MiddleBB {  // Level 1     message Inner {   // Level 2       int32 ival = 1;       bool  booly = 2;     }   } }

2、任意类型

​ 这里代表的不是任意的数据类型,指的是Message 类型!

syntax="proto3"; package dto;  option java_multiple_files = true; option java_package = "com.grpc.api.third"; option go_package="dto";  import "google/protobuf/any.proto";  message City {     uint64 id=1;     string name=2;     // 引用包名称.类型名称     google.protobuf.Any any = 9; }

3、map类型

message City {     uint64 id=1;     string name=2;     // 引用包名称.类型名称     google.protobuf.Any any = 9;     map demo=10; }

4、oneof类型

下面为例子,就是你只能选择 v3 或者 v4 !

message BenchMarkModel {     string v1=1;     uint64 v2=2;     oneof test_oneof {         string v3 = 3;         uint32 v4 = 4;     } }

8、import 作用

首先 import 是引用 路径的,那个路径是相对于你的--proto_path 路径的路径

比如我的项目中,引用就是,项目路径是/Users/fanhaodong/project/programing/grpc-go/api

bin/protoc          --proto_path /Users/fanhaodong/project/programing/grpc-go/api          --proto_path /Users/fanhaodong/go/src/github.com/gogo/protobuf/protobuf          --plugin=protoc-gen-go=bin/protoc-gen-go          --go_out=.          ./dto/*.proto

那么我的import 可以来自于两个路径

import "dto/city.proto"; import "google/protobuf/any.proto";

首先dto/city.proto ,绝对路径是/Users/fanhaodong/project/programing/grpc-go/api/dto/city.proto 我们的编译目录是/Users/fanhaodong/project/programing/grpc-go/api ,所以去除前缀就是dto/city.proto

然后看google/protobuf/any.proto 也是同理

9、package 作用

主要是区分 package 区分 import 可能引用了相同的 message ,所以就需要 package指定,一般package命令为比如我的目录是api/dto,所以一般命名为api.dto ,一般来说跨业务组是不允许相互引用,只能引用一些common的结构

比如下面这种情况,我引用了两个 文件dto/demo.proto,google/protobuf/any.proto

demo.proto 定义了 Any 类型

message Any {   string name=1; }

但是我这时候没有告诉我到底用的哪个 Any,此时编译期无法解决

syntax="proto3"; package dto;  option java_multiple_files = true; option java_package = "com.grpc.api.dto"; option go_package="dto";  import "google/protobuf/any.proto"; import "dto/demo.proto";  message City {     uint64 id=1;     string name=2;     // 引用包名称.类型名称     Any any = 9;     map demo=10; }

可以看到

type City struct {     state         protoimpl.MessageState     sizeCache     protoimpl.SizeCache     unknownFields protoimpl.UnknownFields      Id   uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`     Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`     // 引用包名称.类型名称     Any  *Any              `protobuf:"bytes,9,opt,name=any,proto3" json:"any,omitempty"`     Demo map[string]uint64 `protobuf:"bytes,10,rep,name=demo,proto3" json:"demo,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` }

所以存在这种问题,此时就需要 package解决引用的问题

message City {     uint64 id=1;     string name=2;     // 引用包名称.类型名称     google.protobuf.Any any = 9;     map demo=10; }

3、Protobuf的编码算法原理

Encoding

4、编译工具

  • 官方编译工具,比如我是mac os ,可以直接下载wget https://github.com/protocolbuffers/protobuf/releases/download/v3.9.0/protoc-3.9.0-osx-x86_64.zip
  • gogoprotobuf ,对于需要编码为Golang时,其编码效率贼高而且还省内存, 对立项目是 https://github.com/golang/protobuf
  • 如何编译了 ? --proto_path指定include 目录,--plugin 指定需要用的plugin, 最后一个参数指的是引用的pb文件

使用测试的pb 文件

syntax="proto3"; package dto;  option java_multiple_files = true; option java_package = "com.grpc.api.dto"; option go_package="api/dto";  import "google/protobuf/any.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/timestamp.proto"; import "google/protobuf/empty.proto"; import "google/protobuf/wrappers.proto";  message BenchMarkModel {     string v1=1;     uint64 v2=2;     int64 v3=3;     double v4=4;     float v5=5;     bool v6=6;     enum Corpus {         UNIVERSAL = 0;         WEB = 1;         IMAGES = 2;         LOCAL = 3;         NEWS = 4;         PRODUCTS = 5;         VIDEO = 6;     }     Corpus v7=7;     map v8=8;     oneof test_oneof {         string v9 = 9;         uint32 v10 = 10;     }     bytes v11=11;     message Msg {         string content=1;     }     repeated Msg v12=12;     google.protobuf.Any v13 = 13;     google.protobuf.Duration v14=14;     google.protobuf.Empty v15=15;     google.protobuf.UInt64Value v16=16;     google.protobuf.Timestamp v17=17; }

2、测试代码

package dto import (     "github.com/golang/protobuf/proto"     "github.com/stretchr/testify/assert"     "google.golang.org/protobuf/types/known/anypb"     "google.golang.org/protobuf/types/known/durationpb"     "google.golang.org/protobuf/types/known/emptypb"     "google.golang.org/protobuf/types/known/timestamppb"     "google.golang.org/protobuf/types/known/wrapperspb"     "math"     "testing"     "time" ) func newModel(b testing.TB) *BenchMarkModel {     any := &anypb.Any{}     if err := any.MarshalFrom(wrapperspb.UInt64(math.MaxUint64)); err != nil {         b.Fatal(err)     }     return &BenchMarkModel{         V1: "hello 12345424234234",         V2: math.MaxUint64,         V3: math.MaxInt64,         V4: math.MaxFloat64,         V5: math.MaxFloat32,         V6: true,         V7: BenchMarkModel_PRODUCTS,         V8: map[string]uint32{"1": 1, "2": 2, "3": 3},         TestOneof: &BenchMarkModel_V10{             V10: math.MaxUint32,         },         V11: []byte("hello 1234567890"),         V12: []*BenchMarkModel_Msg{             {Content: "1"}, {Content: "2"}, {Content: "3"},         },         V13: any,         V14: durationpb.New(time.Hour * 24),         V15: &emptypb.Empty{},         V16: wrapperspb.UInt64(math.MaxUint64),         V17: timestamppb.Now(),     } }  func TestGo_Marshal(t *testing.T) {     model := newModel(t)     protoBufBody, err := proto.Marshal(model)     if err != nil {         t.Fatal(err)     }     newModel := &BenchMarkModel{}     if err := proto.UnmarshalMerge(protoBufBody, newModel); err != nil {         t.Fatal(err)     }     assertModel(t, model, newModel) }  func assertModel(t testing.TB, model *BenchMarkModel, newModel *BenchMarkModel) {     assert.Equal(t, model.V1, newModel.V1)     assert.Equal(t, model.V2, newModel.V2)     assert.Equal(t, model.V3, newModel.V3)     assert.Equal(t, model.V4, newModel.V4)     assert.Equal(t, model.V5, newModel.V5)     assert.Equal(t, model.V6, newModel.V6)     assert.Equal(t, model.V7, newModel.V7)     assert.Equal(t, model.V8, newModel.V8)     assert.Equal(t, model.TestOneof, newModel.TestOneof)     assert.Equal(t, model.V11, newModel.V11)      for index, _ := range model.V12 {         assert.Equal(t, model.V12[index].Content, newModel.V12[index].Content)     }      assert.Equal(t, model.V13.Value, newModel.V13.Value)     assert.Equal(t, model.V13.TypeUrl, newModel.V13.TypeUrl)     assert.Equal(t, model.V14.Nanos, newModel.V14.Nanos)     assert.Equal(t, model.V14.Seconds, newModel.V14.Seconds)     assert.Equal(t, model.V15, newModel.V15)     assert.Equal(t, model.V16.Value, newModel.V16.Value)     assert.Equal(t, model.V17.Seconds, newModel.V17.Seconds)     assert.Equal(t, model.V17.Nanos, newModel.V17.Nanos) }

1、使用protoc-gen-go

这里需要知道的是--go_out 需要找到protoc-gen-go 的位置,如果你的protoc-gen-go放在PATH目录下就可以直接使用,但是我们一般不会放在PATH目录下,所以需要指定--plugin=protoc-gen-go=bin/protoc-gen-go,意思就是告诉位置所在

bin/protoc          --proto_path .          --proto_path /Users/fanhaodong/go/grpc/include          --plugin=protoc-gen-go=bin/protoc-gen-go          --go_out=../          ./dto/*.proto

帮助

  --plugin=EXECUTABLE         Specifies a plugin executable to use.                               Normally, protoc searches the PATH for                               plugins, but you may specify additional                               executables not in the path using this flag.                               Additionally, EXECUTABLE may be of the form                               NAME=PATH, in which case the given plugin name                               is mapped to the given executable even if                               the executable's own name differs.

其实规则就是

--plugin=protoc-gen-go=bin/protoc-gen-go 对应的必须是--go_out,它走的是拼前缀,比如你执行这个也OK,因为是看前缀说话

bin/protoc          --proto_path .          --proto_path /Users/fanhaodong/go/grpc/include          --plugin=protoc-gen-go1=bin/protoc-gen-go          --go1_out=../          ./dto/*.proto

开始进入话题进行benchmark

func BenchmarkGo_Marshal(b *testing.B) {     model := newModel(b)     for i := 0; i < b.N; i++ {         if _, err := proto.Marshal(model); err != nil {             b.Fatal(err)         }     } }  func BenchmarkGo_UnMarshal(b *testing.B) {     model := newModel(b)     result, err := proto.Marshal(model)     if err != nil {         b.Fatal(err)     }     newModel := &BenchMarkModel{}     for i := 0; i < b.N; i++ {         if err := proto.UnmarshalMerge(result, newModel); err != nil {             b.Fatal(err)         }     } }

测试结果

➜  dto git:(master) ✗ go test -run=none -bench=BenchmarkGo_ -benchmem -count=4 .  goos: darwin goarch: amd64 pkg: api/dto BenchmarkGo_Marshal-12            428138              2624 ns/op             600 B/op         17 allocs/op BenchmarkGo_Marshal-12            431756              2552 ns/op             600 B/op         17 allocs/op BenchmarkGo_Marshal-12            418332              2595 ns/op             600 B/op         17 allocs/op BenchmarkGo_Marshal-12            503637              2520 ns/op             600 B/op         17 allocs/op BenchmarkGo_UnMarshal-12          537661              2824 ns/op             555 B/op         19 allocs/op BenchmarkGo_UnMarshal-12          542142              2398 ns/op             554 B/op         19 allocs/op BenchmarkGo_UnMarshal-12          509076              2420 ns/op             563 B/op         19 allocs/op BenchmarkGo_UnMarshal-12          544599              2063 ns/op             553 B/op         19 allocs/op PASS ok      api/dto 11.746s

2、使用protoc-gen-gofast

1、首先需要安装

go install github.com/gogo/protobuf/protoc-gen-gofast ## protoc-gen-gofast 工具 go get github.com/gogo/protobuf ## 代码依赖

2、这里使用了Any类型,所以需要我们做gofast的兼容,这点比较坑,官网也写了如何解决:https://github.com/gogo/protobuf , 因此编译命令需要添加一些参数!

bin/protoc          --proto_path .          --proto_path /Users/fanhaodong/go/src/github.com/gogo/protobuf/protobuf          --plugin=protoc-gen-gofast=bin/protoc-gen-gofast          --gofast_out=         Mgoogle/protobuf/any.proto=github.com/gogo/protobuf/types,         Mgoogle/protobuf/duration.proto=github.com/gogo/protobuf/types,         Mgoogle/protobuf/field_mask.proto=github.com/gogo/protobuf/types,         Mgoogle/protobuf/struct.proto=github.com/gogo/protobuf/types,         Mgoogle/protobuf/type.proto=github.com/gogo/protobuf/types,         Mgoogle/protobuf/api.proto=github.com/gogo/protobuf/types,         Mgoogle/protobuf/descriptor.proto=github.com/gogo/protobuf/types,         Mgoogle/protobuf/empty.proto=github.com/gogo/protobuf/types,         Mgoogle/protobuf/source_context.proto=github.com/gogo/protobuf/types,         Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types,         Mgoogle/protobuf/wrappers.proto=github.com/gogo/protobuf/types:../          ./dto/*.proto

3、最坑的来了,也就是它为啥不兼容的问题!

1)原来定义的any现在不能使用了,也就是说api的使用方式上变了!

import (     "encoding/json"     "github.com/gogo/protobuf/types"     "github.com/golang/protobuf/proto"     "github.com/stretchr/testify/assert"     "math"     "testing"     "time" )  func newModel(b testing.TB) *BenchMarkModel {     any, err := types.MarshalAny(&types.UInt64Value{         Value: math.MaxUint64,     })     if err != nil {         b.Fatal(err)     }     return &BenchMarkModel{         V1: "hello 12345424234234",         V2: math.MaxUint64,         V3: math.MaxInt64,         V4: math.MaxFloat64,         V5: math.MaxFloat32,         V6: true,         V7: BenchMarkModel_PRODUCTS,         V8: map[string]uint32{"1": 1, "2": 2, "3": 3},         TestOneof: &BenchMarkModel_V10{             V10: math.MaxUint32,         },         V11: []byte("hello 1234567890"),         V12: []*BenchMarkModel_Msg{{Content: "1"}, {Content: "2"}, {Content: "3"},},         V13: any,         V14: types.DurationProto(time.Hour * 24),         V15: &types.Empty{},         V16: &types.UInt64Value{             Value: math.MaxUint64,         },         V17: types.TimestampNow(),     } }

3、benchmark

➜  dto git:(master) ✗ go test -run=none -bench=BenchmarkGoFast_ -benchmem -count=4 . goos: darwin goarch: amd64 pkg: api/dto BenchmarkGoFast_Marshal-12               1579309               748 ns/op             240 B/op          2 allocs/op BenchmarkGoFast_Marshal-12               1487350               840 ns/op             240 B/op          2 allocs/op BenchmarkGoFast_Marshal-12               1389932               765 ns/op             240 B/op          2 allocs/op BenchmarkGoFast_Marshal-12               1532866               784 ns/op             240 B/op          2 allocs/op BenchmarkGoFast_UnMarshal-12             1000000              1173 ns/op             382 B/op          7 allocs/op BenchmarkGoFast_UnMarshal-12             1235286              1001 ns/op             384 B/op          7 allocs/op BenchmarkGoFast_UnMarshal-12             1083085              1191 ns/op             371 B/op          7 allocs/op BenchmarkGoFast_UnMarshal-12             1000000              1144 ns/op             382 B/op          7 allocs/op PASS ok      api/dto 14.907s

3、总结

1、从性能上来看确实提升至少是一倍起步,基本带来了翻倍的收益(官方给的数据是5-10倍的性能提升,它还提供了更快的!1),然后主要是内存分配上可以看到内存优势很大!

2、但从效率上来说其实对于业务开发其实是不关注太多这些的,开发效率和质量决定一切!

3、关于选择protoc-gen-gofast 还是选择protoc-gen-go ,看你们业务已开始用的什么,如果开始就选择protoc-gen-gofast 那么可以一直用,但是一开始就选择protoc-gen-go 那就恶心了,基本上无法切换到protoc-gen-gofast,可以选择使用protoc-gen-gogo

4、gRPC

1、介绍和文档

​ gRPC 是一个现代的开源高性能远程过程调用(Remote Procedure Call,RPC)框架,可以在任何环境中运行。它可以高效地连接数据中心内部和跨数据中心的服务,并为负载平衡、跟踪、健康检查和身份验证提供可插拔的支持。它也适用于最后一英里的分布式计算连接设备,移动应用程序和浏览器的后端服务。

  • c系列(官方系): https://github.com/grpc/grpc
  • java 系:https://github.com/grpc/grpc-java
  • go 系:https://github.com/grpc/grpc-go
  • 官方文档:https://grpc.io/
  • 如何使用 wireshark 抓取 grpc && http2 包:https://grpc.io/blog/wireshark/
  • grcp 和 http2的关系: https://grpc.io/blog/grpc-on-http2/

2、写rpc接口 (IDL)

第一个lbs接口是:

syntax="proto3"; package third;  option java_multiple_files = true; option java_package = "com.grpc.api.third"; option go_package="api/third";  import "google/protobuf/wrappers.proto"; import "dto/city.proto";  service LbsService {     rpc getCityInfo (google.protobuf.UInt64Value) returns (dto.City); }

第二个是user服务接口:

syntax="proto3"; package third;  option java_multiple_files = true; option java_package = "com.grpc.api.third"; option go_package="api/third";  import "dto/user.proto"; import "google/protobuf/wrappers.proto";  service UserService {     rpc GetUserInfo (google.protobuf.UInt64Value) returns (dto.User); }

3、gofast编译rcp接口

如何编译,我们使用的是 gofast进行编译,所以需要修改一些参数,关于参数如何使用的,这些绝对百度不来,主要是看人家这个gofast项目的文档和example

这里就是需要告诉一下编译的时候使用 plugin=grpc, 然后还需要改变一下引用,最后就是指定一下输出目录

格式就是--{pugin}_out=k1=v1,k2=v2,k3=v3....,kn=vn:{输出目录}

bin/protoc          --proto_path .          --proto_path /Users/fanhaodong/go/src/github.com/gogo/protobuf/protobuf          --plugin=protoc-gen-gofast=bin/protoc-gen-gofast          --gofast_out=plugins=grpc,         Mgoogle/protobuf/any.proto=github.com/gogo/protobuf/types,         Mgoogle/protobuf/duration.proto=github.com/gogo/protobuf/types,         Mgoogle/protobuf/field_mask.proto=github.com/gogo/protobuf/types,         Mgoogle/protobuf/struct.proto=github.com/gogo/protobuf/types,         Mgoogle/protobuf/type.proto=github.com/gogo/protobuf/types,         Mgoogle/protobuf/api.proto=github.com/gogo/protobuf/types,         Mgoogle/protobuf/descriptor.proto=github.com/gogo/protobuf/types,         Mgoogle/protobuf/empty.proto=github.com/gogo/protobuf/types,         Mgoogle/protobuf/source_context.proto=github.com/gogo/protobuf/types,         Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types,         Mgoogle/protobuf/wrappers.proto=github.com/gogo/protobuf/types:../          ./third/*.proto

4、go写接口服务调用

1、服务端代码

package main  import (     "api/dto"     "api/third"     "context"     "fmt"     "github.com/gogo/protobuf/types"     "google.golang.org/grpc"     "log"     "net"     "service/common"     "time" )  type lbsServiceServer struct{}  func (lbsServiceServer) GetCityInfo(ctx context.Context, cityId *types.UInt64Value) (*dto.City, error) {     if cityId.Value == 0 {         return nil, fmt.Errorf("not found city: %d", cityId.Value)     }     return &dto.City{         Id:         cityId.Value,         Name:       fmt.Sprintf("beijing-%d", cityId.Value),         Properties: map[string]string{"time": time.Now().Format(time.RFC3339)},         Msg: &dto.OneofMessage{             TestOneof: &dto.OneofMessage_Name{                 Name: "demo",             },         },     }, nil }  func main() {     // 创建一个tcp listener     lis, err := net.Listen("tcp", common.LbsService)     if err != nil {         log.Fatalf("failed to listen: %v", err)     }     // 创建一个 grpc server     ser := grpc.NewServer()     // 注册信息     third.RegisterLbsServiceServer(ser, lbsServiceServer{})     // 启动服务     if err := ser.Serve(lis); err != nil {         log.Fatalf("failed to serve: %v", err)     } }

2、客户端代码

package main  import (     "api/third"     "context"     "github.com/gogo/protobuf/types"     "google.golang.org/grpc"     "log"     "service/common" )  func main() {     conn, err := grpc.Dial(common.LbsService, grpc.WithInsecure(), grpc.WithBlock())     if err != nil {         log.Fatal(err)     }     client := third.NewLbsServiceClient(conn)     cityInfo, err := client.GetCityInfo(context.Background(), &types.UInt64Value{Value: 1})     if err != nil {         log.Fatal(err)     }     log.Printf("%s", cityInfo) }

请求一下可以看到完全可以调通

2021/04/16 20:10:48 id:1 name:"beijing-1" properties:"time" value:"2021-04-16T20:10:48+08:00" > msg:"demo" > 

5、如何抓包

1、配置pb位置,比如我的就是在/Users/fanhaodong/project/programing/grpc-go/api目录下

2、选择抓取网卡

本地的话一般是就是本地回环网络,我的本地网卡就是lo0

然后选择过滤的端口,比如我刚刚启动的服务端口是8001, 然后记得客户端调用一次服务端,就可以看到以下的流量包了

此时可以监控到流量,但是是tcp,所以我们很难看懂,需要需要分析一下,因此需要decode一下包

所以大概你就可以看到所有包的情况了!

6、http2

7、grpc conn pool

1、如果发现 [] conn

2、如果发现 conn (http2 http3 )

3、

5、使用go-micro 搭建grpc服务

1、官方文档

https://github.com/Anthony-Dong/go-micro

微解决了在云中构建服务的关键需求。它利用微服务体系结构模式,并提供一组作为平台构建块的服务。微处理分布式系统的复杂性,并提供更简单的可编程抽象。

其实看起来和那个现在比较火的 dapr 很像,抽象的级别很高,更加傻瓜式,但是你要是研究的话往往会增大学习成本

2、快速开始的话,你就根据官方提供的就行了

2、提供的能力

1、基本上人家帮代码给你封装好了,直接用

2、提供api-gateway 方便使用

3、提供有 一些内部提供的服务治理能力,需要细细学习

4、有兴趣可以学习一下

相关话题

  • 防水卷材多少钱一卷(又大跌)
  • 茶兀多少钱一瓶(重磅)
  • 大连水费多少钱一吨(大连市11月3日停水通知)
  • 汽车水泵多少钱(发动机水泵异响)
  • 六类网线多少钱一米(上个追光科技)
  • 铼多少钱一克(价值超百亿)
  • 房屋保险一年多少钱(职工医保一年3000多)
  • 头颅磁共振多少钱(颈椎病的人)
  • 宝墨园门票多少钱(暑假带娃去领略岭南文化)
  • 车子喷漆要多少钱(都是喷漆)
  • 激光去疤多少钱(激光祛疤后)
  • 医院ct是检查多少钱(去医院看病)
  • 查肾功能多少钱(年底想体检)
  • 金桔多少钱一斤(不是所有的小橘子都是)
  • 生菜多少钱一斤(菜比肉贵)
  • 石斛一斤多少钱(长于悬崖峭壁的)
  • 劳动仲裁多少钱(一次漂亮的劳动仲裁)
  • 反物质多少钱一克(地球上最贵的物质有多贵)
  • 沙虫干多少钱一斤(泥地里的这种虫子)
  • 玻璃价格多少钱一平方(光伏玻璃产业专题报告)

热门推荐

  • 《江西省科技创新促进条例》计划明年1月1日起实行!
  • 古钟二锅头46度多少钱(白酒板块将添新成员)
  • 装wifi多少钱一年(香港办宽带怎么这么贵)
  • 做饭保姆一个月多少钱(55岁保姆哭诉)
  • 咸阳到西安打车多少钱(西安咸阳机场停车费多少钱一天)
  • 荣威550多少钱一台(荣威550插电式混动版月用车成本为1929)
  • 一克拉钻石多少钱大概(预算5)
  • 西凤酒15年多少钱一瓶(西凤酒全面提价)
  • 液晶显示屏多少钱一块(1099元的165Hz显示器)
  • 二手苹果x能卖多少钱(二手宝马X1怎么买)
  • 插座维修上门多少钱(这是典型的贪小便宜吃大亏)
  • 刷脸支付加盟费多少钱(5万代理费)
  • 面包机多少钱一台家用(Panasonic)
  • 23年工龄退休拿多少钱(工龄21年)
  • 二手木地板多少钱一平方(买二手实木地板靠谱吗)
  • 在银行工作工资多少钱一个月(26岁银行转岗做出纳)
  • 葛陶中紫砂壶市场价多少钱(做壶)
  • 卤江南加盟费是多少钱(食品饮料行业之连锁行业研究)
  • 奔富707多少钱一瓶(葡萄酒界的低调天王奔富)
  • 信阳脱毛多少钱(多地兴建家禽屠宰场)

李熙

关注
免责声明:本文章由会员“李熙”发布,如果文章侵权,请联系我们处理,本站仅提供信息存储空间服务 如因作品内容、版权和其他问题请于本站联系

关注排行榜

  1. 1《江西省科技创新促进条例》计划明年1月1日起实行!
  2. 2活牛多少钱一斤(牛价格多少钱一头)
  3. 3铝单板多少钱一平方(福建铝单板的厂家哪家质量好)
  4. 4一箱牛奶多少钱(是不是我这种妈妈才会给孩子买29一箱的临期纯牛奶)
  5. 5普洱茶一般多少钱(一克就有五亿霉菌)
  6. 6gtx1060多少钱(幽灵线)
  7. 7一辆电动车多少钱(2500元左右电动车)
  8. 8苹果6换主板多少钱(花钱花在刀刃上)
  9. 9养老保险每年多少钱(养老保险每年缴费8000到1万元)
  10. 10代缴社保一个月多少钱(社保缴费每月2600)

编辑精选

Copyright ©2009-2022 KeJiTian.Com, All Rights Reserved

版权所有 未经许可不得转载

增值电信业务经营许可证备案号:辽ICP备14006349号

网站介绍 商务合作 免责声明 - html - txt - xml