Zero to Inf

技术栈的流动-从零到无穷

微服务全套docker-compose.yaml

这份 docker-compose.yml 定义了一套完整的 go-zero 微服务开发环境,覆盖了服务发现、消息队列、数据存储、监控追踪、日志中心等核心基础设施。它让开发者无需在本地繁琐安装配置,即可快速启动一套微服务所需的所有中间件,专注于业务代码开发

该项目存在的意义,旨在于本地docker快速搭建微服务环境

github地址:https://github.com/EvansYe2/microservice-docker-compose-deploy

一、服务发现(etcd)

容器:etcd

  • 作用:etcd 是分布式键值存储,在 go-zero 中充当 服务注册与发现中心。每个微服务启动时将自己注册到 etcd,其他服务通过 etcd 获取对方地址,实现自动路由。
  • 配置:单节点模式,对外暴露 2379 端口供客户端(go-zero 服务)访问。
  • 协作:go-zero 服务通过 etcd 客户端连接 etcd:2379 完成注册与发现。

二、消息队列

1. Kafka 生态(Kafka + Zookeeper + Kafka-UI)

  • Zookeeper:Kafka 依赖 ZooKeeper 管理集群元数据、Broker 选举等。
  • Kafka:高吞吐量分布式消息队列,用于 异步解耦、削峰填谷、事件驱动。go-zero 中的异步任务(如发邮件、订单状态变更)可通过 Kafka 生产消费。
  • Kafka-UI:Web 管理界面,可查看 Topic、消息、消费者组状态,便于开发调试。
  • 协作:go-zero 服务作为生产者将消息投递到 Kafka,消费者从 Kafka 拉取处理;Kafka-UI 连接 Kafka 和 Zookeeper 提供可视化。

2. Beanstalkd 生态(Beanstalkd + Beanstalkd-Console)

  • Beanstalkd:轻量级 延迟队列,专门处理延时任务(如订单超时未支付自动取消)。
  • Beanstalkd-Console:Web 管理界面,查看队列、任务统计。
  • 协作:go-zero 服务可将延时任务投递到 Beanstalkd,消费者在指定时间后取出执行。

三、数据库与缓存

  • MySQL:关系型数据库,存储业务数据(用户、订单等)。
  • Redis:高性能内存数据库,用作 缓存、分布式锁、会话存储、计数器 等。
  • 协作:go-zero 服务通过 GORM 或原生 SQL 操作 MySQL,通过 go-redis 操作 Redis。

四、监控与可观测性

1. Prometheus + Grafana

  • Prometheus:时序数据库,从 go-zero 服务抓取指标(请求量、延迟、错误率),存储为时间序列数据。
    • 配置文件 prometheus.yml 和 targets.json 定义了抓取规则和目标(需列出具体服务端点)。
  • Grafana:可视化面板,连接 Prometheus 展示图表、仪表盘,便于分析系统状态。
  • 协作:go-zero 服务暴露 /metrics 端点,Prometheus 定期拉取;Grafana 读取 Prometheus 数据并展示。

2. Jaeger(链路追踪)

  • Jaeger:分布式链路追踪系统,跟踪一个请求在多个微服务间的完整调用链,帮助定位性能瓶颈和故障点。
  • 存储:将链路数据写入 Elasticsearch(通过 SPAN_STORAGE_TYPE=elasticsearch 配置)。
  • 协作:go-zero 服务通过 OpenTelemetry 或 Jaeger 客户端将 trace 数据发送到 Jaeger 收集器(端口 14250/14268),Jaeger UI(端口 16686)提供查询界面。

五、日志中心(ELK + Filebeat + go-stash)

日志流完整路径:

Docker 容器日志 → Filebeat → Kafka → go-stash → Elasticsearch → Kibana

