带你十天轻松搞定 Go 微服务系列

一年好景君须记,最是橙黄橘绿时。这篇文章主要讲述带你十天轻松搞定 Go 微服务系列相关的知识,希望能为你提供帮助。
本文开始,我们会出一个系列文章跟大家详细展示一个 go-zero 微服务示例,整个系列分十篇文章,目录结构如下:

  1. 环境搭建(本文)
  2. 服务拆分
  3. 用户服务
  4. 产品服务
  5. 订单服务
  6. 支付服务
  7. RPC 服务 Auth 验证
  8. 服务监控
  9. 链路追踪
  10. 分布式事务
期望通过本系列带你在本机利用 Docker 环境利用 go-zero 快速开发一个商城系统,让你快速上手微服务。
完整示例代码:https://github.com/nivin-studio/go-zero-mall
1 环境要求
  • Golang 1.15+
  • Etcd
  • Redis
  • mysql
  • Prometheus
  • Grafana
  • Jaeger
  • DTM
2 Docker 本地开发环境搭建为了方便开发调试,我们使用 Docker 构建本地开发环境。WindowsmacOS 系统可下载 Docker Desktop 安装使用,具体下载安装方法可自行搜索相关教程。
这里我们使用 Docker Compose 来编排管理我们的容器,创建如下目录:
gonivinck ├── dtm# DTM 分布式事务管理器 │├── config.yml# DTM 配置文件 │└── Dockerfile ├── etcd# Etcd 服务注册发现 │└── Dockerfile ├── golang# Golang 运行环境 │└── Dockerfile ├── grafana# Grafana 可视化数据监控 │└── Dockerfile ├── jaeger# Jaeger 链路追踪 │└── Dockerfile ├── mysql# Mysql 服务 │└── Dockerfile ├── mysql-manage# Mysql 可视化管理 │└── Dockerfile ├── prometheus# Prometheus 服务监控 │├── Dockerfile │└── prometheus.yml# Prometheus 配置文件 ├── redis# Redis 服务 │└── Dockerfile ├── redis-manage# Redis 可视化管理 │└── Dockerfile ├── .env# env 配置 └── docker-compose.yml

2.1 编写 Dockerfile
go-zero 的微服务中采用 grpc 进行服务间的通信,而 grpc 的编写就需要用到 protoc 和翻译成 go 语言 rpc stub 代码的插件 protoc-gen-go
为了提高开发效率,减少代码的出错率,缩短业务开发的工作量,go-zero 还提供了 goctl 代码生成工具。
因此,我们需要将 protoc, protoc-gen-go, goctl, 给提前安装到 golang 的容器中,以便后续使用。
所以 golang 容器的 Dockerfile 代码如下:
FROM golang:1.17LABEL maintainer="Ving < ving@nivin.cn> "ENV GOPROXY https://goproxy.cn,direct# 安装必要的软件包和依赖包 USER root RUN sed -i s/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/ /etc/apt/sources.list & & \\ sed -i s/security.debian.org/mirrors.tuna.tsinghua.edu.cn/ /etc/apt/sources.list & & \\ sed -i s/security-cdn.debian.org/mirrors.tuna.tsinghua.edu.cn/ /etc/apt/sources.list & & \\ apt-get update & & \\ apt-get upgrade -y & & \\ apt-get install -y --no-install-recommends \\ curl \\ zip \\ unzip \\ git \\ vim # 安装 goctl USER root RUN GOPROXY=https://goproxy.cn/,direct go install github.com/tal-tech/go-zero/tools/goctl@cli# 安装 protoc USER root RUN curl -L -o /tmp/protoc.zip https://github.com/protocolbuffers/protobuf/releases/download/v3.19.1/protoc-3.19.1-linux-x86_64.zip & & \\ unzip -d /tmp/protoc /tmp/protoc.zip & & \\ mv /tmp/protoc/bin/protoc $GOPATH/bin# 安装 protoc-gen-go USER root RUN go get -u github.com/golang/protobuf/protoc-gen-go@v1.4.0# $GOPATH/bin添加到环境变量中 ENV PATH $GOPATH/bin:$PATH# 清理垃圾 USER root RUN apt-get clean & & \\ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* & & \\ rm /var/log/lastlog /var/log/faillog# 设置工作目录 WORKDIR /usr/src/codeEXPOSE 8000 EXPOSE 8001 EXPOSE 8002 EXPOSE 8003 EXPOSE 9000 EXPOSE 9001 EXPOSE 9002 EXPOSE 9003

