sunchaochaichai / bookinfo

bookinfo服务用于演示go-kit实现微服务

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

BookInfo (For Demo)

BookInfo 使用golang编写,实现简单的书籍查询服务。
项目基于go-kit搭建,并集成常用组件.

PS:仅供演示使用.

  • 服务崩溃恢复
  • 基础代码自动生成
  • 依赖库管理
  • 实时编译
  • 命令行支持
  • grpc支持
  • grpc => http 协议转换支持
  • 服务熔断
  • 访问频率限制
  • prometheus采集支持
  • docker启动
  • 自定义中间件
  • 实时debug图表信息
  • pprof分析器,图表化
  • 生成火焰图
  • 服务优雅退出 graceful
  • yaml配置文件支持
  • env配置文件支持
  • zipkin全链路追踪
  • test demo
  • benchmark demo

文件目录结构

.
├── docker //docker相关
├── pb //pb文件保存目录
├── vendor //依赖库
├── glide.yaml //依赖库配置文件
├── book-servername //书籍服务
|   ├── bin //go build后bin包
|   ├── cmd //服务启动&访问入口
|   |   ├── servername //客户端
|   |   └── servername-server //服务端
|   ├── conf //多环境配置文件保存目录
|   |   ├── container.yaml //容器模式下配置文件
|   |   └── local.yaml //本地开发模式下配置文件
|   ├── global //全局生效 服务实例&变量&配置
|   |   ├── conf.go //实例化配置文件
|   |   ├── db.go //数据库相关
|   |   ├── errors.go //错误信息配置
|   |   ├── global.go //全局变量&配置 入口
|   |   ├── grpcclient.go //grpc客户端
|   |   ├── logger.go //日志实例
|   |   ├── pid.go //记录运行时服务pid
|   |   ├── redis.go //redis相关
|   |   └── zipkin.go //zipkin相关
|   ├── handlers //业务逻辑目录
|   |   ├── handlers.go //最终服务实现入口文件
|   |   ├── hooks.go //钩子(graceful在此实现)
|   |   ├── middlewares.go //中间件加载文件
|   |   ├── mw_ep_name... //endpoint类型中间件
|   |   └── mw_svc_name... //svc类型中间件
|   ├── models //数据模型
|   |   ├── migrate.go //数据库迁移文件
|   |   ├── modelname.go //模型文件
|   |   └── ... //模型文件
|   ├── runtime //保存程序运行时数据
|   |   ├── pid //服务运行pid
|   |   ├── logs //日志保存目录
|   |   └── ... //其他运行时数据
|   ├── svc
|   |   ├── client //服务访问相关
|   |   |   ├── cli //命令行方式
|   |   |   ├── grpc //grpc方式
|   |   |   └── http //http方式
|   |   ├── server //服务启动相关
|   |   |   └── run.go //服务启动逻辑
|   |   ├── endpoints.go //endpoints实现
|   |   ├── transport_grpc.go //transport grpc实现
|   |   └── transport_http.go //transport http实现
|   ├── .realize.yaml //实时自动编译配置文件
|   └── .env //项目运行环境变量
└── book-servername ... //其他服务,目录结构相同

开始之前

# docker环境需要
$ docker version
$ docker-compose version

# 安装go命令行服务监控工具
$ go get -v github.com/divan/expvarmon

生成自动化代码

# *ps:生成动作会覆盖现有代码
# books-details
$ truss $GOPATH/src/bookinfo/pb/details/details.proto \
  --svcout bookinfo/bookdetails-service
> 代码生成目录 $GOPATH/bookinfo/bookdetails-service

# books-comments
$ truss $GOPATH/src/bookinfo/pb/comments/comments.proto \
  --svcout bookinfo/bookcomments-service
> 代码生成目录 $GOPATH/bookinfo/bookcomments-service

启动服务

# docker
$ cd $GOPATH/src/bookinfo
$ docker-compose -f docker/docker-compose.yaml up -d
# *ps:修改本地代码后 容器中服务会自动重新编译启动

访问服务

### books-details
# grpc
$ docker-compose -f docker/docker-compose.yaml \
  exec books-details \
  go run /go/src/bookinfo/bookdetails-service/cmd/bookdetails/main.go detail -id 1
