从本篇文章开始,咱们用一个系列来解说从需要到上线、从代码到k8s部署、从日志到监控等各个方面的微服务残缺实际。

实战我的项目地址:https://github.com/Mikaelemmm...

一、我的项目简介

整个我的项目应用了go-zero开发的微服务,根本蕴含了go-zero以及相干go-zero作者开发的一些中间件,所用到的技术栈根本是go-zero项目组的自研组件,根本是go-zero全家桶了。

我的项目目录构造如下:

  • app:所有业务代码蕴含api、rpc以及mq(音讯队列、提早队列、定时工作)
  • common:通用组件 error、middleware、interceptor、tool、ctxdata等
  • data:该我的项目蕴含该目录依赖所有中间件(mysql、es、redis、grafana等)产生的数据,此目录下的所有内容应该在git疏忽文件中,不须要提交。
  • deploy:

    • filebeat: docker部署filebeat配置
    • go-stash:go-stash配置
    • nginx: nginx网关配置
    • prometheus : prometheus配置
    • script:

      • gencode:生成api、rpc,以及创立kafka语句,复制粘贴应用
      • mysql:生成model的sh工具
    • goctl: 该我的项目goctl的template,goctl生成自定义代码模版,tempalte用法可参考go-zero文档,复制到家目录下.goctl即可,
      该我的项目用到goctl版本是v1.3.0
  • doc : 该我的项目系列文档

二、用到技术栈

  • go-zero
  • nginx网关
  • filebeat
  • kafka
  • go-stash
  • elasticsearch
  • kibana
  • prometheus
  • grafana
  • jaeger
  • go-queue
  • asynq
  • asynqmon
  • dtm
  • docker
  • docker-compose
  • mysql
  • redis

三、我的项目架构图

四、业务架构图

五、我的项目环境搭建

本我的项目采纳air热加载功即时批改代码及时失效,并且不须要每次都要重启,改了代码主动就在容器中从新加载了,本地不须要启动服务,本地装置的sdk就是写代码主动提醒应用的,理论运行是以来容器中cosmtrek/air的golang环境。所以应用goland、vscode都一样

1、clone代码&更新依赖

$ git clone git@github.com:Mikaelemmmm/go-zero-looklook.git$ go mod tidy

2、启动我的项目所依赖的环境

$ docker-compose -f docker-compose-env.yml up -d

jaeger: http://127.0.0.1:16686/search

asynq (延时、定时音讯队列): http://127.0.0.1:8980/

kibana: http://127.0.0.1:5601/

Elastic search: http://127.0.0.1:9200/

Prometheus: http://127.0.0.1:9090/

Grafana: http://127.0.0.1:3001/

Mysql: 自行客户端工具(Navicat、Sequel Pro)查看

  • host : 127.0.0.1
  • port : 33069
  • username : root
  • pwd : PXDN93VRKUm8TeE7

Redis: 自行工具(redisManager)查看

  • host : 127.0.0.1
  • port : 63799
  • pwd : G62m50oigInC30sf

Kafka: 自行客户端工具查看

  • host : 127.0.0.1
  • port : 9092

3、拉取我的项目依赖镜像

因为本我的项目是用air热加载的,所以是在air+golang镜像中运行,间接docker-compose也能够,然而思考依赖可能会比拟大,会影响启动我的项目,所以最好先把这个镜像拉取下来再去启动我的项目,拉取air+golang我的项目依赖的镜像命令如下

$ docker pull cosmtrek/air:latest

4、导入mysql数据

创立数据库looklook_order && 导入deploy/sql/looklook_order.sql数据

创立数据库looklook_payment && 导入deploy/sql/looklook_payment.sql数据

创立数据库looklook_travel && 导入deploy/sql/looklook_travel.sql数据

创立数据库looklook_usercenter && 导入looklook_usercenter.sql数据

5、启动我的项目

$ docker-compose up -d 

【注】依赖的是我的项目根目录下的docker-compose.yml配置

