当前位置: 首页 > news >正文

中国人自己的空间站南京手机网站设计专业

中国人自己的空间站,南京手机网站设计专业,新媒体营销策划,wordpress给分类页加关键词文章目录 一、Protocol Buffer简介二、Protocol Buffer编译器安装三、proto3语言指南四、序列化与反序列化五、引入grpc-gateway1、插件安装2、定义proto文件3、生成go文件4、实现Service服务5、gRPC服务启动方法6、gateway服务启动方法7、main函数启动8、验证 相关参考链接 protobuf官方文档 proto3语法指南 protoc下载地址 grpc-gateway官方文档 grpc-gateway readme swagger安装文档 【当前代码Demo】 一、Protocol Buffer简介 作为一个后端开发我们用的最多的传递信息的协议是http协议。性能需求的提高要求我们转向性能更高的协议这就不得不提到一个由Google公司推广的一个小而快的rpc协议——protocol buffer协议。它到底有着什么样的魔力让大家觉得真香定律。 Protocol Buffer是一个由Google开发的协议是一个可以对结构化数据的序列化和反序列化协议。谷歌开发它的目的是提供一种比XML更好的方式来使系统进行通信。因此他们致力于使其比XML更简单、更小、更快、更易于维护。这个协议甚至超过了JSON,具有更好的性能、更好的可维护性和更小的体积。 另外protoc支持多语言以及跨平台。 天然支持C、C、Java、Python、PHP、Ruby、Kotlin等语言。 不支持Go、Dart等语言。所以基于Go语言需要额外安装插件下面会说到。 Why Protocol Buffer——简单来说它更小、因此也更快。举例如下 // 当前代码位于 https://gitee.com/liuwen766/protobuf-demo.git func TestSerialize(t *testing.T) {// 这个是基于proto生成的personFromProto : pb.Person{Name: 我是小明,Age: 18,PhoneNum: []string{188, 120},Pets: pb.Pets{Type: Cat,Name: Tom,},}marshal1, _ : proto.Marshal(personFromProto)create, _ : os.Create(fileName)defer create.Close()n, err : create.Write(marshal1)if err ! nil {log.Fatal(create.Write(marshal) has err:, err)return}log.Println(proto.Marshal——Serialize Success:, n)// 这个是Go结构体personFromStruct : Person{Name: 我是小明,Age: 18,PhoneNum: []string{188, 120},Pets: Pets{Type: Cat,Name: Tom,},}marshal2, _ : json.Marshal(personFromStruct)create, _ os.Create(fileName)defer create.Close()n, err create.Write(marshal2)if err ! nil {log.Fatal(create.Write(marshal) has err:, err)return}log.Println(json.Marshal——Serialize Success:, n)// 日志输出如下【传递的Person信息一模一样但是基于proto的长度只有38它是二进制数据】//2024/01/22 18:13:16 proto.Marshal——Serialize Success: 38//2024/01/22 18:13:16 json.Marshal——Serialize Success: 107 }二、Protocol Buffer编译器安装 编译proto文件前的环境准备工作只有简单的两个步骤 step1、下载protoc 。 protoc下载地址 #将protoc.exe文件配置到环境变量配置完之后验证 $ protoc --version libprotoc 3.19.4step2、安装go插件。 前面提到过protoc支持多语言包括C、C、Java、Python、PHP、Ruby、Kotlin等语言。 但是不支持Go、Dart等语言。所以基于Go语言需要额外安装插件。只需要下面一个简单的命令。 go get google.golang.org/protobuf/cmd/protoc-gen-go go install google.golang.org/protobuf/cmd/protoc-gen-gogo get 命令会获取依赖包到go env的 GOMODCACHE 目录下。 go intall 命令会将对应的可执行文件安装到go env下的 GOPATH/bin 目录下。 因此需要配置GOPATH/bin为环境变量。否则会报错“‘protoc-gen-go’ 不是内部或外部命令也不是可运行的程序或批处理文件。” 一个简单的proto3文件样例。 // 指定proto语言版本 syntax proto3; // 生成*.pb.go文件的包路径 option go_package /pb; // proto包路径 package protobuf.demo;message Person{string name 1;int32 age 2; }通过protoc生成 *.pb.go 文件 protoc -I . --go_out./proto ./proto/person.proto # 这里的三个 . 都表示当前目录三、proto3语言指南 通过上面编写的简单proto文件可以发现proto文件中定义message与我们创建一个Go语言中的struct结构体类似。针对Go语言中的一些复杂类型例如数组[]int、集合map、枚举enum、嵌套等proto自然也有相对应的定义。 repeated repeated关键字的作用是用来定义数组使用方式是repeated 数组类型 属性名称 字段编号; message Person {repeated string name 1; }map map类型的定义方式是map 键类型值类型 属性名称 字段编号; 这里需要注意对于map的键类型只能定义为基本数据类型但是值的类型可以是任何支持的类型。 message Person {map string, Pets pets 1; } // 嵌套 message Pets{string Type 1;string name 2; }enum 对于枚举的定义需要用到enum关键字。 message Person{Sex sex 5; } enum Sex{Sex_MAN 0;SEX_WOMAN 1; }一个完整示例。 // 指定proto语言版本 syntax proto3; // 生成*.pb.go文件的包路径 option go_package /pb; // proto包路径 package protobuf.demo;message Person{string name 1;int32 age 2;bool marry 3;repeated string phoneNum 4;mapstring, string address 5;Sex sex 6;Pets pets 7; }message Pets{string Type 1;string name 2; }enum Sex{Sex_MAN 0;SEX_WOMAN 1; }定义完proto文件后通过protoc生成 *.pb.go 文件执行如下命令 protoc -I . --go_out./proto ./proto/person.proto # 这里的三个 . 都表示当前目录四、序列化与反序列化 以序列化和反序列化为例演示如何使用由proto编译生成的*.pb.go文件 package protoimport (encoding/jsonlogostestinggoogle.golang.org/protobuf/protoprotobuf-demo/proto/pb )var fileName1 person-proto.txt var fileName2 person-json.txttype Pets struct {Type stringName string }type Person struct {Name stringAge int32PhoneNum []stringAddress map[string]stringPets *Pets }// 序列化 func TestSerialize(t *testing.T) {personFromProto : pb.Person{Name: 我是小明,Age: 18,PhoneNum: []string{188, 120},//Sex: pb.Sex_Sex_MAN,Pets: pb.Pets{Type: Cat,Name: Tom,},}marshal1, _ : proto.Marshal(personFromProto)create, _ : os.Create(fileName1)defer create.Close()n, err : create.Write(marshal1)if err ! nil {log.Fatal(create.Write(marshal) has err:, err)return}log.Println(proto.Marshal——Serialize Success:, n)// why proto?lets look look json.personFromStruct : Person{Name: 我是小明,Age: 18,PhoneNum: []string{188, 120},//Sex: pb.Sex_Sex_MAN,Pets: Pets{Type: Cat,Name: Tom,},}marshal2, _ : json.Marshal(personFromStruct)create, _ os.Create(fileName2)defer create.Close()n, err create.Write(marshal2)if err ! nil {log.Fatal(create.Write(marshal) has err:, err)return}log.Println(json.Marshal——Serialize Success:, n)// 日志输出如下所以说proto更小//2024/01/25 18:13:16 proto.Marshal——Serialize Success: 38//2024/01/25 18:13:16 json.Marshal——Serialize Success: 107 }// 反序列化 func TestDeserialize(t *testing.T) {read, _ : os.ReadFile(fileName1)person : pb.Person{}err : proto.Unmarshal(read, person)if err ! nil {log.Fatal(proto.Unmarshal(read, person) has err:, err)return}log.Printf(Deserialize Success: %v, person) }五、引入grpc-gateway grpc-gateway是protoc的一个插件它会读取proto文件中的grpc服务的定义并将其生成RestFul JSON API并将其反向代理到我们的grpc服务中。 grpc-gatway是在grpc上做的一个拓展。但是grpc并不能很好的支持客户端以及传统的RESTful API。因此grpc-gateway诞生了该项目可以为grpc服务提供HTTPJSON接口。 1、插件安装 首先在项目中去创建一个tools的文件然后执行go mod tidy //go:build tools // build toolspackage toolsimport (_ github.com/envoyproxy/protoc-gen-validate_ github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway_ github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2_ google.golang.org/grpc/cmd/protoc-gen-go-grpc_ google.golang.org/protobuf/cmd/protoc-gen-go )通过执行go install将这些可执行文件安装在GOPATH/bin目录下。 go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2 go install google.golang.org/protobuf/cmd/protoc-gen-go go install google.golang.org/grpc/cmd/protoc-gen-go-grpc2、定义proto文件 // 指定proto语言版本 syntax proto3; // 生成*.pb.go文件的包路径 option go_package /pb;package protobuf.demo;// 导入api注释依赖【注意将这里的注释依赖包放在当前项目的根目录下】 import google/api/annotations.proto;message Book {int32 id 1;string name 2; }message CreateBookRequest {string name 1; }message CreateBookResponse{string code 1;string message 2;Book data 3; }// 定义服务 service BookService {// 创建Bookrpc CreateBook (CreateBookRequest) returns (CreateBookResponse) {option (google.api.http) {// POST /v1/bookspost: /v1/booksbody: *};}; }注意这里需要导入api注释依赖。 由于项目依赖了google的proto文件所以在使用protoc生成go文件的时候需要将依赖的proto文件复制到项目中依赖的proto文件仓库 google/api 和 google/protobuf 。下载下来放在当前项目中的根目录下。注释依赖一般可以自动检测不行就手动配置依赖。 3、生成go文件 执行命令 protoc -I . --grpc-gateway_out./proto/gen --grpc-gateway_opt logtostderrtrue --grpc-gateway_opt pathssource_relative --go_out./proto/gen --go_opt pathssource_relative --go-grpc_out./proto/gen --go-grpc_opt pathssource_relative ./proto/book.proto # 如果报错没有目录则手动创建目录不要被这么长的命令唬住了记住 . 表示当前目录就行。 几个命令分别对应前面安装的三个插件protoc-gen-go、protoc-gen-go-grpc和protoc-gen-grpc-gateway protoc -I . –grpc-gateway_out./proto/gen –grpc-gateway_opt logtostderrtrue --grpc-gateway_opt pathssource_relative –go_out./proto/gen –go_opt pathssource_relative –go-grpc_out./proto/gen –go-grpc_opt pathssource_relative ./proto/book.proto 4、实现Service服务 package serviceimport (contextlogprotobuf-demo/dbpb protobuf-demo/proto/gen/proto )type BookService struct {// 这里是要实现的服务pb.UnimplementedBookServiceServer }// 这里是实现的方法 func (b *BookService) CreateBook(ctx context.Context, req *pb.CreateBookRequest) (*pb.CreateBookResponse, error) {resp : pb.CreateBookResponse{}db.Db.Mux.Lock()defer db.Db.Mux.Unlock()id : db.Db.GetId()book : pb.Book{Name: req.GetName(),Id: id,}err : db.Db.Save(book)if err ! nil {return resp, err}resp.Data booklog.Printf(user %s create a book, %v, db.GetUserId(ctx), book)return resp, nil }5、gRPC服务启动方法 package grpcimport (lognetprotobuf-demo/configprotobuf-demo/grpc/middlepb protobuf-demo/proto/gen/protoprotobuf-demo/servicegoogle.golang.org/grpc )// Run grpc的启动方法 func Run() error {//Step1监听端口用于提供grpc服务grpcAddr : config.GetRpcAddr()listen, err : net.Listen(tcp, grpcAddr)if err ! nil {log.Fatalf(tcp listen failed: %v, err)return err}defer listen.Close()// Step2可以为这个grpc服务加一些定制化的特性option : []grpc.ServerOption{// 这里可以加一些middleware中间件grpc.UnaryInterceptor(middle.AuthInterceptor),}// Step3创建一个grpc服务它是空的服务还不能接收/处理任何请求server : grpc.NewServer(option...)// Step4进行服务注册registerServer(server)log.Printf(Serving gRPC on %s, listen.Addr())// Step5grpc服务接收从监听端口过来的流量请求对外提供服务return server.Serve(listen) }func registerServer(server *grpc.Server) {// 注册 BookService 服务pb.RegisterBookServiceServer(server, service.NewBookService()) }6、gateway服务启动方法 package gatewayimport (contextlognet/httpprotobuf-demo/configprotobuf-demo/gateway/middleprotobuf-demo/handlerpb protobuf-demo/proto/gen/protogithub.com/grpc-ecosystem/grpc-gateway/v2/runtimegoogle.golang.org/grpcgoogle.golang.org/grpc/credentials/insecure )// Run gateway的启动方法 func Run() error {// Step1创建一个客户端连接grpc服务ctx : context.Background()option : []grpc.DialOption{// 这里可以加一些middleware中间件grpc.WithChainUnaryInterceptor(middle.AuthInterceptor),grpc.WithTransportCredentials(insecure.NewCredentials()),}// 创建grpc连接 连接到127.0.0.1:8001conn, err : grpc.DialContext(ctx, config.GetRpcAddr(), option...)if err ! nil {log.Fatalf(dial failed: %v, err)return err}// Step2创建一个ServeMux它是 grpc-gateway 的请求多路复用器。serveMuxOption : []runtime.ServeMuxOption{// 响应拦截runtime.WithForwardResponseOption(middle.Interceptor),// 错误页自定义runtime.WithRoutingErrorHandler(middle.RoutingErrorHandler),// 自定义保留哪些请求头信息到整个上下文中runtime.WithIncomingHeaderMatcher(func(s string) (string, bool) {if s User-Id {return s, true}return runtime.DefaultHeaderMatcher(s)}),}mux : runtime.NewServeMux(serveMuxOption...)// 自定义一些不好用proto编译的接口比如这里的上传/下载接口{if err mux.HandlePath(http.MethodPost, /v1/objects, handler.Upload); err ! nil {return err}if err mux.HandlePath(http.MethodGet, /v1/objects/{name}, handler.Download); err ! nil {return err}}// Step3将http路由注册到前面创建的ServeMux通过grpc-gateway反向代理从而提供http服务err newGateway(ctx, conn, mux)if err ! nil {log.Fatalf(register handler failed: %v, err)return err}// Step4创建一个http服务server : http.Server{Addr: config.GetHttpAddr(), // 127.0.0.1:8002// http服务需要处理的ServeMuxHandler: mux,}log.Printf(Serving Http on %s, server.Addr)// Step5进行监听并提供服务err server.ListenAndServe()if err ! nil {return err}return nil }func newGateway(ctx context.Context, conn *grpc.ClientConn, mux *runtime.ServeMux) error {// 注册 BookService 服务进行反向代理err : pb.RegisterBookServiceHandler(ctx, mux, conn)if err ! nil {return err}return nil }7、main函数启动 package mainimport (logosprotobuf-demo/gatewayprotobuf-demo/grpc )func main() {// 启动grpc服务go func() {err : grpc.Run()if err ! nil {log.Fatal(os.Stderr, err)os.Exit(1)}}()// 启动gateway服务err : gateway.Run()log.Fatal(os.Stderr, err)os.Exit(1) }8、验证 启动服务之后进行接口验证。 # 新增接口 curl --request POST \--url http://localhost:8002/v1/books \--header X-User-Id: \--header content-type: application/json \--data {name: 三国演义 }接下来完成所有的增删改查接口。如下 # 查询接口 curl --request GET \--url http://localhost:8002/v1/books/1 \--header content-type: application/json# 更新接口 curl --request POST \--url http://localhost:8002/v1/books/1 \--header content-type: application/json \--data {id: 1,name: 三国演义2 }# 删除接口 curl --request DELETE \--url http://localhost:8002/v1/books/1 \--header content-type: application/json
http://www.hkea.cn/news/14576975/

