Zipkin 安装与运行教程

前言

技术资源

三种运行方式

Zipkin 支持三种运行方式,包括:

  • 从源码运行
  • Java 命令运行
  • Docker 容器运行

Zipkin 控制台访问

当 Zipkin 的服务正常运行后,默认会监听 9411 端口,浏览器可以通过 http://127.0.0.1:9411/zipkin/ 访问 Zipkin 的 Web 管理控制台。

Java 命令运行

最快的运行方式是从 这里 获取最新发布的 Zipkin 可执行 Jar 文件,然后直接使用 java -jar 命令运行。特别注意,最新版本的 Zipkin 至少需要依赖 Java 17+。

1
2
3
4
5
# 下载最新版本的可执行 Jar 文件
curl -sSL https://zipkin.io/quickstart.sh | bash -s

# 运行 Zipkin
java -jar zipkin.jar

Zipkin 正常运行后输出的日志信息如下,默认会监听 9411 端口。

浏览器通过 http://127.0.0.1:9411/zipkin/ 就可以访问 Zipkin 的 Web 管理控制台。

Docker 运行

Docker 直接运行

1
docker run -d --name zipkin --restart=always -p 9411:9411 -e TZ=Asia/Shanghai -e STORAGE_TYPE=mem openzipkin/zipkin:3.4.1

Docker Compose 运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
version: '3.5'

services:
zipkin:
image: openzipkin/zipkin:3.4.1
container_name: zipkin
ports:
- 9411:9411
environment:
TZ: Asia/Shanghai
STORAGE_TYPE: mem
networks:
- zipkin-network

networks:
zipkin-network:
driver: bridge
  • 重要参数说明:
    • STORAGE_TYPE=mem:使用内存作为存储(默认配置),服务重启后会丢失数据。

Zipkin 数据持久化

Zipkin 支持将追踪数据存储到 Cassandra、Elasticsearch、MySQL。值得一提的是,Zipkin 默认会将追踪数据存储到内存中,服务重启后会丢失数据。

MySQL 持久化

官方文档

Zipkin 支持将数据持久化到 MySQL,详细的说明可以参考 官方文档

特别注意

  • 在 Zipkin 连接 MySQL 之前,必须手动初始化 MySQL 数据库,比如创建数据库、表结构、用户等。
  • 建议使用 MySQL 5.7.x 版本,而不是使用 MySQL 8.x 版本,否则可能会因为 Zipkin 不支持高版本的 MySQL,导致 Zipkin 无法正常运行,具体表现为 Zipkin 无法往 MysQL 查询或插入追踪数据。

数据库初始化

  • 创建数据库,用于 Zipkin 存储追踪数据
1
CREATE DATABASE zipkin DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
  • 切换数据库
