微服务笔记
consul 启动:
在D:soft;只能在 系统自带的cmd启动,不能使用cmder
consul agent -dev -advertise=127.0.0.1
consul 资料:
查看成员:
consul members
查看节点:
curl 127.0.0.1:8500/v1/catalog/nodes
使用DNS协议查看节点信息:
dig @127.0.0.1 -p 8600 Litao-MacBook-Pro.node.consul
这个是列出DNS服务器上的域名与IP地址对应的
consul WEB管理端:http://127.0.0.1:8500
注册服务
curl -X PUT -d '{"Datacenter": "sz-1", "Node": "mysql-1", "Address":
"mysql-1.node.consul","Service": {"Service": "mysql", "tags": ["master","v1"],
"Port": 3306}}' http://127.0.0.1:8500/v1/catalog/register
go-micro 在示例 serivce 运行: 看一下此示例的readme 可以知道好多具体的用法
继续看定义
微服务套件
- API:
类似于网关,是微服务的唯一入口;将对微服务访问的HTTP请求转换成RPC请求;
micro 套件与具体实现的服务api的关系(拿greeter举例)
先跑micro api;再跑greeter api ;micro会将 请求(http)转发(rpc协议)到 greeter 服务上去;
查看micro/example/greeter/api及 greeter readme
这个例子处理流程是这样的:
- new 一个 Say注册Handler
- 当 curl http://localhost:8080/greeter/say/hello?name=John
- 会调用Say 的hello 方法
- hello 方法再请求 go.micro.srv.greeter服务的Say 的Hello方法(greeter服务里用到了接口注册,有点绕,小心)
- postman 访问时 参数 需要 x-www-form-urlencoded
- url构成: 服务名/handler对象名/方法名
greeter web 也是类似的关系
- Web:
提供一套可视化跟整个微服务交流的WEB界面; 路由/[serviceName]可以访问相应的微服务
跟micro的关系 与 api跟micro的关系一样
命令行里运行:micro web
界面上Request的是JSON,如:{"Name":"Jhon"}
可以测试微服务的各接口
- Sidecar:
go-micro的http接口;通过这些接口,可以将非golang服务整合到一起;
- Bot:
是微服务内部的机器人,外部可以通过Slack, HipChat, XMPP等与机器人交流;
- CLI:
通过命令行,执行微服务及其它命令;
Micro example
- flags: 可以自定义命令行参数
- shutdown: 服务退出
- micro/cli/readme: micro的使用命令说明(这个不是example下面)
- greeter/cli/python: python语言调用微服务的实例
- flags: 自定义命令行参数
- broker: 消息发布与订阅
- 初始默认值: go-micro/cmd/cmd.go
Go Micro组成
- Registry:
服务注册
- Selector:
做负载均衡;当客户端请求一个微服务A时,selector首先查询注册的服务A所有节点,让其中一个节点提供服务;目前使用的负载均衡算法有轮询、对访问来源hash后指定、黑名单
example/client/selector:演示了selector的用法;
示例是返回的服务的第一个节点:services[0].Nodes[0];没有看到 使用 random/ roundrobin算法
新建的api 项目,selector选择随机的
go-micro/selector/default.go: 是默认 defaultSelector
go-micro/client/rpc_client.go: rpcClient的Call方法里调用了 选择节点使用selector.select()、请求结束后调用 selector.mark();selector 的其它方法没有找到在哪里调用的
可以作为一种服务,专门提供筛选结点的功能; client在启动时指定 -- selector(这个没有吃透)
- Broker:(用于异步通信)
broker是一种很方便切换的发布与订阅的接口;微服务是基于事件驱动的;目前实现了消息队列系统如nats、rabbitmq 和 http(开发环境使用)
rabbitmq:MQ全称为Message Queue,消息队列(MQ)是一种应用程序对应用程序的通信方法。
example/broker: producer调用了go-micro的broker 发送(pub)信息;consumer 接收(sub)信息w
例子应该使用的 http 来传递消息(因为我本机没有安装其它的消息队列系统),启动的时候 指定--broker=kafka
微服务会实现 订阅的方法(micro new 创建项目会自动创建subscriber)
- Transport:(用于同步通信)
是点对点发送消息的接口;目前实现了http、rabbitmq、nats;此接口可以无缝切换;
- Client:
通过client发起RPC请求;client融合了注册服务、selector、broker和transport;它也包含了重试、超时、上下文的使用等等
写客户端可以参考example/client,包含了基本的全部用法
- Server:server 提供实现微服务的接口;响应RPC请求;
consul分布式跑起来
- consul agent -dev -client=10.8.230.15 //监听10.8.230.15
- ./consul agent -advertise=10.8.230.17 -client=10.8.230.17 -data-dir=/tmp -bind=10.8.230.17 -bootstrap -server
- srv --registry_address=10.8.230.15 //服务注册
- micro --registry_address=10.8.230.15 list services //查询所有服务
- client --registry_address=10.8.230.15
- srv --server_address=:54001 //服务启动时指定监听的IP与端口(这样写法是:默认IP+指定端口)
go交叉编译
参考文章 本地环境已经搭建完成并可以编译
- build.bat在Go根目录下的src,运行也要在此目录
- 接下来执行的命令
set GOOS=linux
set GOARCH=amd64
go build -o autopackage //在工程根目录下执行;-o跟的是编译出来的名称(结果会在当前目录下面)
GOOS=windows GOARCH=386 go build -o hello.exe hello.go
GOOS=darwin GOARCH=amd64 go build hello.go
docker pull microhq/micro 已下载好
使用 docker run microhq/micro --registry_address=10.8.210.228 list services
写的具体服务部署在docker:
docker run -d --name=autopackage-service2 -p 54002:54002 autopackage --store_apk_dir=/val --registry_address=10.8.210.228 --server_advertise=10.8.210.211:54002 --server_address=:54002
生成protoc-gen-go 与 proto.go
go get github.com/micro/protobuf/{proto,protoc-gen-go} 生成生成protoc-gen-go 执行失败的 替换方案(go get = git clone & go install )
- go build github.com/micro/protobuf/proto
- go build github.com/micro/protobuf/protoc-gen-go(会在当前目录下生成protoc-gen-go.exe)
- proto.exe 与 protoc-gen-go.exe 放于同一目录下面
- protoc --go_out=plugins=micro:. greeter.proto
- go_out : 输入go文件所在目录
- plugins : 指定了插件名称, protoc.exe 会在系统path目录里搜索
- greeter.proto : 最后是需要转化的proto文件
- 这种等号连写的方式还没有搞清楚
- protoc -IPath: path是 import的搜索路径,也可以是--protoc_path=Path
- api项目中生成protoc时,要使用默认namespace go.micro,否则会报api.Request没有定义 (api.Request是在引入的protoc中定义的)
- api 项目中生成proto时候,请在f:mygosrc 路径下执行:
protoc --proto_path=F:/mygo/src --go_out=plugins=micro:. F:/mygo/src/autopackage_api/proto/task/task.proto
- protobuf 中repeated表示字段 类似list
分析了实例(micro/example) 了解清楚了broker selector
没有解决的问题:client 如何找到服务,因为注册的地址不同;
已解决: 启动时添加参数 --registry_address
服务已经退出了,但是consul里还显示存在
在启动服务时 加上 TTL(这一招不行)
退出服务还是得ctrl+c(已经找到了方法:example/shutdown)
服务与节点:
go-micro/registry/consul_registry.go、consul_registry_test.go跟consul交互的方法
consul_registry.go的GetService方法:
Registry接口被consulRegistry实现
当调用selector时,registry调用具体实现的GetService方法获取所有正常的节点,获取节点的原理是:selector的registry访问consul的/v1/health/service/+serviceName接口
(如果registry是其它的,刚注意具体实现)
访问consul 以获取服务与接口信息通过 github.com/hashicorp/consul这个库
github.com/hashicorp/consul/api/catalog.go:其中写了多数跟consul交互的接口
go-micro/registry/registry.go:访问服务及节点
通过consul查看服务:http://10.8.230.15:8500/v1/health/service/kf.srv.autopackage
Micro 与Go-Micro的关系
Micro 提供微服务开发的相关工具链
Go-Micro 是具体实现了微服务的SDK
服务退出 删除服务节点
consul接口地址+serviceId
eg:
http://localhost:8500/v1/agent/service/deregister/kf.srv.autopackage_task-913f6119-1689-11e7-b8ec-10c37b6a4139
Go-Micro 定时任务
···service := micro.NewService(
micro.Name("autopackage_task"),
micro.Version("latest"),
micro.Context(ctx),
micro.AfterStart(func() error {
return handler.InitRegistry()
}),
micro.AfterStart(func() error {
go handler.IntervalTask()//这里也要重启一个goroutine一个运行定时任务,否则会阻塞主goroutine,导致在退出服务时不会deregistry
return nil
}),
)
···
Go-Micro的errors库
github.com/micro/go-micro/errors
包含的错误类型:
- BadRequest 对应http 错误的400
- Unauthorized 对应http 错误401
- Forbidden 对应http 错误403
- NotFound 对应http 错误404
- InternalServerError 对应http 错误500
micro 的go-web模块
- 使用方法跟go-micro类似
- 轻量的web框架
- 用micro new 生成的项目实例中 handler请求是访问的其它服务
- 不能像go-micro一样自定义参数