1. Filebeat(日志采集)

  • 读取宿主机 Docker 容器日志(/var/lib/docker/containers/*/*.log),将日志发送到 Kafka 的 go-zero-logs Topic。
  • 配置文件 filebeat.yml 定义了输出目标(Kafka 地址、Topic 等)。

2. Kafka(日志缓冲)

  • 作为日志中转站,削峰填谷,确保日志不会因突发流量丢失。

3. go-stash(日志处理与写入)

  • 从 Kafka 消费日志,按照配置规则处理后写入 Elasticsearch。
  • 配置 config.yaml 中指定了 Kafka 和 Elasticsearch 地址、索引格式(如 go-zero-logs-2006.01.02)。

4. Elasticsearch(日志存储)

  • 分布式搜索引擎,存储日志数据,支持快速检索。

5. Kibana(日志可视化)

  • Elasticsearch 的 Web 界面,用于查询、分析、可视化日志。

协作总结

  • 所有微服务的日志(通过 stdout/stderr)被 Docker 捕获,Filebeat 采集后发往 Kafka;go-stash 消费并写入 ES;开发者通过 Kibana 统一查看、搜索日志。

六、整体协作关系图(数据流)

阶段组件说明
服务启动go-zero 服务 → etcd注册自己
业务调用go-zero 服务 → MySQL / Redis数据读写
异步任务go-zero 服务 → Kafka / Beanstalkd发送消息或延时任务
监控Prometheus → go-zero 服务拉取 /metrics
链路追踪go-zero 服务 → Jaeger发送 trace
日志Filebeat → Kafka → go-stash → Elasticsearch → Kibana采集、传输、存储、展示
version: '3.8'

networks:
  go-zero-network:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/16

volumes:
  etcd-data:
  mysql-data:
  redis-data:
  kafka-data:
  prometheus-data:
  grafana-data:
  jaeger-data:
  elasticsearch-data:
  go-stash:

services:
  # ==================== Service Discovery ====================
  etcd:
    image: quay.io/coreos/etcd:v3.5.10
    container_name: etcd
    restart: unless-stopped
    environment:
      - ETCD_NAME=etcd0
      - ETCD_DATA_DIR=/etcd-data
      - ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379
      - ETCD_ADVERTISE_CLIENT_URLS=http://etcd:2379
      - ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380
      - ETCD_INITIAL_ADVERTISE_PEER_URLS=http://etcd:2380
      - ETCD_INITIAL_CLUSTER=etcd0=http://etcd:2380
      - ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster
      - ETCD_INITIAL_CLUSTER_STATE=new
    ports:
      - "2379:2379"
      - "2380:2380"
    volumes:
      - ./etcd-data:/etcd-data
    networks:
      - go-zero-network

  # ==================== Message Queue ====================
  #Kafka 依赖 ZooKeeper 来管理集群元数据、选举控制器等。它本身不参与业务消息,但却是 Kafka 正常工作的基础。
  zookeeper:
    image: zookeeper:3.9.5
    container_name: zookeeper
    restart: unless-stopped
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
      ZOOKEEPER_TICK_TIME: 2000
      ZOO_MY_ID: 1
    ports:
      - "2181:2181"
    volumes:
      - ./zk-data:/var/lib/zookeeper/data
      - ./zk-datalog:/var/lib/zookeeper/log
    networks:
      - go-zero-network

  #Kafka 是一个高吞吐量分布式消息队列,用于 异步解耦、削峰填谷、事件驱动。go-zero 中的异步任务(如发送通知、订单处理)可以通过 Kafka 生产消费。
  kafka:
    image: apache/kafka:4.0.2
    container_name: kafka
    restart: unless-stopped
    depends_on:
      - zookeeper
    environment:
      KAFKA_NODE_ID: 1
      KAFKA_PROCESS_ROLES: broker,controller
      # 外部访问监听端口为 9092,容器内部使用不同的端口 9094
      KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9094,CONTROLLER://localhost:9093,PLAINTEXT_CONTAINER://kafka:9092
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9094,PLAINTEXT_CONTAINER://kafka:9092
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,PLAINTEXT_CONTAINER:PLAINTEXT
      KAFKA_CONTROLLER_QUORUM_VOTERS: 1@localhost:9093
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
      KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
      KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
      KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
      KAFKA_NUM_PARTITIONS: 3
    ports:
      - "9092:9092"  # 容器内部之间使用的监听端口
      - "9094:9094"  # 容器外部访问监听端口
    volumes:
      - ./kafka-data:/var/lib/kafka/data
    networks:
      - go-zero-network

  #Kafka 的可视化 Web 管理界面,用于查看主题、消息、消费者组状态,方便开发和调试。
  kafka-ui:
    image: provectuslabs/kafka-ui:latest
    container_name: kafka-ui
    restart: unless-stopped
    depends_on:
      - kafka
    environment:
      KAFKA_CLUSTERS_0_NAME: local
      KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka:9092
      KAFKA_CLUSTERS_0_ZOOKEEPER: zookeeper:2181
    ports:
      - "8080:8080"
    networks:
      - go-zero-network

  #Beanstalkd 是一个轻量级的 延迟队列,专门用于处理延时任务(如订单超时未支付自动取消)。
  beanstalkd:
    image: schickling/beanstalkd:latest
    container_name: beanstalkd
    restart: unless-stopped
    command: -l 0.0.0.0
    ports:
      - "11300:11300"
    networks:
      - go-zero-network

  #Beanstalkd 的 Web 管理界面,查看队列状态、任务统计等。
  beanstalkd-console:
    image: agaveapi/beanstalkd-console:latest
    container_name: beanstalkd-console
    restart: unless-stopped
    depends_on:
      - beanstalkd
    environment:
      BEANSTALKD_HOST: beanstalkd
      BEANSTALKD_PORT: 11300
    ports:
      - "8081:8080"
    networks:
      - go-zero-network

  # ==================== Database & Cache ====================
  mysql:
    image: mysql:8.0
    container_name: mysql
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: 123456
      MYSQL_DATABASE: go_zero
      MYSQL_USER: go_zero
      MYSQL_PASSWORD: go_zero123
    ports:
      - "3306:3306"
    volumes:
      - ./mysql-data:/var/lib/mysql
    networks:
      - go-zero-network

  redis:
    image: redis:7.2-alpine
    container_name: redis
    restart: unless-stopped
    command: redis-server --requirepass 123456
    ports:
      - "6379:6379"
    volumes:
      - ./redis-data:/data
    networks:
      - go-zero-network

  

  # ==================== Monitoring & Observability 监控业务====================
  #时序数据库,从 go-zero 服务抓取指标(请求量、延迟、错误率等),并存储为时间序列数据。
  #挂载了 prometheus.yml(抓取规则)和 targets.json(服务发现目标)。
  #targets.json 中应列出需要监控的服务端点(如 user-api:9081)。
  prometheus:
    image: prom/prometheus:v2.48.0
    container_name: prometheus
    restart: unless-stopped
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - ./prometheus/targets.json:/etc/prometheus/targets.json:ro
      - ./prometheus-data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--web.enable-lifecycle'
    ports:
      - "9090:9090"
    networks:
      - go-zero-network

  #prometheus 的 ui 很难看,用来显示 prometheus 收集来的数据,查看prometheus监控数据
  #可视化面板,从 Prometheus 读取数据并展示为图表、仪表盘。
  grafana:
    image: grafana/grafana:10.2.0
    container_name: grafana
    restart: unless-stopped
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
      - GF_INSTALL_PLUGINS=grafana-piechart-panel
    volumes:
      - ./grafana-data:/var/lib/grafana
      - ./grafana/datasources:/etc/grafana/provisioning/datasources:ro
      - ./grafana/dashboards:/etc/grafana/provisioning/dashboards:ro
    ports:
      - "3000:3000"
    networks:
      - go-zero-network

  #jaeger链路追踪 — Jaeger for tracing
  #分布式链路追踪系统,用于跟踪一个请求在多个微服务之间的完整调用链,定位性能瓶颈。
  #将链路数据存储在 Elasticsearch 中(SPAN_STORAGE_TYPE=elasticsearch)。
  jaeger:
    image: jaegertracing/all-in-one:1.53
    container_name: jaeger
    restart: unless-stopped
    environment:
      - COLLECTOR_OTLP_ENABLED=true
      - SPAN_STORAGE_TYPE=elasticsearch
      - ES_SERVER_URLS=http://elasticsearch:9200
    ports:
      - "5775:5775/udp"
      - "6831:6831/udp"
      - "6832:6832/udp"
      - "5778:5778"
      - "16686:16686"
      - "14268:14268"
      - "14250:14250"
      - "9411:9411"
    networks:
      - go-zero-network

  # ==================== Logging Stack ====================
  #存储收集的日志,分布式搜索引擎,用于存储和索引日志数据,支持快速检索。
  #Docker 容器日志 → Filebeat → Kafka → (go-stash/Logstash) → Elasticsearch → Kibana
  elasticsearch:
    image: elasticsearch:7.17.15
    container_name: elasticsearch
    restart: unless-stopped
    environment:
      - discovery.type=single-node
      - ES_JAVA_OPTS=-Xms512m -Xmx512m
      - xpack.security.enabled=false
    ports:
      - "9200:9200"
      - "9300:9300"
    volumes:
      - ./elasticsearch-data:/usr/share/elasticsearch/data
    networks:
      - go-zero-network

  #显示 elasticsearch日志,Elasticsearch 的可视化界面,用于查询、分析日志。
  kibana:
    image: kibana:7.17.15
    container_name: kibana
    restart: unless-stopped
    environment:
      ELASTICSEARCH_HOSTS: http://elasticsearch:9200
    ports:
      - "5601:5601"
    networks:
      - go-zero-network

  #消费kafka中filebeat收集的数据输出到es - The data output collected by FileBeat in Kafka is output to ES
  go-stash:
    image: kevinwan/go-stash:1.1.1
    container_name: go-stash
    environment:
      # 时区上海 - Time zone Shanghai (Change if needed)
      TZ: Asia/Shanghai
    restart: always
    volumes:
      - ./go-stash/etc:/app/etc
    networks:
      - go-zero-network
    depends_on:
      - elasticsearch
      - kafka


  #收集业务数据,收集日志到 kafka
  #轻量级日志采集器,读取 Docker 容器的日志(/var/lib/docker/containers/*/*.log),并将日志发送到 Kafka。
  #挂载了 filebeat.yml 定义输出目标(Kafka topic go-zero-logs)。
  #Docker 容器日志 → Filebeat → Kafka → (go-stash/Logstash) → Elasticsearch → Kibana
  filebeat:
    image: docker.elastic.co/beats/filebeat:7.17.15
    container_name: filebeat
    restart: unless-stopped
    user: root
    volumes:
      - ./filebeat/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro
      - /var/lib/docker/containers:/var/lib/docker/containers:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
    networks:
      - go-zero-network