6、查看我的项目运行状况

拜访 http://127.0.0.1:9090/ , 点击下面菜单“Status”,在点击Targets ,蓝色的就是启动成了,红色就是没启动胜利

【注】如果是第一次拉取我的项目,每个我的项目容器第一次构建拉取依赖,这个看网络状况,可能会比较慢有的服务,所以会导致我的项目启动失败或者被依赖的服务启动失败本人也启动失败了,这个很失常,如果碰到我的项目启动不起来的状况,比方order-api ,这时候咱们去看下日志就能够

$ docker logs -f order-api 

很显著是因为order-rpc启动工夫太久了,而order-api始终等他启动,order-rpc肯定工夫内没有启动胜利,order-api没急躁了(超时了),就算前面order-rpc启动起来,它也不论了,这时候再去重启一次order-api就能够了,这个只是第一次创立容器会这样,之后只有不销毁容器就不会,咱们去到我的项目根目录下重启一下

$ docker-compose restart order-api

【留神】肯定要去到我的项目根目录下重启 ,因为docker-compose.yml在我的项目根目录

而后咱们在看一下,这里咱们应用docker logs 看了

  __    _   ___   / /\  | | | |_) /_/--\ |_| |_| \_ , built with Go 1.17.6mkdir /go/src/github.com/looklook/app/order/cmd/api/tmpwatching .watching descwatching desc/orderwatching etcwatching internalwatching internal/configwatching internal/handlerwatching internal/handler/homestayOrderwatching internal/logicwatching internal/logic/homestayOrderwatching internal/svcwatching internal/types!exclude tmpbuilding...running...

能够看到order-api曾经胜利了 ,再去prometheus看一下

能够看到prometheus也显示胜利了,同理把其余的也排查一次,启动胜利就能够了

7、拜访我的项目

因为咱们应用nginx做的网关,nginx网关配置在docker-compose中,也是配置在docker-compose中,nignx对外裸露端口是8888,所以咱们通过8888端口拜访

$ curl  -X POST "http://127.0.0.1:8888/usercenter/v1/user/register" -H "Content-Type: application/json" -d "{\"mobile\":\"18888888888\",\"password\":\"123456\"}" 返回:{"code":200,"msg":"OK","data":{"accessToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NzM5NjY0MjUsImlhdCI6MTY0MjQzMDQyNSwiand0VXNlcklkIjo1fQ.E5-yMF0OvNpBcfr0WyDxuTq1SRWGC3yZb9_Xpxtzlyw","accessExpire":1673966425,"refreshAfter":1658198425}}

【注】 如果是拜访nginx失败,拜访胜利能够疏忽,可能是nginx依赖后端服务,之前因为后端服务没启动起来,nginx这里没启动起来,重启一次nginx即可,我的项目根目录下重启

$ docker-compose restart nginx

六、日志收集

将我的项目日志收集到es(filebeat收集日志->kafka -> go-stash生产kafka日志->输入到es中, kibana查看es数据)

所以咱们要提前在kafka中创立日志的topic

进入kafka容器

$ docker exec -it kafka /bin/sh

创立log的topic

$ cd /opt/kafka/bin$ ./kafka-topics.sh --create --zookeeper zookeeper:2181 --replication-factor 1 -partitions 1 --topic looklook-log

拜访kibana http://127.0.0.1:5601/ , 创立日志索引

点击左上角菜单(三个横线那个东东),找到Analytics - > 点击discover

而后在以后页面,Create index pattern->输出looklook-* -> Next Step ->抉择@timestamp->Create index pattern

而后点击左上角菜单,找到Analytics->点击discover ,日志都显示了 (如果不显示,就去排查filebeat、go-stash,应用docker logs -f filebeat查看)

七、本我的项目镜像介绍

