您的位置:  首页 > 技术 > go语言 > 正文

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

2022-01-17 15:00 https://my.oschina.net/kevwan/blog/5400102 kevwan 次阅读 条评论

本文开始,我们会出一个系列文章跟大家详细展示一个 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.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 



# 安装 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/code



EXPOSE 8000

EXPOSE 8001

EXPOSE 8002

EXPOSE 8003

EXPOSE 9000

EXPOSE 9001

EXPOSE 9002

EXPOSE 9003

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

服务基于的镜像
DTMyedf/dtm
Etcdbitnami/etcd
Mysqlmysql:5.7
Redisredis:5.0
Mysql Managephpmyadmin/phpmyadmin
Redis Manageerikdubbelboer/phpredisadmin
Prometheusbitnami/prometheus
Grafanagrafana/grafana
Jaegerjaegertracing/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

    ports:                               # 设置端口映射

      - "${ETCD_PORT}:2379"

    networks:

      - backend

    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

    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

    restart: always



  mysql-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: always



  redis-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: always



  prometheus:

    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: always



  grafana:

    build:

      context: ./grafana

    environment:

      - TZ=${TZ}

    ports:

      - "${GRAFANA_PORT}:3000"                        # 设置容器3000端口映射指定宿主机端口,用于宿主机访问可视化web

    networks:

      - backend

    restart: always



  jaeger:

    build:

      context: ./jaeger

    environment:

      - TZ=${TZ}

    ports:

      - "${JAEGER_PORT}:16686"                        # 设置容器16686端口映射指定宿主机端口,用于宿主机访问可视化web

    networks:

      - backend

    restart: always



  dtm:

    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

  • 容器构建中

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

  • 容器已启动运行

2.5 容器说明

容器名称暴露端口host地址说明
golang8000:8000<br>8001:8001<br>8002:8002<br>8003:8003<br>9000:9000<br>9001:9001<br>9002:9002<br>9003:9003golang在生产环境中微服务一般都是集群部署,可能一个微服务一台服务器,也可能一个微服务一个容器。为了方便开发调试,我们将在 golang 容器中启动所有微服务,并为它们分配监听不同的端口号以示区分。<br>80:开头的端口号我们将用于 api 服务 <br>90:开头的端口号我们将用于 rpc 服务
dtm36789:36789<br>36790:36790dtmdtmhttp 协议和 grpc 协议服务端口号,供客户端交互使用。<br>此项目中我们只在 Docker 内部容器之间访问使用,所以也可以不暴露端口号给宿主机
etcd2379:2379etcdEtcd http api 服务端口号,供客户端交互使用。<br>此项目中我们只在 Docker 内部容器之间访问使用,所以也可以不暴露端口号给宿主机
mysql3306:3306mysqlMysql 服务默认端口号,宿主机可通过 127.0.0.1:3306 进行数据库的连接
redis6379:6379redisRedis 服务默认端口号,宿主机可通过 127.0.0.1:6379 进行数据库的连接
mysql-manage1000:80mysql-managephpMyAdmin web 服务端口号,可以在宿主机 127.0.0.1:1000 访问
redis-manage2000:80redis-managephpRedisAdmin web 服务端口号,可以在宿主机 127.0.0.1:2000 访问
prometheus3000:9090prometheusPrometheus web 服务端口号,可以在宿主机 127.0.0.1:3000 访问
grafana4000:3000grafanaGrafana web 服务端口号,可以在宿主机 127.0.0.1:4000 访问
jaeger5000:16686jaegerJaeger web 服务端口号,可以在宿主机 127.0.0.1:5000 访问

2.6 访问验证

  • Mysql 访问验证

  • Redis 访问验证

  • Prometheus 访问验证

  • Grafana 访问验证

  • Jaeger 访问验证

项目地址

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

https://gitee.com/kevwan/go-zero

欢迎使用 go-zerostar 支持我们!

微信交流群

关注『微服务实践』公众号并点击 交流群 获取社区群二维码。/ving@nivin.cn

展开阅读全文                                    
  • 0
    感动
  • 0
    路过
  • 0
    高兴
  • 0
    难过
  • 0
    搞笑
  • 0
    无聊
  • 0
    愤怒
  • 0
    同情
热度排行
友情链接