帶你十天輕鬆搞定 Go 微服務系列(一)
本文開始,我們會出一個系列文章跟大家詳細展示一個 go-zero 微服務示例,整個系列分十篇文章,目錄結構如下:
- 環境搭建(本文)
- 服務拆分
- 用戶服務
- 產品服務
- 訂單服務
- 支付服務
- RPC 服務 Auth 驗證
- 服務監控
- 鏈路追蹤
- 分佈式事務
期望通過本系列帶你在本機利用 Docker 環境利用 go-zero 快速開發一個商城系統,讓你快速上手微服務。
完整示例代碼://github.com/nivin-studio/go-zero-mall
1 環境要求
Golang
1.15+Etcd
Redis
Mysql
Prometheus
Grafana
Jaeger
DTM
2 Docker
本地開發環境搭建
為了方便開發調試,我們使用 Docker
構建本地開發環境。Windows
和 macOS
系統可下載 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 <[email protected]>"
ENV GOPROXY //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=//goproxy.cn/,direct go install github.com/tal-tech/go-zero/tools/goctl@cli
# 安裝 protoc
USER root
RUN curl -L -o /tmp/protoc.zip //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/[email protected]
# $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
無需特殊處理,只要基於現有的鏡像即可。
服務 | 基於的鏡像 |
---|---|
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
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地址 | 說明 |
---|---|---|---|
golang | 8000:8000 8001:8001 8002:8002 8003:8003 9000:9000 9001:9001 9002:9002 9003:9003 |
golang | 在生產環境中微服務一般都是集群部署,可能一個微服務一台服務器,也可能一個微服務一個容器。為了方便開發調試,我們將在 golang 容器中啟動所有微服務,並為它們分配監聽不同的端口號以示區分。80:開頭的端口號我們將用於 api 服務 90:開頭的端口號我們將用於 rpc 服務 |
dtm | 36789:36789 36790:36790 |
dtm | dtm 的 http 協議和 grpc 協議服務端口號,供客戶端交互使用。此項目中我們只在 Docker 內部容器之間訪問使用,所以也可以不暴露端口號給宿主機 |
etcd | 2379:2379 | etcd | Etcd http api 服務端口號,供客戶端交互使用。此項目中我們只在 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
訪問驗證
-
Redis
訪問驗證
-
Prometheus
訪問驗證
-
Grafana
訪問驗證
-
Jaeger
訪問驗證
項目地址
//github.com/zeromicro/go-zero
歡迎使用 go-zero
並 star 支持我們!
微信交流群
關注『微服務實踐』公眾號並點擊 交流群 獲取社區群二維碼。