其他服务容器 Dockerfile 无需特殊处理,只要基于现有的镜像即可。
服务 基于的镜像
DTM yedf/dtm
Etcd bitnami/etcd
Mysql mysql:5.7
Redis redis:5.0
Mysql Manage phpmyadmin/phpmyadmin
Redis Manage erikdubbelboer/phpredisadmin
Prometheus bitnami/prometheus
Grafana grafana/grafana
Jaeger jaegertracing/all-in-one:1.28
2.2 编写 .env 配置文件
# 设置时区 TZ=Asia/Shanghai # 设置网络模式 NETWORKS_DRIVER=bridge# PATHS ########################################## # 宿主机上代码存放的目录路径 CODE_PATH_HOST=./code # 宿主机上Mysql Reids数据存放的目录路径 DATA_PATH_HOST=./data# MYSQL ########################################## # Mysql 服务映射宿主机端口号,可在宿主机127.0.0.1:3306访问 MYSQL_PORT=3306 MYSQL_USERNAME=admin MYSQL_PASSWORD=123456 MYSQL_ROOT_PASSWORD=123456# Mysql 可视化管理用户名称,同 MYSQL_USERNAME MYSQL_MANAGE_USERNAME=admin # Mysql 可视化管理用户密码,同 MYSQL_PASSWORD MYSQL_MANAGE_PASSWORD=123456 # Mysql 可视化管理ROOT用户密码,同 MYSQL_ROOT_PASSWORD MYSQL_MANAGE_ROOT_PASSWORD=123456 # Mysql 服务地址 MYSQL_MANAGE_CONNECT_HOST=mysql # Mysql 服务端口号 MYSQL_MANAGE_CONNECT_PORT=3306 # Mysql 可视化管理映射宿主机端口号,可在宿主机127.0.0.1:1000访问 MYSQL_MANAGE_PORT=1000# REDIS ########################################## # Redis 服务映射宿主机端口号,可在宿主机127.0.0.1:6379访问 REDIS_PORT=6379# Redis 可视化管理用户名称 REDIS_MANAGE_USERNAME=admin # Redis 可视化管理用户密码 REDIS_MANAGE_PASSWORD=123456 # Redis 服务地址 REDIS_MANAGE_CONNECT_HOST=redis # Redis 服务端口号 REDIS_MANAGE_CONNECT_PORT=6379 # Redis 可视化管理映射宿主机端口号,可在宿主机127.0.0.1:2000访问 REDIS_MANAGE_PORT=2000# ETCD ########################################### # Etcd 服务映射宿主机端口号,可在宿主机127.0.0.1:2379访问 ETCD_PORT=2379# PROMETHEUS ##################################### # Prometheus 服务映射宿主机端口号,可在宿主机127.0.0.1:3000访问 PROMETHEUS_PORT=3000# GRAFANA ######################################## # Grafana 服务映射宿主机端口号,可在宿主机127.0.0.1:4000访问 GRAFANA_PORT=4000# JAEGER ######################################### # Jaeger 服务映射宿主机端口号,可在宿主机127.0.0.1:5000访问 JAEGER_PORT=5000# DTM ######################################### # DTM HTTP 协议端口号 DTM_HTTP_PORT=36789 # DTM gRPC 协议端口号 DTM_GRPC_PORT=36790