1
use zipkin;
  • 创建表结构,最新的 DDL 语句可以从 这里 获得
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
CREATE TABLE IF NOT EXISTS zipkin_spans (
`trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',
`trace_id` BIGINT NOT NULL,
`id` BIGINT NOT NULL,
`name` VARCHAR (255) NOT NULL,
`remote_service_name` VARCHAR (255),
`parent_id` BIGINT,
`debug` BIT (1),
`start_ts` BIGINT COMMENT 'Span.timestamp (): epoch micros used for endTs query and to implement TTL',
`duration` BIGINT COMMENT 'Span.duration (): micros used for minDuration and maxDuration query',
PRIMARY KEY (`trace_id_high`, `trace_id`, `id`)
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;

ALTER TABLE zipkin_spans ADD INDEX (`trace_id_high`, `trace_id`) COMMENT 'for getTracesByIds';
ALTER TABLE zipkin_spans ADD INDEX (`name`) COMMENT 'for getTraces and getSpanNames';
ALTER TABLE zipkin_spans ADD INDEX (`remote_service_name`) COMMENT 'for getTraces and getRemoteServiceNames';
ALTER TABLE zipkin_spans ADD INDEX (`start_ts`) COMMENT 'for getTraces ordering and range';

CREATE TABLE IF NOT EXISTS zipkin_annotations (
`trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',
`trace_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.trace_id',
`span_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.id',
`a_key` VARCHAR (255) NOT NULL COMMENT 'BinaryAnnotation.key or Annotation.value if type == -1',
`a_value` BLOB COMMENT 'BinaryAnnotation.value (), which must be smaller than 64KB',
`a_type` INT NOT NULL COMMENT 'BinaryAnnotation.type () or -1 if Annotation',
`a_timestamp` BIGINT COMMENT 'Used to implement TTL; Annotation.timestamp or zipkin_spans.timestamp',
`endpoint_ipv4` INT COMMENT 'Null when Binary/Annotation.endpoint is null',
`endpoint_ipv6` BINARY (16) COMMENT 'Null when Binary/Annotation.endpoint is null, or no IPv6 address',
`endpoint_port` SMALLINT COMMENT 'Null when Binary/Annotation.endpoint is null',
`endpoint_service_name` VARCHAR (255) COMMENT 'Null when Binary/Annotation.endpoint is null'
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;

ALTER TABLE zipkin_annotations ADD UNIQUE KEY (`trace_id_high`, `trace_id`, `span_id`, `a_key`, `a_timestamp`) COMMENT 'Ignore insert on duplicate';
ALTER TABLE zipkin_annotations ADD INDEX (`trace_id_high`, `trace_id`, `span_id`) COMMENT 'for joining with zipkin_spans';
ALTER TABLE zipkin_annotations ADD INDEX (`trace_id_high`, `trace_id`) COMMENT 'for getTraces/ByIds';
ALTER TABLE zipkin_annotations ADD INDEX (`endpoint_service_name`) COMMENT 'for getTraces and getServiceNames';
ALTER TABLE zipkin_annotations ADD INDEX (`a_type`) COMMENT 'for getTraces and autocomplete values';
ALTER TABLE zipkin_annotations ADD INDEX (`a_key`) COMMENT 'for getTraces and autocomplete values';
ALTER TABLE zipkin_annotations ADD INDEX (`trace_id`, `span_id`, `a_key`) COMMENT 'for dependencies job';

CREATE TABLE IF NOT EXISTS zipkin_dependencies (
`day` DATE NOT NULL,
`parent` VARCHAR (255) NOT NULL,
`child` VARCHAR (255) NOT NULL,
`call_count` BIGINT,
`error_count` BIGINT,
PRIMARY KEY (`day`, `parent`, `child`)
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;
  • 创建用户并授权,用于 Zipkin 连接 MySQL 数据库
1
2
3
4
5
6
7
8
-- 创建用户
CREATE USER 'zipkin'@'%' IDENTIFIED WITH mysql_native_password BY 'zipkin';

-- 用户授权
GRANT ALL PRIVILEGES ON zipkin.* TO 'zipkin'@'%';

-- 刷新权限
FLUSH PRIVILEGES;

Java 命令运行

当使用 Java 命令运行 Zipkin 时,可以在启动的时候指定所需的环境变量,比如 MySQL 的地址、端口、用户名、密码等信息。

1
STORAGE_TYPE=mysql MYSQL_HOST=127.0.0.1 MYSQL_TCP_PORT=3306 MYSQL_DB=zipkin MYSQL_USER=zipkin MYSQL_PASS=zipkin java -jar zipkin.jar
  • 重要参数说明:
    • STORAGE_TYPE=mysql:使用 MySQL 作为存储。

MySQL 版本说明

通过 Java 命令运行最新版的 Zipkin (如 3.4.1)时,亲测可以使用 MySQL 5.7.44 或者 MySQL 8.4.2,不会出现无法连接 MySQL 的情况。

Docker 直接运行

当使用 Docker 直接运行 Zipkin 时,可以在启动容器的时候指定所需的环境变量,比如 MySQL 的地址、端口、用户名、密码等信息。

1
2
3
4
5
6
7
8
9
10
11
12
docker run \
--name zipkin -d \
--restart=always \
-p 9411:9411 \
-e TZ=Asia/Shanghai \
-e STORAGE_TYPE=mysql \
-e MYSQL_HOST=192.168.5.168 \
-e MYSQL_TCP_PORT=3306 \
-e MYSQL_DB=zipkin \
-e MYSQL_USER=zipkin \
-e MYSQL_PASS=zipkin \
openzipkin/zipkin:3.4.1
  • 重要参数说明:
    • STORAGE_TYPE=mysql:使用 MySQL 作为存储。
    • MYSQL_HOST=192.168.5.168:MySQL 的 IP 地址,这里的 MySQL 可以不是运行在 Docker 容器里的(即可以单独安装)。

特别注意

通过 Docker 直接运行最新版的 Zipkin(如 3.4.1)时,必须使用 MySQL 5.7.44 版本,笔者尝试使用 MySQL 8.4.2 版本,发现 Zipkin 不能正常运行,也就是无法连接 MySQL,具体表现为 Zipkin 无法往 MysQL 查询或插入追踪数据。

Docker Compose 运行

若需要将追踪数据存储到 MySQL,可以修改 docker-compose.yml 中的 STORAGE_TYPEmysql,并配置相应的存储服务信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
version: '3.5'

services:
mysql:
image: mysql:5.7.44
container_name: mysql-server
restart: always
ports:
- 3306:3306
environment:
TZ: Asia/Shanghai
MYSQL_ROOT_PASSWORD: 123456
healthcheck:
test: ["CMD-SHELL", "mysqladmin ping -h localhost"]
interval: 10s
timeout: 5s
retries: 5
networks:
- zipkin-network

zipkin:
image: openzipkin/zipkin:3.4.1
container_name: zipkin
restart: always
ports:
- 9411:9411
environment:
TZ: Asia/Shanghai
STORAGE_TYPE: mysql # 使用 MySQL 作为存储
MYSQL_HOST: mysql # MySQL 服务的名称
MYSQL_TCP_PORT: 3306 # MySQL 的端口
MYSQL_DB: zipkin # Zipkin 连接 MySQL 时使用的数据库
MYSQL_USER: zipkin # Zipkin 连接 MySQL 时使用的用户
MYSQL_PASS: zipkin # Zipkin 连接 MySQL 时使用的密码
depends_on:
mysql:
condition: service_healthy
networks:
- zipkin-network

networks:
zipkin-network:
driver: bridge
  • 重要参数说明:
    • STORAGE_TYPE: mysql:使用 MySQL 作为存储。
    • MYSQL_HOST: mysql:这里的 mysql 是在 Docker Compose 中定义的 MySQL 服务的名称,用作其他服务(如 Zipkin)访问 MySQL 的主机名,Docker Compose 会自动将这个名称解析为 MySQL 容器的 IP 地址。

特别注意

  • 当通过 Docker Compose 启动 Zipkin 和 MySQL 容器后,可以发现 Zipkin 并不能正常提供服务,比如在 Web 控制台上面无法查询到数据。
  • 这通常是因为在 MySQL 数据库中,并没有 Zipkin 所需要的表结构和用户,因此需要手动创建数据库、表结构和用户,详细的操作步骤请看 这里
  • 通过 Docker Compose 运行最新版的 Zipkin(如 3.4.1)时,必须使用 MySQL 5.7.44 版本,笔者尝试使用 MySQL 8.4.2 版本,发现 Zipkin 不能正常运行,也就是无法连接 MySQL,具体表现为 Zipkin 无法往 MysQL 查询或插入追踪数据。

Elasticsearch 持久化

官方文档

Zipkin 支持将数据持久化到 Elasticsearch,详细的说明可以参考 官方文档

特别注意

  • 在 Zipkin 连接 Elasticsearch 之前,不需要手动初始化 Elasticsearch,比如创建索引。
  • Zipkin 默认使用了 Elasticsearch 5+ 的功能,但针对 Elasticsearch 7 ~ 8.x 版本和 OpenSearch 2.x 也进行了测试,笔者亲测 Zipkin 可以正常使用 Elasticsearch 7.17.4

Java 命令运行

当使用 Java 命令运行 Zipkin 时,可以在启动的时候指定所需的环境变量,比如 Elasticsearch 的连接地址。

1
STORAGE_TYPE=elasticsearch ES_HOSTS=http://127.0.0.1:9200 java -jar zipkin.jar
  • 重要参数说明:
    • STORAGE_TYPE=elasticsearch:使用 Elasticsearch 作为存储。
    • ES_HOSTS=http://127.0.0.1:9200:指定 Elasticsearch 的连接地址。

Docker 直接运行

当使用 Docker 直接运行 Zipkin 时,可以在启动容器的时候指定所需的环境变量,比如 Elasticsearch 的连接地址。

1
2
3
4
5
6
7
8
docker run \
--name zipkin -d \
-p 9411:9411 \
--restart=always \
-e TZ=Asia/Shanghai \
-e STORAGE_TYPE=elasticsearch \
-e ES_HOSTS=http://192.168.5.168:9200 \
openzipkin/zipkin:3.4.1
  • 重要参数说明:
    • STORAGE_TYPE=elasticsearch:使用 Elasticsearch 作为存储。
    • ES_HOSTS=http://192.168.5.168:9200:指定 Elasticsearch 的连接地址,这里的 Elasticsearch 可以不是运行在 Docker 容器里的(即可以单独安装)。

Docker Compose 运行

若需要将追踪数据存储到 Elasticsearch,可以修改 docker-compose.yml 中的 STORAGE_TYPEelasticsearch,并配置相应的存储服务信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
version: '3.5'

services:
elasticsearch:
image: elasticsearch:7.17.4
container_name: elasticsearch-server
ports:
- 9200:9200
environment:
TZ: Asia/Shanghai
cluster.name: es-cluster
discovery.type: single-node # 设置 ElasticSearch 为单节点模式
ES_JAVA_OPTS: '-Xms1024m -Xmx2048m' # 设置 ElasticSearch 的 JVM 堆内存大小
healthcheck:
test: ["CMD-SHELL", "curl -s http://localhost:9200/_cluster/health | grep -q '\"status\":\"green\"'"]
interval: 10s
timeout: 5s
retries: 10
start_period: 60s
networks:
- zipkin-network

zipkin:
image: openzipkin/zipkin:3.4.1
container_name: zipkin
ports:
- 9411:9411
environment:
TZ: Asia/Shanghai
STORAGE_TYPE: elasticsearch # 使用 ElasticSearch 作为存储
ES_HOSTS: http://elasticsearch:9200 # 指定 ElasticSearch 服务的访问地址
depends_on:
elasticsearch:
condition: service_healthy
networks:
- zipkin-network

networks:
zipkin-network:
driver: bridge
  • 重要参数说明:
    • STORAGE_TYPE=elasticsearch:使用 Elasticsearch 作为存储。
    • ES_HOSTS: http://elasticsearch:9200:这里的 elasticsearch 是在 Docker Compose 中定义的 ElasticSearch 服务的名称,用作其他服务(如 Zipkin)访问 ElasticSearch 的主机名,Docker Compose 会自动将这个名称解析为 ElasticSearch 容器的 IP 地址。若连接的是 ElasticSearch 集群,可以使用逗号分割多个 URL 地址。

Zipkin 数据采集

Zipkin 支持多种数据采集方式,包括从 Kafka、RabbitMQ、ActiveMQ 采集追踪数据,详细的 Docker 使用说明请参考 官方的 Docker 使用示例

常见的使用错误

MySQL 持久化失败

  • 错误描述:当 Zipkin 使用 MySQL 作为存储时,Zipkin 容器无法正常启动,通过 docker logs zipkin 命令得到容器启动时的错误日志信息如下:
1
Version mismatch : Database version is older than what dialect MYSQL supports: 5.7.44. 
  • 错误分析:从表面看像是当前使用的 Zipkin 版本并不支持低版本的 MySQL(比如 5.7.44)。但是,笔者尝试将 MySQL 镜像的版本升级到 8.4.2,发现 Zipkin 不能正常运行,也就是无法连接 MySQL,具体表现为 Zipkin 无法往 MysQL 查询或插入追踪数据。

  • 解决方法:重启 Zipkin 容器即可,使用的命令如下:

1
2
3
4
5
# 重启容器
docker restart zipkin

# 等待数十秒后,查看容器的运行状态
docker ps -a

参考资料