这篇文章主要是微服务服务端的实践。node
开始开发前须要先配置好Go的开发环境,能够看我写的基于Golang的微服务——上手篇git
在 GOPATH目录下的src目录下建立咱们的实战项目目录 tech,切换到这个目录github
go get github.com/micro/go-micro //用于开发的微服务的RPC框架,是micro架构的基础
go get github.com/micro/protoc-gen-micro // 用于生成Protobuf的代码
go get github.com/micro/micro // 工具集安装,会自动将 micro加入环境变量
复制代码
Go Micro提供分布式系统开发的核心库,包含RPC与事件驱动的通讯机制。micro的设计哲学是可插拔的架构理念,她提供可快速构建系统的组件,而且能够根据自身的需求剥离默认实现并自行定制。golang
Go Micro 把分布式系统的各类细节抽象出来web
注册(Registry) 注册提供了服务发现机制来解析服务名到地址上。它可使用Consul、etcd、zookeeper、dns、gossip等等提供支持。服务使用启动注册关机卸载的方式注册。服务能够选择性提供过时TTL和定时重注册来保证服务在线,以及在服务不在线时把它清理掉。算法
选择器(Selector) 选择器是构建在注册这上的负载均衡抽象。它容许服务被过滤函数过滤掉不提供服务,也能够经过选择适当的算法来被选中提供服务,算法能够是随机、轮询(客户端均衡)、最少连接(leastconn)等等。选择器经过客户端建立语法时发生做用。客户端会使用选择器而不是注册表,由于它提供内置的负载均衡机制。json
传输(Transport) Transport是服务与服务之间同步请求/响应的通讯接口。和Golang的net包相似,可是提供更高级的抽象,请容许咱们能够切换通讯机制,好比http、rabbitmq、websockets、NATs。传输也支持双向流,这一强大的功能使得客户端能够向服务端推送数据。api
代理(Broker) Broker提供异步通讯的消息发布/订阅接口。对于微服务系统及事件驱动型的架构来讲,发布/订阅是基础。一开始,默认咱们使用收件箱方式的点到点HTTP系统来最小化依赖的数量。可是,在go-plugins是提供有消息代理实现的,好比RabbitMQ、NATS、NSQ、Google Cloud Pub Sub等等。bash
编码(Codec) 编码包用于在消息传输到两端时进行编码与解码,能够是json、protobuf、bson、msgpack等等。与其它编码方式不一样,咱们支持RPC格式。因此咱们有JSON-RPC、PROTO-RPC、BSON-RPC等格式。websocket
编码包把客户端与服务端的编码隔离开来,并提供强大的方法来集成其它系统,好比gRPC、Vanadium等等。
Server(服务端) Server包是使用编写服务的构建包,能够命名服务,注册请求处理器,增长中间件等等。服务构建在以上说的包之上,提供独立的接口来服务请求。如今服务的构建是RPC系统,在将来可能还会有其它的实现。服务端容许定义多个不一样的编码来服务不一样的编码消息。
Client(客户端) 客户端提供接口来建立向服务端的请求。与服务端相似,它构建在其它包之上,它提供独立的接口,经过注册中心来基于名称发现服务,基于选择器(selector)来负载均衡,使用transport、broker处理同步、异步消息。
上面的这些组件均可以在micro中,从更高的角度当作是服务(Service)
若是按照文章开头执行的那三个命令行,用的GOPROXY 代理下载的依赖包,会有一个问题,获取到的examples不是最新的。会有不少报错,我本身的解决办法是直接将目录切换到
cd $GOPATH/pkg/mod/github/micro
git clone github.com/micro/examples examples
cd examples/greeter
复制代码
用 git clone 直接下载最新的官网示例包 greeter示例 按照这个示例的说明文档运行 最后发现调试 API 时出现报错
{"id":"go.micro.client","code":500,"detail":"error selecting go.micro.srv.greeter node: not found","status":"Internal Server Error"}
复制代码
刚开始找不到缘由,去github用蹩脚英语提问,丢人现眼了一回。哈哈,可是学到东西就行,我是这么安慰本身的。 我在运行示例的时候,只执行了三个脚本:
go run api/api.go
micro api --handler=api
curl http://localhost:8080/greeter/say/hello?name=John
复制代码
前两个命令行正常,第三个报错。去提issue,有个老外很快回复我了,但我仍是一脸懵逼。最后尝试先执行
go run srv/main.go
复制代码
就正常了,目前代码里的逻辑理解的不深刻,之后回过头来探个究竟吧.最新版本的注册中心没有指定consul了,运行micro web
,能够启动 micro web工具集合,访问localhost:8082
就能够看到注册的微服务名称了。
go run main.go --registry=consul
复制代码
就能够在consul自带的UI控制面板里找到对应注册的服务(go.micro.srv.greeter)
题外话:我的经验,平常开发过程当中若是遇到问题跨不过去,能够多查查资料,请教别人,一时解决不了的暂时放下,隔段时间回头在看,不少时候都会有新的思路和解决办法,不要死怼着问题不放。还有就是代码若是逻辑实现太复杂了,请停下来,想下是否是本身的实现思路有问题,多半就是实现方式有问题,不会有很复杂的代码的。血泪教训,之前本身遇到问题了就是猛怼,身边也没有人能够请教。其实那是不对的,很浪费时间。
官方示例运行正常了就来尝试下写本身的服务吧。根据以前提到的
如何才能使用micro?
来试试按照这两步走会遇到什么妖魔鬼怪吧
微服务中有个关键需求点,就是接口的强定义。Micro使用protobuf来完成这个需求。 GOPATH 文件夹下新建文件夹 popular/proto
touch popular.proto
复制代码
建立好原型文件后,编辑文件内容
syntax = "proto3";
service Popular {
rpc Ping(PingRequest) returns (PingResponse) {}
}
message PingRequest {
string name = 1;
}
message PingResponse {
string popularing = 2;
}
复制代码
文件的第一行指定了你使用的是proto3的语法. 咱们定义Popular处理器,它有一个Ping方法。它有PingRequest入参对象及PingResponse出参对象,两个对象都有一个字符串类型的参数。
在定义好原型后咱们得使用protoc及micro的插件编译它,micro插件能够帮助生成go micro须要的原型文件。切换到$GOPATH/src
目录,执行命令:
protoc --proto_path=$GOPATH/src/popular/proto:. --micro_out=. --go_out=. popular/proto/popular.proto
复制代码
运行这个命令时可能会报错
-bash: protoc: command not found
复制代码
那是须要下面这个工具来生成protobuf代码文件,它们负责生成定义的go代码实现
brew install protobuf // 若是失败就下载源码包本身编译,加入到环境变量,我是这么整的
go get github.com/golang/protobuf/{proto,protoc-gen-go}
go get github.com/micro/protoc-gen-micro
复制代码
protobuf 源码编译安装会有一些报错,忽略就行。安装参考
一切正常后会在 proto 文件夹下生成
popular.micro.go popular.pb.go
复制代码
须要实现几个需求:
切换到 popular
文件夹下,建立文件 main.go
cd popular && touch main.go
复制代码
编辑main.go 文件
package main
import (
"context"
"fmt"
micro "github.com/micro/go-micro"
proto "popular/proto"
)
type Popular struct{}
func (g *Popular) Ping(ctx context.Context, req *proto.PingRequest, rsp *proto.PingResponse) error {
rsp.Popularing = "Ping " + req.Name // (Popularing, Name 首字母都要大写 )
return nil
}
func main() {
// 建立新的服务,这里能够传入其它选项。
service := micro.NewService(
micro.Name("popular"),
)
// 初始化方法会解析命令行标识
service.Init()
// 注册处理器
proto.RegisterPopularHandler(service.Server(), new(Popular))
// 运行服务
if err := service.Run(); err != nil {
fmt.Println(err)
}
}
复制代码
[卡在这里不能动了,缘由不说。。。] 干了一成天,终于把微服务搭建起来了,有时间再整理文章吧,得休息下了,头晕眼花。。 贴一张图:服务发现与注册用的是Consul
这篇关于服务端的文章到这里暂告一段落
想继续深刻能够看我下一篇文章:基于Golang的微服务——Micro实践(二)