go-zero实战:让微服务Go起来——2环境搭建

2.1 环境要求

  • Golang 1.17
  • Etcd
  • Redis
  • Mysql
  • Prometheus
  • Grafana
  • Jaeger

2.2 Docker 本地开发环境搭建

为了方便开发调试,我们使用 Docker 构建本地开发环境。WindowsmacOS 系统可下载 Docker Desktop 安装使用,具体下载安装方法可自行搜索相关教程。

这里我们使用 Docker Compose 来编排管理我们的容器,创建如下目录:

golang
├── 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 配置文件
│   └── targets.json
├── redis                 # Redis 服务
│   └── Dockerfile
├── redis-manage          # Redis 可视化管理
│   └── Dockerfile
├── .env                  # env 配置
└── docker-compose.yml
复制代码

2.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.17

LABEL 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 

# 安装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 && \
    cp -r /tmp/protoc /usr/local/protoc

# protoc添加到环境变量中
ENV PATH /usr/local/protoc/bin:$PATH

# 安装 goctl 和 protoc-gen-go
RUN go get -u github.com/tal-tech/go-zero/tools/goctl && \
    go get -u github.com/golang/protobuf/protoc-gen-go@v1.3.2

# 清理垃圾
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/code

EXPOSE 8000
EXPOSE 8001
EXPOSE 8002
EXPOSE 8003
EXPOSE 8004
EXPOSE 8005
EXPOSE 8006
复制代码

其他服务容器 Dockerfile 无需特殊处理,只要基于现有的镜像即可。

服务 基于的镜像
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.2 编写 .env 配置文件

TZ=Asia/Shanghai              # 设置时区

# Paths ##########################################
CODE_PATH_HOST=./code         # 宿主机上代码存放的目录路径
DATA_PATH_HOST=./data         # 宿主机上Mysql Reids数据存放的目录路径

# MYSQL ##########################################
MYSQL_HOST=mysql
MYSQL_PORT=3306               # Mysql 服务映射宿主机端口号,可在宿主机127.0.0.1:3306访问
MYSQL_USERNAME=admin
MYSQL_PASSWORD=123456
MYSQL_ROOT_PASSWORD=123456

MYSQL_MANAGE_PORT=1000        # Mysql 可视化管理映射宿主机端口号,可在宿主机127.0.0.1:1000访问

# REDIS ##########################################
REDIS_HOST=redis
REDIS_PORT=6379               # Redis 服务映射宿主机端口号,可在宿主机127.0.0.1:6379访问

REDIS_MANAGE_USERNAME=admin   # Redis 可视化管理用户名称
REDIS_MANAGE_PASSWORD=123456  # Redis 可视化管理用户密码
REDIS_MANAGE_PORT=2000        # Redis 可视化管理映射宿主机端口号,可在宿主机127.0.0.1:2000访问

# ETCD ###########################################
ETCD_PORT=2379                # Etcd 服务映射宿主机端口号,可在宿主机127.0.0.1:2379访问

# PROMETHEUS #####################################
PROMETHEUS_PORT=3000          # Prometheus 服务映射宿主机端口号,可在宿主机127.0.0.1:3000访问

# GRAFANA ########################################
GRAFANA_PORT=4000             # Grafana 服务映射宿主机端口号,可在宿主机127.0.0.1:4000访问

# JAEGER #########################################
JAEGER_PORT=5000              # Jaeger 服务映射宿主机端口号,可在宿主机127.0.0.1:5000访问
复制代码

2.2.3 编写 docker-compose.yml 配置文件

version: '3.0'
# 网络配置
networks:
  backend:                       # 自定义网络名称    
    driver: bridge               # 网络模式
    ipam:                        # ip地址管理
      config:                    # 配置信息
        - subnet: 172.30.0.0/16  # 网段配置