相关文章:

  • 旅游网站开发注意点磐安住房和城乡建设部网站
  • 北京网站建设公司哪家实惠玻璃制品东莞网站建设
  • 北京网站seo排名网站优化公司 网络服务
  • 网站封面怎么做网站建设单页
  • 设计网站视频教程沈阳做网站的互联网公司
  • 南通通州建设工程质量监督网站网络项目设计方案
  • 网站开发公司资质山东省示范校建设网站
  • 制作旅游网站网页的代码企业营销型网站有特点
  • 建一个网站大约需要花费多少钱wordpress在header添加
  • 卖营销软件的网站建网站买完域名后怎么做
  • 悬浮网站底部代码北京it行业公司排名
  • 西安地产网站制作公司百度安装应用
  • jquery 手机网站开发微信营销系统平台
  • 宜昌市夷陵区建设局网站东城区网站排名seo
  • 东营网站建设服务商做网站运维的待遇
  • 原型样网站网站改版完成
  • 怎么做直播网站营口化工网站建设
  • jpress wordpress对比百度搜索引擎优化的推广计划
  • 权重高的博客网站手机网站开发环境搭建
  • 网站建设网络公司seo推广外包企业
  • 贵州省建设银行招聘网站非法网站怎么推广
  • 河北邢台做移动网站网站搜索引擎友好性分析
  • 做家教网站怎么样安卓app在线开发
  • 网站策划设计人工智能公司网站建设
  • php网站底部文件网站建设如何财务处理
  • 网站开发语言 aspwordpress 编辑图片无法显示
  • seo网站三种链接北京故宫网页设计
  • 马鞍山的网站建设公司哪家好怎么免费创造自己的网址
  • ps兼职做网站公司建设网站需要固定ip吗
  • 中国那些企业做网站做得好微信调用wordpress