Take you ten days to easily complete the Go micro service series

Posted by Pedestrian on Tue, 18 Jan 2022 09:26:59 +0100

At the beginning of this article, we will publish a series of articles to show you a go zero micro service example in detail. The whole series is divided into ten articles, and the directory structure is as follows:

  1. Environment construction (this paper)
  2. Service splitting
  3. User services
  4. Product service
  5. Order service
  6. Payment services
  7. RPC service Auth authentication
  8. Service monitoring
  9. Link tracking
  10. Distributed transaction

This series is expected to take you to quickly develop a mall system using go zero in the Docker environment on the machine, so that you can quickly start microservices.

Complete sample code: github.com/nivin-studio/go-zero-ma...

1 environmental requirements

  • Golang 1.15+
  • Etcd
  • Redis
  • Mysql
  • Prometheus
  • Grafana
  • Jaeger
  • DTM

2. Construction of docker local development environment

In order to facilitate development and debugging, we use Docker to build a local development environment. For Windows and macOS systems, you can download Docker Desktop for installation. For specific download and installation methods, you can search the relevant tutorials.

Here, we use Docker Compose to choreograph and manage our containers, and create the following directories:

gonivinck
├── dtm                   # DTM distributed transaction manager
│   ├── config.yml        # DTM profile
│   └── Dockerfile
├── etcd                  # Etcd service registration discovery
│   └── Dockerfile
├── golang                # Golang running environment
│   └── Dockerfile
├── grafana               # Grafana visual data monitoring
│   └── Dockerfile
├── jaeger                # Jaeger link tracking
│   └── Dockerfile
├── mysql                 # Mysql service
│   └── Dockerfile
├── mysql-manage          # Mysql visual management
│   └── Dockerfile
├── prometheus            # Prometheus service monitoring
│   ├── Dockerfile
│   └── prometheus.yml    # Prometheus profile
├── redis                 # Redis service
│   └── Dockerfile
├── redis-manage          # Redis visual management
│   └── Dockerfile
├── .env                  # env configuration
└── docker-compose.yml

2.1 writing Dockerfile

Grpc is used to communicate between services in go zero microservices, and the writing of grpc requires protocol and plug-in protocol Gen go translated into go language rpc stub code.

In order to improve development efficiency, reduce the error rate of code and shorten the workload of business development, go zero also provides goctl code generation tool.

Therefore, we need to install the protocol, protocol Gen go and goctl into the container of golang in advance for subsequent use.

Therefore, the Dockerfile code of the golang container is as follows:

FROM golang:1.17

LABEL maintainer="Ving <ving@nivin.cn>"

ENV GOPROXY https://goproxy.cn,direct

# Install the necessary software packages and dependent packages
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 

# Install goctl
USER root
RUN GOPROXY=https://goproxy.cn/,direct go install github.com/tal-tech/go-zero/tools/goctl@cli

# Install protoc ol
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

# Install protocol Gen go
USER root
RUN go get -u github.com/golang/protobuf/protoc-gen-go@v1.4.0

# $GOPATH/bin added to environment variable
ENV PATH $GOPATH/bin:$PATH

# Clean up garbage
USER root
RUN apt-get clean && \
    rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \
    rm /var/log/lastlog /var/log/faillog

# Set working directory
WORKDIR /usr/src/code

EXPOSE 8000
EXPOSE 8001
EXPOSE 8002
EXPOSE 8003
EXPOSE 9000
EXPOSE 9001
EXPOSE 9002
EXPOSE 9003

Other service containers dockerfiles do not need special processing, but are based on existing images.

service Based mirroring
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 preparation env profile

# Set time zone
TZ=Asia/Shanghai
# Set network mode
NETWORKS_DRIVER=bridge


# PATHS ##########################################
# The directory path where the code is stored on the host
CODE_PATH_HOST=./code
# The directory path where MySQL IDS data is stored on the host
DATA_PATH_HOST=./data


# MYSQL ##########################################
# Mysql service maps the host port number, which can be accessed in the host 127.0.0.1:3306
MYSQL_PORT=3306
MYSQL_USERNAME=admin
MYSQL_PASSWORD=123456
MYSQL_ROOT_PASSWORD=123456

# Mysql visual management user name, the same as MYSQL_USERNAME
MYSQL_MANAGE_USERNAME=admin
# Mysql visual management user password, the same as MYSQL_PASSWORD
MYSQL_MANAGE_PASSWORD=123456
# Mysql visual management root user password, the same as MYSQL_ROOT_PASSWORD
MYSQL_MANAGE_ROOT_PASSWORD=123456
# Mysql service address
MYSQL_MANAGE_CONNECT_HOST=mysql
# Mysql service port number
MYSQL_MANAGE_CONNECT_PORT=3306
# Mysql visual management maps the host port number, which can be accessed in the host 127.0.0.1:1000
MYSQL_MANAGE_PORT=1000