2.3 编写 docker-compose.yml 配置文件
version: 3.5 # 网络配置 networks: backend: driver: $NETWORKS_DRIVER# 服务容器配置 services: golang:# 自定义容器名称 build: context: ./golang# 指定构建使用的 Dockerfile 文件 environment:# 设置环境变量 - TZ=$TZ volumes:# 设置挂载目录 - $CODE_PATH_HOST:/usr/src/code# 引用 .env 配置中 CODE_PATH_HOST 变量,将宿主机上代码存放的目录挂载到容器中 /usr/src/code 目录 ports:# 设置端口映射 - "8000:8000" - "8001:8001" - "8002:8002" - "8003:8003" - "9000:9000" - "9001:9001" - "9002:9002" - "9003:9003" stdin_open: true# 打开标准输入,可以接受外部输入 tty: true networks: - backend restart: always# 指定容器退出后的重启策略为始终重启etcd:# 自定义容器名称 build: context: ./etcd# 指定构建使用的 Dockerfile 文件 environment: - TZ=$TZ - ALLOW_NONE_AUTHENTICATION=yes - ETCD_ADVERTISE_CLIENT_URLS=http://etcd:2379 ports:# 设置端口映射 - "$ETCD_PORT:2379" networks: - backend restart: alwaysmysql: build: context: ./mysql environment: - TZ=$TZ - MYSQL_USER=$MYSQL_USERNAME# 设置 Mysql 用户名称 - MYSQL_PASSWORD=$MYSQL_PASSWORD# 设置 Mysql 用户密码 - MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD# 设置 Mysql root 用户密码 volumes: - $DATA_PATH_HOST/mysql:/var/lib/mysql# 引用 .env 配置中 DATA_PATH_HOST 变量,将宿主机上存放 Mysql 数据的目录挂载到容器中 /var/lib/mysql 目录 ports: - "$MYSQL_PORT:3306"# 设置容器3306端口映射指定宿主机端口 networks: - backend restart: alwaysredis: build: context: ./redis environment: - TZ=$TZ volumes: - $DATA_PATH_HOST/redis:/data# 引用 .env 配置中 DATA_PATH_HOST 变量,将宿主机上存放 Redis 数据的目录挂载到容器中 /data 目录 ports: - "$REDIS_PORT:6379"# 设置容器6379端口映射指定宿主机端口 networks: - backend restart: alwaysmysql-manage: build: context: ./mysql-manage environment: - TZ=$TZ - PMA_ARBITRARY=1 - MYSQL_USER=$MYSQL_MANAGE_USERNAME# 设置连接的 Mysql 服务用户名称 - MYSQL_PASSWORD=$MYSQL_MANAGE_PASSWORD# 设置连接的 Mysql 服务用户密码 - MYSQL_ROOT_PASSWORD=$MYSQL_MANAGE_ROOT_PASSWORD # 设置连接的 Mysql 服务 root 用户密码 - PMA_HOST=$MYSQL_MANAGE_CONNECT_HOST# 设置连接的 Mysql 服务 host,可以是 Mysql 服务容器的名称,也可以是 Mysql 服务容器的 ip 地址 - PMA_PORT=$MYSQL_MANAGE_CONNECT_PORT# 设置连接的 Mysql 服务端口号 ports: - "$MYSQL_MANAGE_PORT:80"# 设置容器80端口映射指定宿主机端口,用于宿主机访问可视化web depends_on:# 依赖容器 - mysql# 在 Mysql 服务容器启动后启动 networks: - backend restart: alwaysredis-manage: build: context: ./redis-manage environment: - TZ=$TZ - ADMIN_USER=$REDIS_MANAGE_USERNAME# 设置 Redis 可视化管理的用户名称 - ADMIN_PASS=$REDIS_MANAGE_PASSWORD# 设置 Redis 可视化管理的用户密码 - REDIS_1_HOST=$REDIS_MANAGE_CONNECT_HOST# 设置连接的 Redis 服务 host,可以是 Redis 服务容器的名称,也可以是 Redis 服务容器的 ip 地址 - REDIS_1_PORT=$REDIS_MANAGE_CONNECT_PORT# 设置连接的 Redis 服务端口号 ports: - "$REDIS_MANAGE_PORT:80"# 设置容器80端口映射指定宿主机端口,用于宿主机访问可视化web depends_on:# 依赖容器 - redis# 在 Redis 服务容器启动后启动 networks: - backend restart: alwaysprometheus: build: context: ./prometheus environment: - TZ=$TZ volumes: - ./prometheus/prometheus.yml:/opt/bitnami/prometheus/conf/prometheus.yml# 将 prometheus 配置文件挂载到容器里 ports: - "$PROMETHEUS_PORT:9090"# 设置容器9090端口映射指定宿主机端口,用于宿主机访问可视化web networks: - backend restart: alwaysgrafana: build: context: ./grafana environment: - TZ=$TZ ports: - "$GRAFANA_PORT:3000"# 设置容器3000端口映射指定宿主机端口,用于宿主机访问可视化web networks: - backend restart: alwaysjaeger: build: context: ./jaeger environment: - TZ=$TZ ports: - "$JAEGER_PORT:16686"# 设置容器16686端口映射指定宿主机端口,用于宿主机访问可视化web networks: - backend restart: alwaysdtm: build: context: ./dtm environment: - TZ=$TZ entrypoint: - "/app/dtm/dtm" - "-c=/app/dtm/configs/config.yaml" volumes: - ./dtm/config.yml:/app/dtm/configs/config.yaml # 将 dtm 配置文件挂载到容器里 ports: - "$DTM_HTTP_PORT:36789" - "$DTM_GRPC_PORT:36790" networks: - backend restart: always