# 服务容器配置
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:                           # 指定网络配置名称
        ipv4_address: 172.30.0.2         # 指定容器ip地址,需要符合在指定网络配置的网段中
    restart: always                      # 指定容器退出后的重启策略为始终重启

  etcd:                                  # 自定义容器名称
    build:
      context: ./etcd                    # 指定构建使用的 Dockerfile 文件
    environment:
      - TZ=${TZ}
      - ALLOW_NONE_AUTHENTICATION=yes
    ports:                               # 设置端口映射
      - "${ETCD_PORT}:2379"
    networks:
      backend:
        ipv4_address: 172.30.0.3         # 指定容器 ip 地址,需要符合在指定网络配置的网段中
    restart: always

  mysql:
    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:
        ipv4_address: 172.30.0.4
    restart: always

  redis:
    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:
        ipv4_address: 172.30.0.5
    restart: always

  mysql-manage:
    build:
      context: ./mysql-manage
    environment:
      - TZ=${TZ}
      - MYSQL_USER=${MYSQL_USERNAME}                  # 设置连接的 Mysql 服务用户名称
      - MYSQL_PASSWORD=${MYSQL_PASSWORD}              # 设置连接的 Mysq l服务用户密码
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}    # 设置连接的 Mysql 服务 root 用户密码
      - PMA_ARBITRARY=1
      - PMA_HOST=${MYSQL_HOST}                        # 设置连接的 Mysql 服务 host,可以是 Mysql 服务容器的名称,也可以是 Mysql 服务容器的 ip 地址
      - PMA_PORT=3306                                 # 设置连接的 Mysql 服务端口号
    ports:
      - "${MYSQL_MANAGE_PORT}:80"                     # 设置容器80端口映射指定宿主机端口,用于宿主机访问可视化web
    depends_on:                                       # 依赖容器
      - mysql                                         # 在 Mysql 服务容器启动后启动
    networks:
      backend:
        ipv4_address: 172.30.0.6
    restart: always

  redis-manage:
    build:
      context: ./redis-manage
    environment:
      - TZ=${TZ}
      - REDIS_1_HOST=${REDIS_HOST}                    # 设置连接的 Redis 服务 host,可以是 Redis 服务容器的名称,也可以是 Redis 服务容器的 ip 地址
      - REDIS_1_PORT=6379                             # 设置连接的 Redis 服务端口号
      - ADMIN_USER=${REDIS_MANAGE_USERNAME}           # 设置 Redis 可视化管理的用户名称
      - ADMIN_PASS=${REDIS_MANAGE_PASSWORD}           # 设置 Redis 可视化管理的用户密码
    ports:
      - "${REDIS_MANAGE_PORT}:80"                     # 设置容器80端口映射指定宿主机端口,用于宿主机访问可视化web
    depends_on:                                       # 依赖容器
      - redis                                         # 在 Redis 服务容器启动后启动
    networks:
      backend:
        ipv4_address: 172.30.0.7
    restart: always

  prometheus:
    build:
      context: ./prometheus
    environment:
      - TZ=${TZ}
    volumes:
      - ./prometheus/prometheus.yml:/opt/bitnami/prometheus/conf/prometheus.yml  # 将 prometheus 配置文件挂载到容器里
      - ./prometheus/targets.json:/opt/bitnami/prometheus/conf/targets.json
    ports:
      - "${PROMETHEUS_PORT}:9090"                     # 设置容器9090端口映射指定宿主机端口,用于宿主机访问可视化web
    networks:
      backend:
        ipv4_address: 172.30.0.8
    restart: always

  grafana:
    build:
      context: ./grafana
    environment:
      - TZ=${TZ}
    ports:
      - "${GRAFANA_PORT}:3000"                        # 设置容器3000端口映射指定宿主机端口,用于宿主机访问可视化web
    networks:
      backend:
        ipv4_address: 172.30.0.9
    restart: always

  jaeger:
    build:
      context: ./jaeger
    environment:
      - TZ=${TZ}
    ports:
      - "${JAEGER_PORT}:16686"                        # 设置容器16686端口映射指定宿主机端口,用于宿主机访问可视化web
    networks:
      backend:
        ipv4_address: 172.30.0.10
    restart: always
复制代码

2.2.4 构建与运行

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

image.png

  • Windows 系统容器构建中出现如下图所示,请选择 Share it 这将允许 Windows 的文件目录挂载到容器目录中。

image.png

  • 容器已启动运行

image.png

image.png

2.2.5 容器说明

容器名称 暴露端口 IP地址 说明
golang 8000:8000
8001:8001
8002:8002
8003:8003
9000:9000
9001:9001
9002:9002
9003:9003
172.30.0.2 在生产环境中微服务一般都是集群部署,可能一个微服务一台服务器,也可能一个微服务一个容器。为了方便开发调试,我们将在 golang 容器中启动所有微服务,并为它们分配监听不同的端口号以示区分。
80:开头的端口号我们将用于 api 服务
90:开头的端口号我们将用于 rpc 服务
etcd 2379:2379 172.30.0.3 Etcd http api 服务端口号,供客户端交互使用。
此项目中我们只在 Docker 内部容器之间访问使用,所以也可以不暴露端口号给宿主机
mysql 3306:3306 172.30.0.4 Mysql 服务默认端口号,宿主机可通过 127.0.0.1:3306 进行数据库的连接
redis 6379:6379 172.30.0.5 Redis 服务默认端口号,宿主机可通过 127.0.0.1:6379 进行数据库的连接
mysql-manage 1000:80 172.30.0.6 phpMyAdmin web 服务端口号,可以在宿主机 127.0.0.1:1000 访问
redis-manage 2000:80 172.30.0.7 phpRedisAdmin web 服务端口号,可以在宿主机 127.0.0.1:2000 访问
prometheus 3000:9090 172.30.0.8 Prometheus web 服务端口号,可以在宿主机 127.0.0.1:3000 访问
grafana 4000:3000 172.30.0.9 Grafana web 服务端口号,可以在宿主机 127.0.0.1:4000 访问
jaeger 5000:16686 172.30.0.10 Jaeger web 服务端口号,可以在宿主机 127.0.0.1:5000 访问

2.2.6 访问验证

  • Mysql 访问验证

image.png

  • Redis 访问验证

image.png

  • Prometheus 访问验证

image.png

  • Grafana 访问验证

image.png

  • Jaeger 访问验证

image.png