所有服务启动胜利,应该是如下这些,自行比照

  • nginx : 网关 (nginx->api->rpc)
  • cosmtrek/air : 咱们业务代码开发依赖的环境镜像,之所以用这个是因为air热加载,写代码实时编译太不便了,这个镜像是air+golang,实际上咱们启咱们本人的业务服务后,咱们的业务服务是运行在此镜像中的
  • wurstmeister/kafka : 业务应用的kafka
  • wurstmeister/zookeeper : kafka依赖的zookeeper
  • redis:业务应用的redis
  • mysql: 业务应用的数据库
  • prom/prometheus:监控业务
  • grafana/grafana :prometheus的ui很难看,用来显示prometheus收集来的数据
  • elastic/filebeat : 收集日志到kafka
  • go-stash : 生产kafka中日志,脱敏、过滤而后输入到es
  • docker.elastic.co/elasticsearch/elasticsearch : 存储收集的日志
  • docker.elastic.co/kibana/kibana : 显示elasticsearch
  • jaegertracing/jaeger-query 、jaegertracing/jaeger-collector、jaegertracing/jaeger-agent:链路追踪
  • go-stash : filebeat收集日志到kafka后,go-stash去生产kafka进行数据脱敏、过滤日志中内容,最初输入到es中

八、我的项目开发倡议

  • app下放所有业务服务代码
  • common放所有服务的公共根底库
  • data我的项目依赖中间件产生的数据,理论开发中应该在git中疏忽此目录以及此目录下产生的数据
  • 生成api、rpc代码:

个别咱们在生成api,rpc代码时候手动去敲goctl的命令比拟长,也记不住,所以咱们间接去deploy/script/gencode/gen.sh中复制代码即可。比方我在usercenter服务中新减少了一个业务,批改明码,写完api文件之后,进入到usercenter/cmd/api/desc目录下,间接复制deploy/script/gencode/gen.sh中的生成api命令运行即可

$ goctl api go -api *.api -dir ../  -style=goZero

生成rpc也一样,在写完proto文件后,间接粘复制deploy/script/gencode/gen.sh中的生成rpc命令运行即可

goctl >= 1.3 进入"服务/cmd/rpc/pb"目录下,执行上面命令

$ goctl rpc protoc *.proto --go_out=../ --go-grpc_out=../  --zrpc_out=../$ sed -i "" 's/,omitempty//g' *.pb.go

goctl < 1.3 进入"服务/cmd"目录下,执行上面命令

$  goctl rpc proto -src rpc/pb/*.proto -dir ./rpc -style=goZero$  sed -i "" 's/,omitempty//g'  ./rpc/pb/*.pb.go

【注】倡议在生成rpc文件时候,在多执行一次上面那个命令,把protobuf生成的omitempty给删除掉,不然字段为nil就不返回了

  • 生成kafka代码:
    因为本我的项目应用了go-queue的kq做音讯队列,kq又依赖的kafka,理论就是应用了kafka做音讯队列,然而kq默认是须要咱们提前把topic建好的,不许默认主动生成,所以命令也筹备好了,间接复制deploy/script/gencode/gen.sh中的创立kafka的topic代码即可

     kafka-topics.sh --create --zookeeper zookeeper:2181 --replication-factor 1 -partitions 1 --topic {topic}
  • 生成model代码,间接运行deploy/script/mysql/genModel.sh 参数
  • api我的项目中的.api文件咱们做了拆分,对立放到每个api的desc文件夹下,因为如果所有内容都写在api中可能不便于查看,所以做了拆分,把所有办法写到一个api中,其余的实体以及req、rep对立放到一个文件夹独自定义比拟清晰
  • 生成model、错误处理时候应用了template从新定义,该我的项目用到的自定义的goctl的模版在我的项目data/goctl下

九、后续

因为我的项目中因为波及到的技术栈略微有点多,将分章节一步一步解说,敬请关注。

我的项目地址

https://github.com/zeromicro/go-zero

欢送应用 go-zerostar 反对咱们!

微信交换群

关注『微服务实际』公众号并点击 交换群 获取社区群二维码。