# REDIS ##########################################
# Redis service maps the port number of the host, which can be accessed at 127.0.0.1:6379 of the host
REDIS_PORT=6379

# Redis visual management user name
REDIS_MANAGE_USERNAME=admin
# Redis visual management user password
REDIS_MANAGE_PASSWORD=123456
# Redis service address
REDIS_MANAGE_CONNECT_HOST=redis
# Redis service port number
REDIS_MANAGE_CONNECT_PORT=6379
# Redis visual management maps the host port number, which can be accessed in the host 127.0.0.1:2000
REDIS_MANAGE_PORT=2000


# ETCD ###########################################
# The Etcd service maps the host port number, which can be accessed at the host 127.0.0.1:2379
ETCD_PORT=2379


# PROMETHEUS #####################################
# The Prometheus service maps the port number of the host, which can be accessed at the host 127.0.0.1:3000
PROMETHEUS_PORT=3000


# GRAFANA ########################################
# The Grafana service maps the port number of the host, which can be accessed at the host 127.0.0.1:4000
GRAFANA_PORT=4000


# JAEGER #########################################
# The Jaeger service maps the port number of the host, which can be accessed at the host 127.0.0.1:5000
JAEGER_PORT=5000


# DTM #########################################
# DTM HTTP protocol port number
DTM_HTTP_PORT=36789
# DTM gRPC protocol port number
DTM_GRPC_PORT=36790

2.3 write docker compose YML profile

version: '3.5'
# network configuration
networks:
  backend:
    driver: ${NETWORKS_DRIVER}

# Service container configuration
services:
  golang:                                # Custom container name
    build:
      context: ./golang                  # Specifies the Dockerfile file used for the build
    environment:                         # Setting environment variables
      - TZ=${TZ}
    volumes:                             # Set mount directory
      - ${CODE_PATH_HOST}:/usr/src/code  # quote. Code in env configuration_ PATH_ Host variable, mount the directory where the code is stored on the host to the / usr/src/code directory in the container
    ports:                               # Set port mapping
      - "8000:8000"
      - "8001:8001"
      - "8002:8002"
      - "8003:8003"
      - "9000:9000"
      - "9001:9001"
      - "9002:9002"
      - "9003:9003"
    stdin_open: true                     # Open standard input to accept external input
    tty: true
    networks:
      - backend
    restart: always                      # Specifies that the restart policy after the container exits is always restart

  etcd:                                  # Custom container name
    build:
      context: ./etcd                    # Specifies the Dockerfile file used for the build
    environment:
      - TZ=${TZ}
      - ALLOW_NONE_AUTHENTICATION=yes
    ports:                               # Set port mapping
      - "${ETCD_PORT}:2379"
    networks:
      - backend
    restart: always

  mysql:
    build:
      context: ./mysql
    environment:
      - TZ=${TZ}
      - MYSQL_USER=${MYSQL_USERNAME}                  # Set Mysql user name
      - MYSQL_PASSWORD=${MYSQL_PASSWORD}              # Set Mysql user password
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}    # Set Mysql root user password
    volumes:
      - ${DATA_PATH_HOST}/mysql:/var/lib/mysql        # quote. Data in env configuration_ PATH_ Host variable, mount the directory where Mysql data is stored on the host to the / var/lib/mysql directory in the container
    ports:
      - "${MYSQL_PORT}:3306"                          # Set container 3306 port mapping to specify the host port
    networks:
      - backend
    restart: always

  redis:
    build:
      context: ./redis
    environment:
      - TZ=${TZ}
    volumes:
      - ${DATA_PATH_HOST}/redis:/data                 # quote. Data in env configuration_ PATH_ Host variable, which mounts the directory where Redis data is stored on the host to the / data directory in the container
    ports:
      - "${REDIS_PORT}:6379"                          # Set container 6379 port mapping to specify host port
    networks:
      - backend
    restart: always

  mysql-manage:
    build:
      context: ./mysql-manage
    environment:
      - TZ=${TZ}
      - PMA_ARBITRARY=1
      - MYSQL_USER=${MYSQL_MANAGE_USERNAME}               # Set the Mysql service user name of the connection
      - MYSQL_PASSWORD=${MYSQL_MANAGE_PASSWORD}           # Set the password of the connected Mysql service user
      - MYSQL_ROOT_PASSWORD=${MYSQL_MANAGE_ROOT_PASSWORD} # Set the root password of the connected Mysql service
      - PMA_HOST=${MYSQL_MANAGE_CONNECT_HOST}             # Set the connected Mysql service host, which can be the name of the Mysql service container or the ip address of the Mysql service container
      - PMA_PORT=${MYSQL_MANAGE_CONNECT_PORT}             # Set the Mysql service port number of the connection
    ports:
      - "${MYSQL_MANAGE_PORT}:80"                         # Set the container 80 port mapping to specify the host port for the host to access the visual web
    depends_on:                                           # Dependent container
      - mysql                                             # Start after the Mysql service container starts
    networks:
      - backend
    restart: always

  redis-manage:
    build:
      context: ./redis-manage
    environment:
      - TZ=${TZ}
      - ADMIN_USER=${REDIS_MANAGE_USERNAME}           # Set the user name of Redis visual management
      - ADMIN_PASS=${REDIS_MANAGE_PASSWORD}           # Set user password for Redis visual management
      - REDIS_1_HOST=${REDIS_MANAGE_CONNECT_HOST}     # Set the connected Redis service host, which can be the name of the Redis service container or the ip address of the Redis service container
      - REDIS_1_PORT=${REDIS_MANAGE_CONNECT_PORT}     # Set the connected Redis service port number
    ports:
      - "${REDIS_MANAGE_PORT}:80"                     # Set the container 80 port mapping to specify the host port for the host to access the visual web
    depends_on:                                       # Dependent container
      - redis                                         # Start after the Redis service container is started
    networks:
      - backend
    restart: always

  prometheus:
    build:
      context: ./prometheus
    environment:
      - TZ=${TZ}
    volumes:
      - ./prometheus/prometheus.yml:/opt/bitnami/prometheus/conf/prometheus.yml  # Mount the prometheus configuration file into the container
    ports:
      - "${PROMETHEUS_PORT}:9090"                     # Set the container 9090 port mapping to specify the host port for the host to access the visual web
    networks:
      - backend
    restart: always

  grafana:
    build:
      context: ./grafana
    environment:
      - TZ=${TZ}
    ports:
      - "${GRAFANA_PORT}:3000"                        # Set the container 3000 port mapping to specify the host port for the host to access the visual web
    networks:
      - backend
    restart: always

  jaeger:
    build:
      context: ./jaeger
    environment:
      - TZ=${TZ}
    ports:
      - "${JAEGER_PORT}:16686"                        # Set the container 16686 port mapping to specify the host port for the host to access the visual 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 # Mount the dtm configuration file into the container
    ports:
      - "${DTM_HTTP_PORT}:36789"
      - "${DTM_GRPC_PORT}:36790"
    networks:
      - backend
    restart: always