# http
$ curl "http://localhost:5001/v1/detail?id=1"

### books-comments
# grpc
$ docker-compose -f docker/docker-compose.yaml \
  exec books-comments \
  go run /go/src/bookinfo/bookcomments-service/cmd/bookcomments/main.go get -id 1
# http
$ curl "http://localhost:5011/v1/get?id=1"

崩溃恢复

当服务出现panic会记录错误信息,程序不会退出。grpc,http均支持

熔断

# 满足以下规则进行熔断:
#   异常请求超过10%
#   并发请求超过1000
> {"code":429,"msg":"too many connections"}

限频

# 满足以下规则进行限频率:
#   每秒 30000次请求
# *ps:配置规则为 N秒 M个请求
> {"error":"rate limit exceeded"}

优雅退出

# *ps:docker-compose方式启动时会启动自动编译服务,测试优雅退出功能需要在本地运行服务,或者以pid 1进程运行在docker中
# 测试优雅退出可以在代码中增加sleep进行测试
$ cat $GOPATH/src/bookinfo/bookdetails-server/runtime/pid | xargs kill -s SIGINT

prometheus监控

$ open http://127.0.0.1:9090

zipkin调用链路跟踪

$ open http://127.0.0.1:9411

Debug

实时图表化数据

$ open http://localhost:5003/debug/charts/

命令行同时观察多个服务

$ expvarmon \
  -i 1s \
  -ports="127.0.0.1:5003,127.0.0.1:5013" \
  -vars="Goroutines,mem:memstats.Alloc,mem:memstats.TotalAlloc,mem:memstats.HeapAlloc,mem:memstats.Sys,mem:memstats.HeapSys,mem:memstats.HeapObjects,mem:memstats.HeapIdle,mem:memstats.HeapInuse,memstats.NumGC,duration:memstats.PauseTotalNs,duration:Uptime"

pprof

$ cd $GOPATH/src/bookinfo
# 采集数据
$ docker-compose \
  -f docker/docker-compose.yaml \
  exec books-details \
  go tool pprof -web localhost:5003/debug/pprof/profile
  
# 采集结果
> Saved profile in /root/pprof/pprof.bookdetails-service.samples.cpu.002.pb.gz

---------------------------------------------------------------------------------
# 启动http服务 展示采集结果
$ docker-compose -f docker/docker-compose.yaml \
  exec books-details \
  go tool pprof -http=0.0.0.0:5005 \
  /root/pprof/pprof.bookdetails-service.samples.cpu.002.pb.gz
  
# 访问服务
$ open http://localhost:5005

cpu火焰图

$ cd $GOPATH/src/bookinfo

# 采集数据生成火焰图
$ docker-compose -f docker/docker-compose.yaml \
  exec books-details \
  /go/bin/go-torch \
  -t 30 \
  --file "torch.svg" \
  --url http://localhost:5003

# 获取生成的火焰图
$ containerName=`docker-compose -f docker/docker-compose.yaml ps books-details | grep books-details | awk '{print $1}'`; \
  docker cp $containerName:/go/torch.svg /tmp && \
  open -a /Applications/Google\ Chrome.app /tmp/torch.svg

内存(inuse_space)火焰图 PS:用于分析程序常驻内存情况

$ cd $GOPATH/src/bookinfo

# 采集数据生成火焰图
$ docker-compose -f docker/docker-compose.yaml \
  exec books-details \
  /go/bin/go-torch \
  -t 30 \
  --file "torch_mem_inuse_space.svg" \
  -inuse_space http://localhost:5003/debug/pprof/heap \
  --colors=mem

# 获取生成的火焰图
$ containerName=`docker-compose -f docker/docker-compose.yaml ps books-details | grep books-details | awk '{print $1}'`; \
  docker cp $containerName:/go/torch_mem_inuse_space.svg /tmp && \
  open -a /Applications/Google\ Chrome.app /tmp/torch_mem_inuse_space.svg

内存(alloc_space)火焰图 PS:用于分析程序临时分配内存情况

$ cd $GOPATH/src/bookinfo

# 采集数据生成火焰图
$ docker-compose -f docker/docker-compose.yaml \
  exec books-details \
  /go/bin/go-torch \
  -t 30 \
  --file "torch_mem_alloc_space.svg" \
  -alloc_space http://localhost:5003/debug/pprof/heap \
  --colors=mem

