帶你十天輕松搞定 Go 微服務(wù)系列(一)
本文開始,我們會(huì)出一個(gè)系列文章跟大家詳細(xì)展示一個(gè) go-zero 微服務(wù)示例,整個(gè)系列分十篇文章,目錄結(jié)構(gòu)如下:
環(huán)境搭建(本文) 服務(wù)拆分 用戶服務(wù) 產(chǎn)品服務(wù) 訂單服務(wù) 支付服務(wù) RPC 服務(wù) Auth 驗(yàn)證 服務(wù)監(jiān)控 鏈路追蹤 分布式事務(wù)
期望通過本系列帶你在本機(jī)利用 Docker 環(huán)境利用 go-zero 快速開發(fā)一個(gè)商城系統(tǒng),讓你快速上手微服務(wù)。
完整示例代碼:https://github.com/nivin-studio/go-zero-mall
1 環(huán)境要求
Golang1.15+EtcdRedisMysqlPrometheusGrafanaJaegerDTM
2 Docker 本地開發(fā)環(huán)境搭建
為了方便開發(fā)調(diào)試,我們使用 Docker 構(gòu)建本地開發(fā)環(huán)境。Windows 和 macOS 系統(tǒng)可下載 Docker Desktop 安裝使用,具體下載安裝方法可自行搜索相關(guān)教程。
這里我們使用 Docker Compose 來編排管理我們的容器,創(chuàng)建如下目錄:
gonivinck
├──?dtm???????????????????#?DTM?分布式事務(wù)管理器
│???├──?config.yml????????#?DTM?配置文件
│???└──?Dockerfile
├──?etcd??????????????????#?Etcd?服務(wù)注冊(cè)發(fā)現(xiàn)
│???└──?Dockerfile
├──?golang????????????????#?Golang?運(yùn)行環(huán)境
│???└──?Dockerfile
├──?grafana???????????????#?Grafana?可視化數(shù)據(jù)監(jiān)控
│???└──?Dockerfile
├──?jaeger????????????????#?Jaeger?鏈路追蹤
│???└──?Dockerfile
├──?mysql?????????????????#?Mysql?服務(wù)
│???└──?Dockerfile
├──?mysql-manage??????????#?Mysql?可視化管理
│???└──?Dockerfile
├──?prometheus????????????#?Prometheus?服務(wù)監(jiān)控
│???├──?Dockerfile
│???└──?prometheus.yml????#?Prometheus?配置文件
├──?redis?????????????????#?Redis?服務(wù)
│???└──?Dockerfile
├──?redis-manage??????????#?Redis?可視化管理
│???└──?Dockerfile
├──?.env??????????????????#?env?配置
└──?docker-compose.yml
2.1 編寫 Dockerfile
在 go-zero 的微服務(wù)中采用 grpc 進(jìn)行服務(wù)間的通信,而 grpc 的編寫就需要用到 protoc 和翻譯成 go 語言 rpc stub 代碼的插件 protoc-gen-go。
為了提高開發(fā)效率,減少代碼的出錯(cuò)率,縮短業(yè)務(wù)開發(fā)的工作量,go-zero 還提供了 goctl 代碼生成工具。
因此,我們需要將 protoc, protoc-gen-go, goctl, 給提前安裝到 golang 的容器中,以便后續(xù)使用。
所以 golang 容器的 Dockerfile 代碼如下:
FROM?golang:1.17
LABEL?maintainer="Ving?"
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/[email protected]
#?$GOPATH/bin添加到環(huán)境變量中
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
#?設(shè)置工作目錄
WORKDIR?/usr/src/code
EXPOSE?8000
EXPOSE?8001
EXPOSE?8002
EXPOSE?8003
EXPOSE?9000
EXPOSE?9001
EXPOSE?9002
EXPOSE?9003
其他服務(wù)容器 Dockerfile 無需特殊處理,只要基于現(xiàn)有的鏡像即可。
| 服務(wù) | 基于的鏡像 |
|---|---|
| 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 配置文件
#?設(shè)置時(shí)區(qū)
TZ=Asia/Shanghai
#?設(shè)置網(wǎng)絡(luò)模式
NETWORKS_DRIVER=bridge
#?PATHS?##########################################
#?宿主機(jī)上代碼存放的目錄路徑
CODE_PATH_HOST=./code
#?宿主機(jī)上Mysql?Reids數(shù)據(jù)存放的目錄路徑
DATA_PATH_HOST=./data
#?MYSQL?##########################################
#?Mysql?服務(wù)映射宿主機(jī)端口號(hào),可在宿主機(jī)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?服務(wù)地址
MYSQL_MANAGE_CONNECT_HOST=mysql
#?Mysql?服務(wù)端口號(hào)
MYSQL_MANAGE_CONNECT_PORT=3306
#?Mysql?可視化管理映射宿主機(jī)端口號(hào),可在宿主機(jī)127.0.0.1:1000訪問
MYSQL_MANAGE_PORT=1000
#?REDIS?##########################################
#?Redis?服務(wù)映射宿主機(jī)端口號(hào),可在宿主機(jī)127.0.0.1:6379訪問
REDIS_PORT=6379
#?Redis?可視化管理用戶名稱
REDIS_MANAGE_USERNAME=admin
#?Redis?可視化管理用戶密碼
REDIS_MANAGE_PASSWORD=123456
#?Redis?服務(wù)地址
REDIS_MANAGE_CONNECT_HOST=redis
#?Redis?服務(wù)端口號(hào)
REDIS_MANAGE_CONNECT_PORT=6379
#?Redis?可視化管理映射宿主機(jī)端口號(hào),可在宿主機(jī)127.0.0.1:2000訪問
REDIS_MANAGE_PORT=2000
#?ETCD?###########################################
#?Etcd?服務(wù)映射宿主機(jī)端口號(hào),可在宿主機(jī)127.0.0.1:2379訪問
ETCD_PORT=2379
#?PROMETHEUS?#####################################
#?Prometheus?服務(wù)映射宿主機(jī)端口號(hào),可在宿主機(jī)127.0.0.1:3000訪問
PROMETHEUS_PORT=3000
#?GRAFANA?########################################
#?Grafana?服務(wù)映射宿主機(jī)端口號(hào),可在宿主機(jī)127.0.0.1:4000訪問
GRAFANA_PORT=4000
#?JAEGER?#########################################
#?Jaeger?服務(wù)映射宿主機(jī)端口號(hào),可在宿主機(jī)127.0.0.1:5000訪問
JAEGER_PORT=5000
#?DTM?#########################################
#?DTM?HTTP?協(xié)議端口號(hào)
DTM_HTTP_PORT=36789
#?DTM?gRPC?協(xié)議端口號(hào)
DTM_GRPC_PORT=36790
2.3 編寫 docker-compose.yml 配置文件
version:?'3.5'
#?網(wǎng)絡(luò)配置
networks:
??backend:
????driver:?${NETWORKS_DRIVER}
#?服務(wù)容器配置
services:
??golang:????????????????????????????????#?自定義容器名稱
????build:
??????context:?./golang??????????????????#?指定構(gòu)建使用的?Dockerfile?文件
????environment:?????????????????????????#?設(shè)置環(huán)境變量
??????-?TZ=${TZ}
????volumes:?????????????????????????????#?設(shè)置掛載目錄
??????-?${CODE_PATH_HOST}:/usr/src/code??#?引用?.env?配置中?CODE_PATH_HOST?變量,將宿主機(jī)上代碼存放的目錄掛載到容器中?/usr/src/code?目錄
????ports:???????????????????????????????#?設(shè)置端口映射
??????-?"8000:8000"
??????-?"8001:8001"
??????-?"8002:8002"
??????-?"8003:8003"
??????-?"9000:9000"
??????-?"9001:9001"
??????-?"9002:9002"
??????-?"9003:9003"
????stdin_open:?true?????????????????????#?打開標(biāo)準(zhǔn)輸入,可以接受外部輸入
????tty:?true
????networks:
??????-?backend
????restart:?always??????????????????????#?指定容器退出后的重啟策略為始終重啟
??etcd:??????????????????????????????????#?自定義容器名稱
????build:
??????context:?./etcd????????????????????#?指定構(gòu)建使用的?Dockerfile?文件
????environment:
??????-?TZ=${TZ}
??????-?ALLOW_NONE_AUTHENTICATION=yes
????ports:???????????????????????????????#?設(shè)置端口映射
??????-?"${ETCD_PORT}:2379"
????networks:
??????-?backend
????restart:?always
??mysql:
????build:
??????context:?./mysql
????environment:
??????-?TZ=${TZ}
??????-?MYSQL_USER=${MYSQL_USERNAME}??????????????????#?設(shè)置?Mysql?用戶名稱
??????-?MYSQL_PASSWORD=${MYSQL_PASSWORD}??????????????#?設(shè)置?Mysql?用戶密碼
??????-?MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}????#?設(shè)置?Mysql?root?用戶密碼
????volumes:
??????-?${DATA_PATH_HOST}/mysql:/var/lib/mysql????????#?引用?.env?配置中?DATA_PATH_HOST?變量,將宿主機(jī)上存放?Mysql?數(shù)據(jù)的目錄掛載到容器中?/var/lib/mysql?目錄
????ports:
??????-?"${MYSQL_PORT}:3306"??????????????????????????#?設(shè)置容器3306端口映射指定宿主機(jī)端口
????networks:
??????-?backend
????restart:?always
??redis:
????build:
??????context:?./redis
????environment:
??????-?TZ=${TZ}
????volumes:
??????-?${DATA_PATH_HOST}/redis:/data?????????????????#?引用?.env?配置中?DATA_PATH_HOST?變量,將宿主機(jī)上存放?Redis?數(shù)據(jù)的目錄掛載到容器中?/data?目錄
????ports:
??????-?"${REDIS_PORT}:6379"??????????????????????????#?設(shè)置容器6379端口映射指定宿主機(jī)端口
????networks:
??????-?backend
????restart:?always
??mysql-manage:
????build:
??????context:?./mysql-manage
????environment:
??????-?TZ=${TZ}
??????-?PMA_ARBITRARY=1
??????-?MYSQL_USER=${MYSQL_MANAGE_USERNAME}???????????????#?設(shè)置連接的?Mysql?服務(wù)用戶名稱
??????-?MYSQL_PASSWORD=${MYSQL_MANAGE_PASSWORD}???????????#?設(shè)置連接的?Mysql?服務(wù)用戶密碼
??????-?MYSQL_ROOT_PASSWORD=${MYSQL_MANAGE_ROOT_PASSWORD}?#?設(shè)置連接的?Mysql?服務(wù)?root?用戶密碼
??????-?PMA_HOST=${MYSQL_MANAGE_CONNECT_HOST}?????????????#?設(shè)置連接的?Mysql?服務(wù)?host,可以是?Mysql?服務(wù)容器的名稱,也可以是?Mysql?服務(wù)容器的?ip?地址
??????-?PMA_PORT=${MYSQL_MANAGE_CONNECT_PORT}?????????????#?設(shè)置連接的?Mysql?服務(wù)端口號(hào)
????ports:
??????-?"${MYSQL_MANAGE_PORT}:80"?????????????????????????#?設(shè)置容器80端口映射指定宿主機(jī)端口,用于宿主機(jī)訪問可視化web
????depends_on:???????????????????????????????????????????#?依賴容器
??????-?mysql?????????????????????????????????????????????#?在?Mysql?服務(wù)容器啟動(dòng)后啟動(dòng)
????networks:
??????-?backend
????restart:?always
??redis-manage:
????build:
??????context:?./redis-manage
????environment:
??????-?TZ=${TZ}
??????-?ADMIN_USER=${REDIS_MANAGE_USERNAME}???????????#?設(shè)置?Redis?可視化管理的用戶名稱
??????-?ADMIN_PASS=${REDIS_MANAGE_PASSWORD}???????????#?設(shè)置?Redis?可視化管理的用戶密碼
??????-?REDIS_1_HOST=${REDIS_MANAGE_CONNECT_HOST}?????#?設(shè)置連接的?Redis?服務(wù)?host,可以是?Redis?服務(wù)容器的名稱,也可以是?Redis?服務(wù)容器的?ip?地址
??????-?REDIS_1_PORT=${REDIS_MANAGE_CONNECT_PORT}?????#?設(shè)置連接的?Redis?服務(wù)端口號(hào)
????ports:
??????-?"${REDIS_MANAGE_PORT}:80"?????????????????????#?設(shè)置容器80端口映射指定宿主機(jī)端口,用于宿主機(jī)訪問可視化web
????depends_on:???????????????????????????????????????#?依賴容器
??????-?redis?????????????????????????????????????????#?在?Redis?服務(wù)容器啟動(dòng)后啟動(dòng)
????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"?????????????????????#?設(shè)置容器9090端口映射指定宿主機(jī)端口,用于宿主機(jī)訪問可視化web
????networks:
??????-?backend
????restart:?always
??grafana:
????build:
??????context:?./grafana
????environment:
??????-?TZ=${TZ}
????ports:
??????-?"${GRAFANA_PORT}:3000"????????????????????????#?設(shè)置容器3000端口映射指定宿主機(jī)端口,用于宿主機(jī)訪問可視化web
????networks:
??????-?backend
????restart:?always
??jaeger:
????build:
??????context:?./jaeger
????environment:
??????-?TZ=${TZ}
????ports:
??????-?"${JAEGER_PORT}:16686"????????????????????????#?設(shè)置容器16686端口映射指定宿主機(jī)端口,用于宿主機(jī)訪問可視化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 構(gòu)建與運(yùn)行
使用 docker-compose命令來構(gòu)建和啟動(dòng)運(yùn)行我們的服務(wù)容器,在根目錄執(zhí)行如下命令:
$?docker-compose?up?-d
容器構(gòu)建中

