内容简介:微服务想必大家都不陌生了。刚接触到示例代码通过目录可以看到这里使用了
微服务想必大家都不陌生了。刚接触到 golang
,那么在 golang
中怎么使用微服务呢。这里使用 gRRC
框架写了一个简单的例子。
环境要求
- go>=1.13; set GO111MODULE=on
- 安装 protoc
- 安装 Protoc plugin-go
示例代码 iris-grpc-example
项目结构
iris-grpc-example │ .gitignore │ go.mod │ go.sum │ README.md │ ├─proto │ README.md │ servers.pb.go │ servers.proto │ └─servers main.go services.go
通过目录可以看到这里使用了 go mod
,当前 golang
版本 1.13
。
proto
使用 Protobuf
定义了通信的IDL,可以理解为 rpc
中接口定义。
-
protocol buf
可扩展的序列化数据结构,在通信协议中使用的比较广泛。比 json
更快,更小。比 xml
更简洁。
servers.proto
syntax = "proto3"; package proto; message Id { int32 id=1; } message Name { string name=1; } message Age { int32 age=1; } // 用户变量 message User { int32 id=1; string name=2; int32 age=3; } // 用户参数 message UserParams{ Name name=1; Age age=2; } // 声明那些方法可以使用rpc service ServiceSearch{ rpc SaveUser(UserParams) returns (Id){} rpc UserInfo(Id) returns (User){} }
简单说明
syntax = "proto3";
声明了 proto
语法版本。
package
声明包名
message Id { int32 id=1; }
接口中使用的变量声明 变量名称: Id
,类型: int32
,等号后面表示字段编号为 1
service ServiceSearch{ rpc SaveUser(UserParams) returns (Id){} rpc UserInfo(Id) returns (User){} }
声明了两个函数 SaveUser(),UserInfo()
是使用 RPC
协议,接收的参数与返回参数分别为什么。
servers.go
该文件是使用 servers.proto
编译生成的
。在完成 servers.proto
之后 在 proto
目录下执行
protoc --go_out=plugins=grpc:. *.proto
Protoc plugin-go grpc
编译命令执行完之后,就会生成 servers.go
。而我们在 go
的模块中实际使用的代码也就是这个文件。
如果有兴趣的同学可以看看里面的代码,主要就是一些参数定义【 我们在proto中所定义的
】,还有一个接口的声明。
...... // ServiceSearchServer is the server API for ServiceSearch service. type ServiceSearchServer interface { SaveUser(context.Context, *UserParams) (*Id, error) UserInfo(context.Context, *Id) (*User, error) } // UnimplementedServiceSearchServer can be embedded to have forward compatible implementations. type UnimplementedServiceSearchServer struct { } func (*UnimplementedServiceSearchServer) SaveUser(ctx context.Context, req *UserParams) (*Id, error) { return nil, status.Errorf(codes.Unimplemented, "method SaveUser not implemented") } func (*UnimplementedServiceSearchServer) UserInfo(ctx context.Context, req *Id) (*User, error) { return nil, status.Errorf(codes.Unimplemented, "method UserInfo not implemented") } func RegisterServiceSearchServer(s *grpc.Server, srv ServiceSearchServer) { s.RegisterService(&_ServiceSearch_serviceDesc, srv) } ......
可以看到最后有一个 RegisterServiceSearchServer
注册服务的方法,接受一个 grpc.Server
与一个 ServiceSearchServer
的接口。而我们在 servers/services.go
中,主要就是实现 ServiceSearchServer
这个接口,并通过 RegisterServiceSearchServer
将接口实现的函数注册 rpc
服务中。
servers
rpc 接口的实现与调用
services.go 接口的实现
package main import ( "context" "fmt" "google.golang.org/grpc" "iris-grpc-example/proto" "log" "math/rand" "net" ) type ServiceSearch struct{} func main() { listen, err := net.Listen("tcp", "127.0.0.1:9527") if err != nil { log.Fatalf("tcp listen failed:%v", err) } server := grpc.NewServer() fmt.Println("services start success") proto.RegisterServiceSearchServer(server, &ServiceSearch{}) server.Serve(listen) } //保存用户 func (Service *ServiceSearch) SaveUser(ctx context.Context, params *proto.UserParams) (*proto.Id, error) { id := rand.Int31n(10) //随机生成id 模式保存成功 res := &proto.Id{Id: id} fmt.Printf("username:%s,age:%d\r\n", params.Name, params.Age) return res, nil } func (Service *ServiceSearch) UserInfo(ctx context.Context, id *proto.Id) (*proto.User, error) { res := &proto.User{Id:id.GetId(),Name:"test",Age:31} return res, nil }
- 实现
ServiceSearchServer
接口,在代码中声明了一个ServiceSearch
来实现了ServiceSearchServer
接口。 -
SaveUser
,实现了proto
中定义的SaveUser
方法,需要注意的是这里需要返回两个参,数第一个是我们预先定好的参数,第二个为定义的错误信息。 -
main
函数声明当前服务的ip以及端口,并创建了一个grpc server
然后通过proto.RegisterServiceSearchServer(server, &ServiceSearch{})
将ServiceSearch
注册到grpc
中
main.go 接口的调用
package main import ( "context" "github.com/kataras/iris/v12" "google.golang.org/grpc" "iris-grpc-example/proto" "log" ) var client proto.ServiceSearchClient func main() { app := iris.New() app.Logger().SetLevel("debug") //debug app.Handle("GET", "/testSaveUser", saveUser) app.Handle("GET", "/testUserInfo", userInfo) app.Run(iris.Addr("127.0.0.1:8080")) } func saveUser(ctx iris.Context) { params := proto.UserParams{} params.Age = &proto.Age{Age: 31} params.Name = &proto.Name{Name: "test"} res, err := client.SaveUser(context.Background(), ¶ms) if err != nil { log.Fatalf("client.SaveUser err: %v", err) } ctx.JSON(res) } func userInfo(ctx iris.Context) { res, err := client.UserInfo(context.Background(), &proto.Id{Id: 1}) if err != nil { log.Fatalf("client.userInfo err: %v", err) } ctx.JSON(res) } func init() { connect, err := grpc.Dial("127.0.0.1:9527", grpc.WithInsecure()) if err != nil { log.Fatalln(err) } client = proto.NewServiceSearchClient(connect) }
这里使用了 iris
作为了一个 client
。与传统 http
的区别主要是在
func init() { connect, err := grpc.Dial("127.0.0.1:9527", grpc.WithInsecure()) if err != nil { log.Fatalln(err) } client = proto.NewServiceSearchClient(connect) }
这里创建了一个 rpc
的 client
。在使用的时候我们只需要调用 services
里面已经写好的函数即可。
测试
\iris-grpc-example>cd servers
开启服务: go run services.go
开启Client: go run main.go
浏览器访问
http://127.0.0.1:8080/testSaveUser { "id": 1 } http://127.0.0.1:8080/testUserInfo { "id": 1, "name": "test", "age": 31 }
期待一起交流
以上所述就是小编给大家介绍的《go-gRPC 初体验》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 降低云游戏延迟优化云游戏体验:贝塞斯达推出Orion技术,还公布了免费体验计划
- PyTorch 初体验
- indexedDB 初体验
- golang爬虫初体验
- Netty 入门初体验
- Ansible初体验
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Ruby原理剖析
[美] Patrick Shaughnessy / 张汉东、秦凡鹏 / 华中科技大学出版社 / 2016-12-1 / 78.80元
《Ruby原理剖析》解开Ruby编程语言的魔法面纱。全书图文并茂、深入浅出地剖析了Ruby编程语言的核心工作原理。作者本着科学实证的精神,设计了一系列实验,帮助读者轻松了解这门编程语言的工作奥秘,包括Ruby如何用虚拟机执行代码,Ruby的垃圾回收算法,以及类和模块在Ruby内部的关系等。一起来看看 《Ruby原理剖析》 这本书的介绍吧!