当前位置: 首页 > 科技观察

微服务从代码到K8s部署无所不在

时间:2023-03-16 18:46:30 科技观察

从本文开始,我们用一个系列从需求到上线,从代码到k8s部署,从日志到监控,从各个方面讲解微服务的完整实践。实际项目地址:https://github.com/Mikaelemmmm/go??-zero-looklook一、项目介绍整个项目使用了go-zero开发的微服务,基本包括go-zero和相关go-zero作者开发的一些中间件,使用的技术栈基本都是go-zero项目组的自研组件,基本上是go-zero全家桶。项目目录结构如下:app:所有业务代码包括api、rpc、mq(消息队列、延迟队列、定时任务)common:常用组件error、中间件、拦截器、工具、ctxdata等data:本项目包含了该目录下所有中间依赖文件(mysql、es、redis、grafana等)产生的数据,该目录下的所有内容都应该在gitignore文件中,无需提交。deploy:gencode:生成api,rpc,创建kafka语句,使用mysql复制粘贴:生成模型sh工具filebeat:docker部署filebeat配置go-stash:go-stash配置nginx:nginx网关配置prometheus:prometheus配置脚本??:goctl:本项目的goctl模板,goctl生成自定义代码模板,模板的使用可以参考go-zero文档,复制到home目录下。.使用技术栈go-zeronginx网关文件beatkafkago-stashelasticsearchkibanaprometheusgrafanajaegergo-queueeasynqasynqmondtmdockerdocker-composemysqlredis3.项目架构图4.业务架构图5.项目环境搭建本项目使用air热加载功能,修改代码立即生效,及时生效,并且不需要每次都更新重启,如果代码有改动,会自动重新加载到容器中。无需在本地启动服务。写代码时会自动提示使用本地安装的sdk。实际运行的是容器中cosmtrek/air的golang环境。所以使用goland和vscode是一样的1.克隆代码&更新依赖$gitclonegit@github.com:Mikaelemmmm/go??-zero-looklook.git$gomodtidy2.启动项目依赖的环境$docker-compose-fdocker-compose-env.ymlup-djaeger:http://127.0.0.1:16686/searchasynq(延时、定时消息队列):http://127.0.0.1:8980/kibana:http://127.0.0.1:5601/Elasticsearch:http://127.0.0.1:9200/Prometheus:http://127.0.0.1:9090/Grafana:http://127.0.0.1:3001/,默认账号和密码为adminMysql:自助客户端工具(Navicat,SequelPro)查看host:127.0.0.1port:33069username:rootpwd:PXDN93VRKUm8TeE7Redis:自助客户端工具(redisManager)查看host:127.0.0.1port:63799pwd:G62m50oigInC30sfKafka:自助客户端工具1.17port0.0.17port0::90923拉取工程依赖镜像。因为这个项目是用air热加载的,所以运行在air+golang镜像中。也可以直接docker-compose,但是考虑到可能依赖比较大,会影响启动项目,所以最好先拉这个镜像再启动项目。拉取air+golang项目依赖的镜像命令如下$dockerpullcosmtrek/air:latest4,导入mysql数据创建数据库looklook_order&&importdeploy/sql/looklook_order.sql数据创建数据库looklook_payment&&importdeploy/sql/looklook_payment.sql数据创建数据库looklook_travel&&importdeploy/sql/looklook_travel.sqldatacreatedatabaselooklook_usercenter&&importlooklook_usercenter.sqldata5.启动项目$docker-composeup-d[注意]取决于项目根目录下的docker-compose.yml配置6.查看项目运行访问http://127.0.0.1:9090/,点击上面的菜单“Status”,然后点击Targets,蓝色的表示启动成功,红色的表示启动不成功【注意】如果是第一次拉取项目,则每一个项目容器都是第一次构建和拉取依赖。根据网络情况,有些服务可能会比较慢,所以会导致项目无法启动或者依赖的服务无法启动,同样会启动失败。这个是正常的。如果遇到项目无法启动,比如order-api,这时候我们可以查看日志。$dockerlogs-forder-api很明显是因为order-rpc启动时间太长,而order-api一直在等待他启动,order-rpc在一定时间内未能成功启动,order-api是不耐烦(超时),即使后面启动了order-rpc也不在乎,然后再重启order-api,这只是第一次创建容器时会出现的,然后只要你不要破坏容器,我们去项目根目录重启$docker-composerestartorder-api【注意】必须去项目根目录重启,因为docker-compose.yml在项目的根目录,然后我们看一下。这里我们使用dockerlogs查看______//\||||_)/_/--\|_||_|\_,使用Go1.17.6mkdir/go/src/github.com/looklook/app/order/cmd/api/tmpwatching.watchingdescwatchingdesc/orderwatchingetcwatchinginternalwatchinginternal/configwatchinginternal/handlerwatchinginternal/handler/homestayOrderw构建watchinginternal/logicwatchinginternal/logic/homestayOrderwatchinginternal/svcwatchinginternal/types!excludetmpbuilding...running...可以看到order-api成功了,再去prometheus看prometheus也显示成功,并且同上7.访问项目由于我们使用的是nginx做的网关,所以nginx网关是在docker-compose中配置的,在docker-compose中也是配置的。nignx暴露的端口是8888,所以我们通过8888端口访问$curl-XPOST"http://127.0.0.1:8888/usercenter/v1/user/register"-H"Content-Type:application/json"-d"{\"手机\":\"18888888888\",\"密码\":\"123456\"}"返回:{"code":200,"msg":"OK","data":{"accessToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NzM5NjY0MjUsImlhdCI6MTY0MjQzMDQyNSwiand0VXNlcklkIjo1fQ.E5-yMF0OvNpBcfr0WyDxuTq1SRWGC3yZb9_Xpxtzlyw","accessExpire":1673966425,"refreshAfter":1658198425}}[Note]Iftheaccesstonginxfails,thesuccessfulaccesscanbeignored.可能是nginx依赖了后端服务。后端服务没有启动之前,nginx这里没有启动,只需要重启一次nginx,在项目根目录下重启$docker-composerestartnginx六、日志收集收集项目日志到es(filebeat收集日志->kafka->go-stash消费kafka日志->输出到es,kibana查es数据)所以我们需要提前在kafka中创建一个logtopic,输入kafka容器$dockerexec-itkafka/bin/sh创建日志主题$cd/opt/kafka/bin$./kafka-topics.sh--create--zookeeperzookeeper:2181--replication-factor1-partitions1--topiclooklook-log访问kibanahttp://127.0.0.1:5601/,创建日志索引,点击左上角菜单(三横线那个),找到Analytics->点击discover,然后在当前页面,Createindexpattern->Inputlooklook-*->NextStep->选择@timestamp->Createindexpattern然后点击左上方菜单,找到Analytics->点击discover,显示日志(如果不显示,去查看filebeat,go-stash,使用dockerlogs-ffilebeat查看)7.这个项目镜像介绍所有服务已经启动成功。它应该如下所示。自己对比一下nginx:gateway(nginx->api->rpc)cosmtrek/air:我们业务代码开发依赖的环境Mirror,之所以用这个是因为air是热加载的,写起来很方便实时编码和编译。这个镜像是air+golang。其实我们启动自己的业务服务后,我们的业务服务就是运行在这个镜像/kafka中的wurstmeister:kafkawurstmeister/zookeeper业务用:zookeeperredisforkafka:redismysql业务用:databaseprom/prometheus业务用:监控业务grafana/grafana:prometheus的ui很丑,用来展示prometheus收集的数据elastic/filebeat:收集日志到kafkago-stash:在kafka消费日志,脱敏,过滤输出到esdocker.elastic.co/elasticsearch/elasticsearch:存储收集的日志docker.elastic.co/kibana/kibana:显示elasticsearchjaegertracing/jaeger-query,jaegertracing/jaeger-collector,jaegertracing/jaeger-agent:链接跟踪go-stash:filebeat收集日志到kafka后,go-stash消费kafka进行数据脱敏和过滤日志内容,以及最后输出到es。8、项目开发建议应用将所有业务服务代码发布到所有服务的公共基础库中。数据项目依赖于中间件生成的数据。实际开发中应该在git中忽略该目录,在该目录下生成。从数据中生成api和rpc代码:一般我们在生成api和rpc代码的时候,手动敲goctl的命令比较长,记不住,所以直接去deploy/script/gencode/gen.sh和复制代码比如我在usercenter服务中新增了一个业务,修改了密码,写好api文件后,进入到usercenter/cmd目录下,直接复制deploy/script/gencode/gen.sh中的generateapi命令运行$goctlapigo-api./api/desc/*.api-dir./api-style=goZero也会生成rpc。写好proto文件后,将生成的rpc粘贴复制到deploy/script/gencode/gen.sh中运行命令即可$goctlrpcproto-srcrpc/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的,它是默认不允许自动生成,所以命令也准备好了,直接copydeploy/script/gencode在/gen.sh中创建kafka主题代码kafka-topics.sh--create--zookeeperzookeeper:2181--replication-factor1-partitions1--topic{topic}生成模型代码,直接运行deploy/Script/mysql/genModel.sh参数api工程中的.api文件已经拆分,放在各个api的desc文件夹中,因为它如果所有的内容都写在api里可能不太好看,所以我们做了Split,把所有的方法写到一个api里,其他entity,req,rep放到一个文件夹里。定义比较明确。生成模型,并重新定义模板以进行错误处理。本项目使用的自定义goctl模板在项目data/goctl的下九个。后续由于项目涉及的技术栈有点多,会分章节逐步讲解,敬请期待。项目地址https://github.com/zeromicro/go-zero欢迎使用go-zero和star支持我们!