Prometheus 配置文件 (prometheus/prometheus.yml)

global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'file_ds'
    file_sd_configs:
      - files:
          - /etc/prometheus/targets.json
        refresh_interval: 30s

Prometheus 服务发现目标 (prometheus/targets.json)

[
  {
    "targets": ["user-api:9081"],
    "labels": {
      "job": "user-api",
      "app": "user-api",
      "env": "test"
    }
  },
  {
    "targets": ["user-rpc:9091"],
    "labels": {
      "job": "user-rpc",
      "app": "user-rpc",
      "env": "test"
    }
  },
  {
    "targets": ["order-api:9082"],
    "labels": {
      "job": "order-api",
      "app": "order-api",
      "env": "test"
    }
  },
  {
    "targets": ["order-rpc:9092"],
    "labels": {
      "job": "order-rpc",
      "app": "order-rpc",
      "env": "test"
    }
  }
]

Grafana 数据源配置 (grafana/datasources/prometheus.yaml)

apiVersion: 1
datasources:
  - name: Prometheus
    type: prometheus
    access: proxy
    url: http://prometheus:9090
    isDefault: true

Filebeat 配置文件 (filebeat/filebeat.yml)

filebeat.inputs:
  - type: container
    paths:
      - /var/lib/docker/containers/*/*.log

output.kafka:
  hosts: ["kafka:9092"]
  topic: "go-zero-logs"
  partition.round_robin:
    reachable_only: true

logging.level: info

go-stash/etc/config.yaml

Clusters:
  - Input:
      Kafka:
        Name: gostash
        Brokers:
          - kafka:9092
        Topics:
          - go-zero-logs
        Group: go-stash-group
        Consumer:
          Offset: first
    Output:
      ElasticSearch:
        Hosts:
          - http://elasticsearch:9200
        Index: go-zero-logs-{{yyyy-MM-dd}}
        # 可选:索引滚动策略等

Go-zero 服务配置示例 (config.yaml)

# 服务发现
Etcd:
  Hosts:
    - etcd:2379
  Key: user.rpc

# 链路追踪
Telemetry:
  Name: user-api
  Endpoint: http://jaeger:14268/api/traces
  Sampler: 1.0
  Batcher: jaeger

# Prometheus 监控
Prometheus:
  Host: 0.0.0.0
  Port: 9081
  Path: /metrics

# MySQL
DB:
  DataSource: root:123456@tcp(mysql:3306)/go_zero?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai

# Redis
Redis:
  Host: redis:6379
  Pass: 123456
  Type: node

# Kafka 配置
Kafka:
  Brokers:
    - kafka:9092
  GroupID: go-zero-group
  Topic: order-topic

# Beanstalkd 配置
Beanstalkd:
  Endpoint: beanstalkd:11300
  Tube: delay-tube
# 创建配置文件目录
mkdir -p prometheus grafana/datasources filebeat

# 将上述配置文件写入对应目录
# 启动所有容器
docker-compose up -d

验证服务状态
docker-compose ps

访问各服务 UI

服务地址说明
etcdhttp://localhost:2379服务注册发现(etcd API)
Kafka UIhttp://localhost:8080Kafka 管理界面
Beanstalkd Consolehttp://localhost:8081延迟队列管理界面
Redis Commanderhttp://localhost:8082Redis 管理界面
Prometheushttp://localhost:9090监控指标收集
Grafanahttp://localhost:3000监控可视化(admin/admin)从 Prometheus 读取数据并展示为图表、仪表盘。
Jaeger UIhttp://localhost:16686链路追踪查询
Kibanahttp://localhost:5601日志分析,查看es日志
MySQLlocalhost:3306数据库
Redislocalhost:6379缓存
etcd-keeperhttp://localhost:8080

访问 kibana http://127.0.0.1:5601/ , 创建日志索引

点击左上角菜单(三个横线那个东东),找到 Analytics – > 点击 discover

然后在当前页面,Create index pattern->输入 go-zero-logs-* -> Next Step ->选择 @timestamp->Create index pattern

然后点击左上角菜单,找到 Analytics->点击 discover ,日志都显示了 (如果不显示,就去排查 filebeat、go-stash,使用 docker logs -f filebeat 查看)

发表回复

Your email address will not be published. Required fields are marked *.

*
*