go-zero标准的项目结构,以及如何使用docker-compose部署道linux服务器上
如履薄冰
先附上一张图表示我这几天的心情吧,微服务确实有点难啊.但是谁让它是go-zero呢.只要是go的,我都喜欢.
go-zero项目结构
刚学完go-zero框架,就着手写一个小项目练习练习,谁知道一开始就把项目结构搭错了,被官网的项目结构误解了.(怪我,没看懂官网上的意思,现在才恍然大悟)
先给出一个树形结构吧,能看懂直接跳过接口
etcd和etcd-manage这两个文件夹可以忽略,在部署的时候会解释.app目录下面有两个服务,tag服务和user服务.两个服务内部都是三个目录,一个common,是一些公共配置,如fgorm,jwt等等.restful则是对应服务的api层.service是对应服务的rpc层.其实每一个服务就可以相当于是一个小项目了.
─app
├─etcd
├─etcd-manage
├─tag
│ ├─common
│ │ ├─bcrypt
│ │ ├─gorm
│ │ ├─jwt
│ │ ├─redis
│ │ ├─response
│ │ └─validate
│ ├─restful
│ │ ├─etc
│ │ ├─internal
│ │ │ ├─config
│ │ │ ├─handler
│ │ │ │ ├─tagLogin
│ │ │ │ └─tagTest
│ │ │ ├─logic
│ │ │ │ ├─tagLogin
│ │ │ │ └─tagTest
│ │ │ ├─svc
│ │ │ └─types
│ │ ├─logs
│ │ └─tag
│ │ └─logs
│ └─service
│ ├─client
│ │ ├─taglogin
│ │ └─tagsign
│ ├─etc
│ ├─internal
│ │ ├─config
│ │ ├─logic
│ │ │ ├─taglogin
│ │ │ └─tagsign
│ │ ├─server
│ │ │ ├─taglogin
│ │ │ └─tagsign
│ │ ├─svc
│ │ └─types
│ ├─logs
│ └─tag
└─user
├─common
│ ├─bcrypt
│ ├─gorm
│ ├─jwt
│ ├─redis
│ ├─response
│ └─validate
├─restful
│ ├─etc
│ ├─internal
│ │ ├─config
│ │ ├─handler
│ │ │ └─userGroup
│ │ ├─logic
│ │ │ └─userGroup
│ │ ├─svc
│ │ └─types
│ └─logs
└─service
├─etc
├─internal
│ ├─config
│ ├─logic
│ ├─server
│ ├─svc
│ └─types
├─logs
├─user
└─userservice
项目结构图片
如此一来,一个api内如何调用两个完全独立的rpc服务呢?
其实很简单,把另一个服务的.proto文件复制一份到自己的服务内一份,然后执行goctl命令生成一份代码. 然后就和在一个服务内 api调用rpc业务逻辑的方法相同了.
注意:再这个服务内生成的代码,是不需要你再重新编写业务逻辑的
使用docker-compose部署
1.ETCD镜像文件的编写
在上述的etcd文件夹下面新建一个Dockerfile文件.内容如下
每一个服务内的yaml文件内可以按照如下写法.
FROM bitnami/etcd:latest
LABEL maintainer="zyf021026 <your-email>"
2.ETCD-UI镜像文件的编写
在上述文件夹,etcd-manage下编写Dockerfile,内容如下
FROM evildecay/etcdkeeper
LABEL maintainer="zyf021026 <your-email>"
3.服务内dockerfile内容的编写
用user服务举例
user服务中的rpc层Dockerfile编写
1.进入user/restful目录 使用goctl工具生成dockerfile文件
goctl docker -go user.go #生成的文件暂时放着不管
2.在进入user/service目录 , 使用goctl工具生成dockerfile文件
goctl docker -go user.go #同样暂时忽略
#########################
需要简单修改生成的dockerfile文件 以 api服务中的dockerfile为例
FROM golang:alpine AS builder
LABEL stage=gobuilder
ENV CGO_ENABLED 0
ENV GOPROXY https://goproxy.cn,direct
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
RUN apk update --no-cache && apk add --no-cache tzdata
WORKDIR /build
ADD go.mod .
ADD go.sum .
RUN go mod download
COPY . .
COPY restful/etc /app/etc #检查此处的配置文件目录
RUN go build -ldflags="-s -w" -o /app/user restful/user.go #这个地方需要检查生成的go文件路径是否正确.
FROM scratch
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=builder /usr/share/zoneinfo/Asia/Shanghai /usr/share/zoneinfo/Asia/Shanghai
ENV TZ Asia/Shanghai
WORKDIR /app
COPY --from=builder /app/user /app/user
COPY --from=builder /app/etc /app/etc
CMD ["./user", "-f", "etc/user.yaml"] #此处配置文件的路径和名称是否符合要求
#########################
#########################
其它Dokcerfile如上
#########################
4.在服务器上构建镜像文件
当热,此处是有更简便的方法,但是,目前水平有限,后续在升级.
把user/restful和user/service中的Dockerfile依次拉到对应服务的根目录下.然后执行dockerbuild–no-cache-timage-name:0.0.1
我的项目中tag服务也是同样的操作.
5.Docker-compose编写
docker-compose.yaml 是在项目的根目录下编写的.
注意修改你自己生成的镜像的名称,同时在服务器上暴露你的端口
镜像生成完成之后,编写docker-compose.yaml部署容器 (刚才编写的两个etcd的Dockerfile就派上用处了)
version: '3'
networks:
backend:
driver: bridge
######## 项目依赖的环境,启动项目之前要先启动此环境 #######
services:
etcd:
build:
context: etcd #etcd的Dockerfie路径
environment:
- TZ=Asia/Shanghai
- ALLOW_NONE_AUTHENTICATION=yes
- ETCD_ADVERTISE_CLIENT_URLS=http://your_ip:2379
ports: # 设置端口映射
- "2379:2379"
networks:
- backend
restart: always
etcd-manage:
build:
context: etcd-manage#etcd-ui的Dockerfie路径
environment:
- TZ=Asia/Shanghai
ports:
- "7000:8080" # 设置容器8080端口映射指定宿主机端口,用于宿主机访问可视化web
depends_on: # 依赖容器
- etcd # 在 etcd 服务容器启动后启动
networks:
- backend
restart: always
# 服务发现
tag-rpc: #自定义容器名称
image: tag-rpc:0.0.1
container_name: tag-rpc
restart: always
environment: #设置环境变量
- TZ=Asia/Shanghai
privileged: true
ports: #设置端口映射
- "8081:8081"
networks:
- backend
user-rpc: #自定义容器名称
image: user-rpc:0.0.1
container_name: user-rpc
restart: always
environment: #设置环境变量
- TZ=Asia/Shanghai
privileged: true
ports: #设置端口映射
- "8082:8082"
networks:
- backend
tag-api: #自定义容器名称
image: tag-api:0.0.1
container_name: tag-api
restart: always
environment: #设置环境变量
- TZ=Asia/Shanghai
privileged: true
ports: #设置端口映射
- "8888:8888"
networks:
- backend
user-api: #自定义容器名称
image: user-api:0.0.1
container_name: user-api
restart: always
environment: #设置环境变量
- TZ=Asia/Shanghai
privileged: true
ports: #设置端口映射
- "8887:8887"
networks:
- backend
如有疑问,可以私信
升级版docker-compose.yaml 一键部署
上述Dockerfile中的内容不需要改变
docker-compose.yaml中内容改写
docker-compose.yaml中的kafak镜像不需要可以注释掉
#version: '3'
#
#networks:
# backend:
# driver: bridge
#
#
######### 项目依赖的环境,启动项目之前要先启动此环境 #######
#services:
# etcd:
# build:
# context: etcd
# environment:
# - TZ=Asia/Shanghai
# - ALLOW_NONE_AUTHENTICATION=yes
# - ETCD_ADVERTISE_CLIENT_URLS=http://101.37.175.145:2379
# ports: # 设置端口映射
# - "2379:2379"
# networks:
# - backend
# restart: always
# etcd-manage:
# build:
# context: etcd-manage
# environment:
# - TZ=Asia/Shanghai
# ports:
# - "7000:8080" # 设置容器8080端口映射指定宿主机端口,用于宿主机访问可视化web
# depends_on: # 依赖容器
# - etcd # 在 etcd 服务容器启动后启动
# networks:
# - backend
# restart: always
# # 服务发现
# tag-rpc: #自定义容器名称
# image: tag-rpc:0.0.1
# container_name: tag-rpc
# restart: always
# environment: #设置环境变量
# - TZ=Asia/Shanghai
# privileged: true
# ports: #设置端口映射
# - "8081:8081"
# networks:
# - backend
#
# user-rpc: #自定义容器名称
# image: user-rpc:0.0.1
# container_name: user-rpc
# restart: always
# environment: #设置环境变量
# - TZ=Asia/Shanghai
# privileged: true
# ports: #设置端口映射
# - "8082:8082"
# networks:
# - backend
#
# tag-api: #自定义容器名称
# image: tag-api:0.0.1
# container_name: tag-api
# restart: always
# environment: #设置环境变量
# - TZ=Asia/Shanghai
# privileged: true
# ports: #设置端口映射
# - "8888:8888"
# networks:
# - backend
#
# user-api: #自定义容器名称
# image: user-api:0.0.1
# container_name: user-api
# restart: always
# environment: #设置环境变量
# - TZ=Asia/Shanghai
# privileged: true
# ports: #设置端口映射
# - "8887:8887"
# networks:
# - backend
version: '3'
networks:
backend:
driver: bridge
######## 项目依赖的环境,启动项目之前要先启动此环境 #######
services:
etcd:
build:
context: etcd
environment:
- TZ=Asia/Shanghai
- ALLOW_NONE_AUTHENTICATION=yes
- ETCD_ADVERTISE_CLIENT_URLS=http://101.37.175.145:2379
ports: # 设置端口映射
- "2379:2379"
networks:
- backend
restart: always
etcd-manage:
build:
context: etcd-manage
environment:
- TZ=Asia/Shanghai
ports:
- "7000:8080" # 设置容器8080端口映射指定宿主机端口,用于宿主机访问可视化web
depends_on: # 依赖容器
- etcd # 在 etcd 服务容器启动后启动
networks:
- backend
restart: always
zoo1:
image: confluentinc/cp-zookeeper:7.3.2
hostname: zoo1
container_name: zoo1
ports:
- "2181:2181"
environment:
ZOOKEEPER_CLIENT_PORT: 2181
ZOOKEEPER_SERVER_ID: 1
ZOOKEEPER_SERVERS: zoo1:2888:3888
kafka1:
image: confluentinc/cp-kafka:7.3.2
hostname: kafka1
container_name: kafka1
ports:
- "9092:9092"
- "29092:29092"
- "9999:9999"
environment:
KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka1:19092,EXTERNAL://${DOCKER_HOST_IP:-127.0.0.1}:9092,DOCKER://host.docker.internal:29092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT,DOCKER:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
KAFKA_ZOOKEEPER_CONNECT: "zoo1:2181"
KAFKA_BROKER_ID: 1
KAFKA_LOG4J_LOGGERS: "kafka.controller=INFO,kafka.producer.async.DefaultEventHandler=INFO,state.change.logger=INFO"
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
KAFKA_JMX_PORT: 9999
KAFKA_JMX_HOSTNAME: ${DOCKER_HOST_IP:-127.0.0.1}
KAFKA_AUTHORIZER_CLASS_NAME: kafka.security.authorizer.AclAuthorizer
KAFKA_ALLOW_EVERYONE_IF_NO_ACL_FOUND: "true"
depends_on:
- zoo1
kafka-ui:
container_name: kafka-ui
image: provectuslabs/kafka-ui:latest
ports:
- 8080:8080
depends_on:
- kafka1
environment:
DYNAMIC_CONFIG_ENABLED: "TRUE"
# 服务发现
tag-rpc: #自定义容器名称
build:
context: tag
dockerfile: service/Dockerfile
container_name: tag-rpc
restart: always
environment: #设置环境变量
- TZ=Asia/Shanghai
privileged: true
ports: #设置端口映射
- "8081:8081"
networks:
- backend
user-rpc: #自定义容器名称
build:
context: user
dockerfile: service/Dockerfile
restart: always
environment: #设置环境变量
- TZ=Asia/Shanghai
privileged: true
ports: #设置端口映射
- "8082:8082"
networks:
- backend
tag-api: #自定义容器名称
build:
context: tag
dockerfile: restful/Dockerfile
container_name: tag-api
restart: always
environment: #设置环境变量
- TZ=Asia/Shanghai
privileged: true
ports: #设置端口映射
- "8888:8888"
networks:
- backend
user-api: #自定义容器名称
build:
context: user
dockerfile: restful/Dockerfile
container_name: user-api
restart: always
environment: #设置环境变量
- TZ=Asia/Shanghai
privileged: true
ports: #设置端口映射
- "8887:8887"
networks:
- backend