Go语言micro之快速搭建微服务
背景
go-micro给我们提供了一个非常便捷的方式来快速搭建微服务,而且并不需要提前系统了解micro,下面用一个简单的示例来快速实现一个服务。
创建proto文件
因为我们要做微服务,那么就一定有服务端和客户端,这两个端通过什么格式进行内容传输,就涉及到了序列化,比较主流的序列化协议就是json和protobuf,因为protobuf是以二进制传输的,体积比较小,所以传输速度也相对较快,今天就以protobuf来进行演示。
下面使用proto3的语法在protos目录创建文件greeter.proto
,该文件定义一个名为greeter
的服务,以及对应的入参和出参。
syntax = "proto3"; package protos; service greeter { rpc hello (request) returns (response) { }; } message request { string name = 1; } message response { string greeting = 2; }
生成go文件
生成go文件之前,要先确保本机安装了protobuf,如果在终端输入protoc
没有打印出帮助文档,那么就是未安装。
$ protoc usage: protoc [option] proto_files parse proto_files and generate output based on the options given: -ipath, --proto_path=path specify the directory in which to search for imports. may be specified multiple times; directories will be searched in order. if not ……
可以通过官方文档提示的命令进行安装。
go get github.com/micro/protoc-gen-micro/v2
安装成功之后,通过protoc命令将greeter.proto
文件生成出对应的go文件。
protoc --proto_path=./protos --micro_out=./protos --go_out=./protos ./protos/greeter.proto
-
--proto_path
是greeter.proto文件所在的路径 -
--micro_out
是生成.go
文件的所在目录,该文件被用于创建服务 -
--go_out
是生成.go
文件的所在目录,该文件被用于做数据序列化传输
可以根据需求自定义输出目录,我这边输出到了protos目录,现在可以看到protos目录中生成了两个文件。
greeter.pb.go greeter.pb.micro.go
实现服务
因为刚才已经通过protobuf定义了服务的接口,所以接下来需要实现对应的服务。
第一步,实现定义的服务接口
在生成的greeter.pb.micro.go
文件中,可以看到我们greeter.proto
文件中一个名为greeterhandler
的接口。
type greeterhandler interface { hello(context.context, *request, *response) error }
我们需要先实现该接口,接下来创建server.go文件,定义结构体greeter,并实现hello方法。
type greeter struct { } func (g *greeter) hello(context context.context, req *protos.request, rsp *protos.response) error { rsp.greeting = "hello " + req.name return nil }
hello方法的后两个参数刚好就是我们前面所生成的greeter.bp.go
文件中定义的request和response结构体。在方法内部,将请求参数的name前面拼接上了hello
字符串,并且赋值给了response的greeting变量。
第二步,初始化服务
我们创建一个名为greeter
的服务。
func main() { service := micro.newservice( micro.name("greeter"), ) service.init() }
调用micro.newservice
方法来创建一个新的服务,该方法的参数是可变参数,可以通过micro中的一系列方法来设置服务的参数,本次示例中只配置服务的名称,记得在创建完服务后执行service.init
方法来初始化,micro版本建议使用v2。
第三步,注册服务到handler
func main() { service := micro.newservice( micro.name("greeter"), ) service.init() err := protos.registergreeterhandler(service.server(), new(greeter)) if err != nil { fmt.println(err) } }
第四步,将服务跑起来
if err := service.run(); err != nil { fmt.println(err) }
完整代码如下
package main import ( "context" "fmt" "github.com/micro/go-micro/v2" ) type greeter struct { } func (g *greeter) hello(context context.context, req *request, rsp *response) error { rsp.greeting = "hello " + req.name return nil } func main() { service := micro.newservice( micro.name("greeter"), ) service.init() err := protos.registergreeterhandler(service.server(), new(greeter)) if err != nil { fmt.println(err) } if err := service.run(); err != nil { fmt.println(err) } }
现在将服务端跑起来。
$ go run server.go 2020-03-27 11:28:20 starting [service] greeter 2020-03-27 11:28:20 server [grpc] listening on [::]:63763 2020-03-27 11:28:20 registry [mdns] registering node: greeter-8afc1183-a159-4473-a567-c13b83d1d75c
实现客户端
创建client.go
文件
func main() { service := micro.newservice(micro.name("greeter.client")) service.init() greeter := protos.newgreeterservice("greeter", service.client()) rsp, err := greeter.hello(context.todo(), &protos.request{name: "pingye"}) if err != nil { fmt.println(err) } fmt.println(rsp.greeting) }
执行客户端文件,输出hello pingye
,执行成功。
$ go run client.go hello pingye
服务注册到了哪里?
在启动服务端的时候从终端输出的信息可以看出,有一个名为greeter
的服务注册到了registry
。
2020-03-27 11:28:20 starting [service] greeter 2020-03-27 11:28:20 server [grpc] listening on [::]:63763 2020-03-27 11:28:20 registry [mdns] registering node: greeter-8afc1183-a159-4473-a567-c13b83d1d75c
registry是go-micro的注册模块,作用是将服务注册到某个介质,以方便客户端使用。注册模块默认支持cache、consul、etcd、k8s、mdns、memory等多种介质,默认使用的是mdns。
var ( defaultregistry = newregistry() // not found error when getservice is called errnotfound = errors.new("service not found") // watcher stopped error when watcher is stopped errwatcherstopped = errors.new("watcher stopped") )
mdns主要用于在没有传统dns服务器的情况下,在局域网中实现主机之间的发现与通讯,它遵从dns协议。
go语言组件示例开源库,欢迎star
https://github.com/enochzg/golang-examples
上一篇: Jquery为单选框checkbox绑定单击click事件
下一篇: 测试开发阿里巴巴笔试题2020