# 获取生成的火焰图
$ containerName=`docker-compose -f docker/docker-compose.yaml ps books-details | grep books-details | awk '{print $1}'`; \
  docker cp $containerName:/go/torch_mem_alloc_space.svg /tmp && \
  open -a /Applications/Google\ Chrome.app /tmp/torch_mem_alloc_space.svg

常规debug信息

$ open http://localhost:5003/debug/pprof/
$ open http://localhost:5003/debug/pprof/cmdline
$ open http://localhost:5003/debug/pprof/profile
$ open http://localhost:5003/debug/pprof/symbol
$ open http://localhost:5003/debug/pprof/trace

Test

$ docker-compose -f docker/docker-compose.yaml \
  exec books-details \
  go test -v -cover=true ./src/bookinfo/bookdetails-service/...
  
--------------------------------------------------------------------------------------

=== RUN   TestBooksDetailsV1Detail
--- PASS: TestBooksDetailsV1Detail (0.01s)
PASS
coverage: 32.0% of statements
ok  	bookinfo/bookdetails-service/handlers	0.052s	coverage: 32.0% of statements

Benchmark

$ docker-compose -f docker/docker-compose.yaml \
  exec books-details \
  go test -bench=. -benchtime=30s -benchmem -run=none \
  ./src/bookinfo/bookdetails-service/handlers/handlers_test.go \
  ./src/bookinfo/bookdetails-service/handlers/handlers.go
  
-------------------------------------------------------------------------------------------------------

goos: linux
goarch: amd64
BenchmarkBooksDetailsV1Detail-8   	   20000	   2103049 ns/op	  163115 B/op	     715 allocs/op
PASS
ok  	command-line-arguments	63.111s

压力测试

$ hey -c 200 -n 50000 "http://localhost:5001/v1/detail?id=1"

-----------------------------------------------------------------------------------------------

Summary:
  Total:	1.2266 secs
  Slowest:	0.0603 secs
  Fastest:	0.0002 secs
  Average:	0.0084 secs
  Requests/sec:	40517.4967

  Total data:	2099835 bytes
  Size/request:	42 bytes

Response time histogram:
  0.000 [1]	|
  0.006 [16943]	|■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  0.012 [24485]	|■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  0.018 [6835]	|■■■■■■■■■■■
  0.024 [984]	|■■
  0.030 [103]	|
  0.036 [68]	|
  0.042 [148]	|
  0.048 [59]	|
  0.054 [44]	|
  0.060 [30]	|


Latency distribution:
  10% in 0.0033 secs
  25% in 0.0054 secs
  50% in 0.0073 secs
  75% in 0.0106 secs
  90% in 0.0140 secs
  95% in 0.0163 secs
  99% in 0.0236 secs

Details (average, fastest, slowest):
  DNS+dialup:	0.0000 secs, 0.0002 secs, 0.0603 secs
  DNS-lookup:	0.0001 secs, 0.0000 secs, 0.0321 secs
  req write:	0.0000 secs, 0.0000 secs, 0.0082 secs
  resp wait:	0.0055 secs, 0.0001 secs, 0.0359 secs
  resp read:	0.0019 secs, 0.0000 secs, 0.0270 secs

Status code distribution:
  [200]	49700 responses

服务单独启动

# zipkin
$ docker run -d \
  --rm \
  --name zipkin \
  -p 9411:9411 \
  openzipkin/zipkin
  
# mysql
$ docker run -d\
  --name mysql-bookinfo \
  --rm \
  -p 3406:3306 \
  -e MYSQL_ROOT_PASSWORD=root \
  -e MYSQL_DATABASE=bookinfo \
  mysql:5.6 \
  --character-set-server=utf8 \
  --collation-server=utf8_bin
  
# prometheus
$ docker run -d \
  --rm \
  -p 9090:9090 \
  --name prometheus \
  -v $GOPATH/src/bookinfo/docker/prometheus/data:/prometheus-data \
  prom/prometheus \
  --config.file=/prometheus-data/prometheus.yml

About

bookinfo服务用于演示go-kit实现微服务


Languages

Language:Go 100.0%