在
Windows系統(tǒng)容器構(gòu)建中出現(xiàn)如下圖所示,請(qǐng)選擇Share it這將允許Windows的文件目錄掛載到容器目錄中。
容器已啟動(dòng)運(yùn)行


2.5 容器說明
| 容器名稱 | 暴露端口 | host地址 | 說明 |
|---|---|---|---|
| golang | 8000:8000 8001:8001 8002:8002 8003:8003 9000:9000 9001:9001 9002:9002 9003:9003 | golang | 在生產(chǎn)環(huán)境中微服務(wù)一般都是集群部署,可能一個(gè)微服務(wù)一臺(tái)服務(wù)器,也可能一個(gè)微服務(wù)一個(gè)容器。為了方便開發(fā)調(diào)試,我們將在 golang 容器中啟動(dòng)所有微服務(wù),并為它們分配監(jiān)聽不同的端口號(hào)以示區(qū)分。80:開頭的端口號(hào)我們將用于 api 服務(wù) 90:開頭的端口號(hào)我們將用于 rpc 服務(wù) |
| dtm | 36789:36789 36790:36790 | dtm | dtm 的 http 協(xié)議和 grpc 協(xié)議服務(wù)端口號(hào),供客戶端交互使用。此項(xiàng)目中我們只在 Docker 內(nèi)部容器之間訪問使用,所以也可以不暴露端口號(hào)給宿主機(jī) |
| etcd | 2379:2379 | etcd | Etcd http api 服務(wù)端口號(hào),供客戶端交互使用。此項(xiàng)目中我們只在 Docker 內(nèi)部容器之間訪問使用,所以也可以不暴露端口號(hào)給宿主機(jī) |
| mysql | 3306:3306 | mysql | Mysql 服務(wù)默認(rèn)端口號(hào),宿主機(jī)可通過 127.0.0.1:3306 進(jìn)行數(shù)據(jù)庫的連接 |
| redis | 6379:6379 | redis | Redis 服務(wù)默認(rèn)端口號(hào),宿主機(jī)可通過 127.0.0.1:6379 進(jìn)行數(shù)據(jù)庫的連接 |
| mysql-manage | 1000:80 | mysql-manage | phpMyAdmin web 服務(wù)端口號(hào),可以在宿主機(jī) 127.0.0.1:1000 訪問 |
| redis-manage | 2000:80 | redis-manage | phpRedisAdmin web 服務(wù)端口號(hào),可以在宿主機(jī) 127.0.0.1:2000 訪問 |
| prometheus | 3000:9090 | prometheus | Prometheus web 服務(wù)端口號(hào),可以在宿主機(jī) 127.0.0.1:3000 訪問 |
| grafana | 4000:3000 | grafana | Grafana web 服務(wù)端口號(hào),可以在宿主機(jī) 127.0.0.1:4000 訪問 |
| jaeger | 5000:16686 | jaeger | Jaeger web 服務(wù)端口號(hào),可以在宿主機(jī) 127.0.0.1:5000 訪問 |
2.6 訪問驗(yàn)證
Mysql訪問驗(yàn)證
Redis訪問驗(yàn)證
Prometheus訪問驗(yàn)證
Grafana訪問驗(yàn)證
Jaeger訪問驗(yàn)證
推薦閱讀
