得益于Go语言的编译快性能高特色,在云原生时代其做为服务端编程语言发展迅速,尤为是微服务领域,已逐渐造成一个良好的生态,基于Golang的微服务框架现在有不少,如go-kit、go-micro、kite、gizmo等,每一种都自有其优势。今天就来探一探go-micro框架。
go-micro是基于Go语言实现的插件化RPC微服务框架,与go-kit,kite等微服务框架相比,它具备易上手、部署简单、工具插件化等优势。html
go-micro框架提供了服务发现、负载均衡、同步传输、异步通讯以及事件驱动等机制,它尝试去简化分布式系统间的通讯,让咱们能够专一于自身业务逻辑的开发。因此对于新手而言,go-micro是个不错的微服务实践的开始。node
下图为官方博客提供的go-micro架构图:git
go-micro是组件化的框架,每个基础功能都是一个interface,方便扩展。同时,组件又是分层的,上层基于下层功能向上提供服务,总体构成go-micro框架。
go-micro的组件包括:github
全部以上组件功能共同构成一个go-micro微服务。编程
两个微服务之间的通讯是基于C/S模型,即服务发请求方充当Client,服务接收方充当Server。
其通讯过程大体以下图:windows
上图大体描绘了go-micro服务内各组件的职责与交互。架构
纸上得来终觉浅,下面就来搭建环境,实现一个简单的基于go-micro的微服务。
为简单起见,client与server之间咱们使用点对点的同步方式(Transport),即无需消息中间件(Broker),注册中心采用consul系统。负载均衡
服务注册中心咱们选择consul:框架
brew install consul
运行consul:启动Consul agent的开发模式:异步
consul agent -dev
该命令快速启动一个单节点的consul,且为集群的领袖
查看Consul集群的成员:打开另外一个终端执行:
consul members
中止Agent:使用 Ctrl-C,优雅的关闭Agent
也能够经过WebUI来查看各service状态:http://localhost:8500/
micro是以go-micro框架为核心的微服务管理工具,经过它能够方便查看go-micro服务状况。
在$GOPATH目录下,执行go get github.com/micro/micro
,该命令会在bin目录($GOBIN)下生成micro(.exe)工具
micro命令行工具能够提供诸如服务列表查看、服务详情查看、调用服务接口等功能。
protoc:Protobuf(Protocol Buffers - Google's data interchange format)编译器:
brew install protobuf
go get github.com/micro/protobuf/{proto,protoc-gen-go}
,该命令会在bin目录下生成protoc-gen-go(.exe)工具,protoc编译器利用protoc-gen-go插件将.proto文件转换为Golang源文件go get github.com/micro/protoc-gen-micro
,该命令会在bin目录下生成protoc-gen-micro(.exe),protoc编译器利用protoc-gen-micro插件将.proto文件转换为micro代码风格文件goprotobuf编译参数:
-I
参数:指定import路径,能够指定多个-I
参数,编译时按照顺序查找,不指定时默认查找当前目录--go_out
:Golang编译支持,支持如下参数
- `plugins=plugin1+plugin2`:指定插件,支持grpc/micro,即:plugins=grpc+micro - `M`参数:指定导入的.proto文件路径编译后对应的goalng包名(不指定默认.proto文件中import语句路径) - `import_prefix=xxx`:为全部import路径添加前缀,主要用于编译子目录内的多个proto文件 - `import_path=foo/bar`:指定未声明package或go_package的文件的包名,最右边的斜线前的字符会被忽略
至此,go-micro框架的编程环境已基本搭建好,接下来就是写代码了。
下面实现一个Hello服务:它接收一个字符串类型参数请求,返回一个字符串问候语:Hello 『参数值』。
1)定义API
建立proto/hello.proto文件:
使用protobuf文件来定义服务API接口
syntax = "proto3"; service Hello { rpc Ping(Request) returns (Response) {} } message Request { string name = 1; } message Response { string msg = 1; }
执行protoc
命令,生成当前pb文件的go实现:
protoc --go_out=plugins=micro:. ./proto/hello.proto
2)建立service
建立services/hello.go文件:
package main import ( "context" "fmt" proto "winmicro/proto" micro "github.com/micro/go-micro" ) type Hello struct{} func (h *Hello) Ping(ctx context.Context, req *proto.Request, res *proto.Response) error { res.Msg = "Hello " + req.Name return nil } func main() { service := micro.NewService( micro.Name("hellooo"), // 服务名称 ) service.Init() proto.RegisterHelloHandler(service.Server(), new(Hello)) if err := service.Run(); err != nil { fmt.Println(err) } }
3)模拟client
建立Clients/helloclient.go文件:
package main import ( "context" "fmt" proto "winmicro/proto" micro "github.com/micro/go-micro" ) func main() { service := micro.NewService(micro.Name("hello.client")) // 客户端服务名称 service.Init() helloservice := proto.NewHelloService("hellooo", service.Client()) res, err := helloservice.Ping(context.TODO(), &proto.Request{Name: "World ^_^"}) if err != nil { fmt.Println(err) } fmt.Println(res.Msg) }
启动consul以后
执行micro list services
查看当前已有服务:
> micro list services consul
执行go run services/hello.go
命令,启动hellooo服务:
>go run services/hello.go 2018/11/29 20:18:08 Listening on [::]:61463 2018/11/29 20:18:08 Broker Listening on [::]:61464 2018/11/29 20:18:08 Registering node: hellooo-74122f56-4728-4449-a9d4-6c3c85ba2fcb ....
再次执行micro list services
查看当前已有服务:
> micro list services consul hellooo
即hellooo服务已启动
注 经过WebUI来查看各service信息:http://localhost:8500/
请求服务
执行go run clients/helloclient.go
命令,向hellooo服务发起请求:
>go run clients/helloclient.go Hello World ^_^
https://github.com/micro/go-m...
https://micro.mu/docs/go-micr...
https://lixiangyun.gitbooks.i...
https://github.com/hb-go/micro