2.4 construction and operation

  • Use the docker compose command to build and start our service container, and execute the following commands in the root directory:
$ docker-compose up -d
  • Container building

  • In the Windows system container build, as shown in the figure below, please select Share it, which will allow the file directory of Windows to be mounted in the container directory.

  • Container started running

2.5 vessel description

Container name Exposed port host address explain
golang 8000:8000
8001:8001
8002:8002
8003:8003
9000:9000
9001:9001
9002:9002
9003:9003
golang In the production environment, microservices are generally deployed in clusters. One microservice may be a server, or one microservice may be a container. To facilitate development and debugging, we will start all microservices in the golang container and assign them different port numbers to listen to.
80: the port number at the beginning will be used for api services
90: the port number at the beginning will be used for rpc service
dtm 36789:36789
36790:36790
dtm The http protocol and grpc protocol service port number of dtm are used for client interaction.
In this project, we only access and use between Docker internal containers, so we can also not expose the port number to the host
etcd 2379:2379 etcd Etcd http api service port number for client interaction.
In this project, we only access and use between Docker internal containers, so we can also not expose the port number to the host
mysql 3306:3306 mysql The default port number of Mysql service. The host can connect to the database through 127.0.0.1:3306
redis 6379:6379 redis The default port number of Redis service. The host can connect to the database through 127.0.0.1:6379
mysql-manage 1000:80 mysql-manage phpMyAdmin web service port number, which can be accessed on the host machine 127.0.0.1:1000
redis-manage 2000:80 redis-manage phpRedisAdmin web service port number, which can be accessed on the host machine 127.0.0.1:2000
prometheus 3000:9090 prometheus Prometheus web service port number, which can be accessed on the host machine 127.0.0.1:3000
grafana 4000:3000 grafana Grafana web service port number, which can be accessed on the host 127.0.0.1:4000
jaeger 5000:16686 jaeger Jaeger web service port number, which can be accessed on the host 127.0.0.1:5000

2.6 access verification

  • Mysql access verification

  • Redis access verification

  • Prometheus access authentication

  • Grafana access authentication

  • Jaeger access authentication

Project address

github.com/zeromicro/go-zero

Welcome to go zero and star support us!

Wechat communication group

Focus on the "micro service practice" official account and click on the exchange group to get the community community's two-dimensional code.

Topics: Go Framework Microservices go-zero