2.4 构建与运行
  • 使用 docker-compose 命令来构建和启动运行我们的服务容器,在根目录执行如下命令:
$ docker-compose up -d

  • 容器构建中
    带你十天轻松搞定 Go 微服务系列

    文章图片

  • Windows 系统容器构建中出现如下图所示,请选择 Share it 这将允许 Windows 的文件目录挂载到容器目录中。
    带你十天轻松搞定 Go 微服务系列

    文章图片

  • 容器已启动运行
    带你十天轻松搞定 Go 微服务系列

    文章图片

    带你十天轻松搞定 Go 微服务系列

    文章图片

2.5 容器说明
容器名称 暴露端口 host地址 说明
golang 8000:8000< br> 8001:8001< br> 8002:8002< br> 8003:8003< br> 9000:9000< br> 9001:9001< br> 9002:9002< br> 9003:9003 golang 在生产环境中微服务一般都是集群部署,可能一个微服务一台服务器,也可能一个微服务一个容器。为了方便开发调试,我们将在 golang 容器中启动所有微服务,并为它们分配监听不同的端口号以示区分。< br> 80:开头的端口号我们将用于 api 服务 < br> 90:开头的端口号我们将用于 rpc 服务
dtm 36789:36789< br> 36790:36790 dtm dtmhttp 协议和 grpc 协议服务端口号,供客户端交互使用。< br> 此项目中我们只在 Docker 内部容器之间访问使用,所以也可以不暴露端口号给宿主机
etcd 2379:2379 etcd Etcd http api 服务端口号,供客户端交互使用。< br> 此项目中我们只在 Docker 内部容器之间访问使用,所以也可以不暴露端口号给宿主机
mysql 3306:3306 mysql Mysql 服务默认端口号,宿主机可通过 127.0.0.1:3306 进行数据库的连接
redis 6379:6379 redis Redis 服务默认端口号,宿主机可通过 127.0.0.1:6379 进行数据库的连接
mysql-manage 1000:80 mysql-manage phpMyAdmin web 服务端口号,可以在宿主机 127.0.0.1:1000 访问
redis-manage 2000:80 redis-manage phpRedisAdmin web 服务端口号,可以在宿主机 127.0.0.1:2000 访问
prometheus 3000:9090 prometheus Prometheus web 服务端口号,可以在宿主机 127.0.0.1:3000 访问
grafana 4000:3000 grafana Grafana web 服务端口号,可以在宿主机 127.0.0.1:4000 访问
jaeger 5000:16686 jaeger Jaeger web 服务端口号,可以在宿主机 127.0.0.1:5000 访问
2.6 访问验证
  • Mysql 访问验证
    带你十天轻松搞定 Go 微服务系列

    文章图片

  • Redis 访问验证
    带你十天轻松搞定 Go 微服务系列

    文章图片

  • Prometheus 访问验证
    带你十天轻松搞定 Go 微服务系列

    文章图片

  • Grafana 访问验证
    带你十天轻松搞定 Go 微服务系列

    文章图片

  • Jaeger 访问验证
    带你十天轻松搞定 Go 微服务系列

    文章图片
项目地址https://github.com/zeromicro/go-zero
欢迎使用 go-zero 并 star 支持我们!
微信交流群【带你十天轻松搞定 Go 微服务系列】关注『微服务实践』公众号并点击 交流群 获取社区群二维码。

    推荐阅读