本指南使用 MySQL 8.4 LTS,分别启动 PMS 和 ADS:PMS 写入策略,ADS 使用独立的只读账号读取同一个数据库。本地演示使用 Docker,HTTP 服务只监听本机回环地址。远程部署可使用已有的 MySQL,并参考安全配置。
1. 编译包含 MySQL 后端的 Speedle
准备 Git、Bash、curl、已启动的 Docker,以及支持的 Go 工具链(Go 1.26.10 或 Go 1.27.3)。从当前源码编译,确保两个服务都包含 mysql 后端;已安装的旧版本可能没有该后端。
git clone --depth 1 https://github.com/teramoby/speedle-plus.git
cd speedle-plus
mkdir -p bin
go build -o ./bin/ ./cmd/spctl ./cmd/speedle-pms ./cmd/speedle-ads后续命令都在这个 speedle-plus 目录执行。确认 3306、6733、6734 端口未被占用;若修改端口,需同步修改下文的命令和配置。
2. 启动 MySQL 8.4
下列固定密码仅为本地演示凭据。部署时请使用自己的凭据与密钥交付方式。命名卷会在容器停止或重建后保留数据库。
docker run --name speedle-mysql --detach \
--publish 127.0.0.1:3306:3306 \
--volume speedle-mysql-data:/var/lib/mysql \
--env MYSQL_ROOT_PASSWORD=SpeedleDemoRoot84 \
mysql:8.4等待 MySQL 初始化完成:
until docker exec speedle-mysql mysqladmin ping \
--host=127.0.0.1 --user=root --password=SpeedleDemoRoot84 --silent
do
sleep 1
done已有 MySQL 8.4 时,跳过 Docker 启动命令,使用管理员客户端执行下一步 SQL。Docker 镜像只在数据目录为空时初始化账号;对已有数据卷修改环境变量不会重置密码。
3. 创建数据库和服务账号
Speedle 默认自动建表,但不会创建数据库。先以管理员身份创建 speedle 数据库及两个独立账号:
docker exec -i speedle-mysql mysql --user=root --password=SpeedleDemoRoot84 <<'SQL'
CREATE DATABASE speedle CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin;
CREATE USER 'speedle_pms'@'%' IDENTIFIED BY 'SpeedleDemoPms84';
CREATE USER 'speedle_ads'@'%' IDENTIFIED BY 'SpeedleDemoAds84';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, REFERENCES ON speedle.* TO 'speedle_pms'@'%';
GRANT SELECT ON speedle.* TO 'speedle_ads'@'%';
SQLPMS 自动建表需要 CREATE、REFERENCES,管理策略还需要 SELECT、INSERT、UPDATE、DELETE。ADS 只需 SELECT,并必须关闭自动建表。示例中的账号主机 % 允许宿主机通过 Docker 连接;远程部署应限制为实际 PMS/ADS 主机。
4. 写入 PMS 与 ADS 配置文件
两个 DSN 必须指向同一个 MySQL 服务和数据库。DSN 格式为 用户:密码@tcp(主机:端口)/数据库。
mkdir -p mysql-demo
cat > mysql-demo/pms.json <<'JSON'
{
"storeConfig": {
"storeType": "mysql",
"storeProps": {
"MySQLDSN": "speedle_pms:SpeedleDemoPms84@tcp(127.0.0.1:3306)/speedle",
"MySQLInitSchema": true,
"MySQLPollInterval": "1s",
"MySQLQueryTimeout": "10s"
}
}
}
JSON
cat > mysql-demo/ads.json <<'JSON'
{
"storeConfig": {
"storeType": "mysql",
"storeProps": {
"MySQLDSN": "speedle_ads:SpeedleDemoAds84@tcp(127.0.0.1:3306)/speedle",
"MySQLInitSchema": false,
"MySQLPollInterval": "1s",
"MySQLQueryTimeout": "10s"
}
},
"enableWatch": true
}
JSON
chmod 600 mysql-demo/pms.json mysql-demo/ads.jsonMySQLInitSchema: false 表示只检查已有表结构,不执行 DDL。enableWatch: true 让 ADS 自动同步已提交的变更。配置文件包含密码,请勿提交到代码仓库。
5. 先启动 PMS,再启动 ADS
在终端 A 中启动 PMS,由它完成建表:
./bin/speedle-pms --config-file mysql-demo/pms.json --endpoint 127.0.0.1:6733 --insecure=true保持 PMS 运行。在终端 B 中进入同一个代码目录,确认表已创建:
docker exec speedle-mysql mysql --user=speedle_ads --password=SpeedleDemoAds84 speedle -e 'SHOW TABLES;'应看到下面五张表:
| 表名 | 保存内容 |
|---|---|
speedle_services |
服务及服务元数据 |
speedle_policies |
授权策略 |
speedle_role_policies |
角色策略 |
speedle_functions |
自定义函数定义 |
speedle_store_meta |
结构版本与已提交的策略修订号 |
然后在终端 B 中启动 ADS,并保持运行:
./bin/speedle-ads --config-file mysql-demo/ads.json --endpoint 127.0.0.1:6734 --insecure=true等两个服务的 REST 监听启动后再继续。未传入 --grpc-endpoint 时,gRPC 服务默认关闭。
6. 创建策略并检查授权
在终端 C 创建服务,授予 Alice 读取 book 的权限:
curl -fsS -X POST http://127.0.0.1:6733/policy-mgmt/v1/service \
-H 'Content-Type: application/json' \
-d '{"name":"mysql-demo","type":"application","policies":[{"name":"alice-read","effect":"grant","principals":[["user:alice"]],"permissions":[{"resource":"book","actions":["read"]}]}]}'等待 ADS 同步。默认轮询间隔为 1 秒,还需加上查询和缓存重建时间;如果请求发生在同步完成之前,稍后重试:
curl -fsS -X POST http://127.0.0.1:6734/authz-check/v1/is-allowed \
-H 'Content-Type: application/json' \
-d '{"subject":{"principals":[{"type":"user","name":"alice"}]},"serviceName":"mysql-demo","resource":"book","action":"read"}'预期返回 {"allowed":true,"reason":0}。Bob 没有匹配的授权策略:
curl -fsS -X POST http://127.0.0.1:6734/authz-check/v1/is-allowed \
-H 'Content-Type: application/json' \
-d '{"subject":{"principals":[{"type":"user","name":"bob"}]},"serviceName":"mysql-demo","resource":"book","action":"read"}'预期返回 {"allowed":false,"reason":3}。
7. 验证自动更新和持久化
通过 PMS 新增一条拒绝 Alice 的策略,无需重启 ADS:
curl -fsS -X POST http://127.0.0.1:6733/policy-mgmt/v1/service/mysql-demo/policy \
-H 'Content-Type: application/json' \
-d '{"name":"alice-deny","effect":"deny","principals":[["user:alice"]],"permissions":[{"resource":"book","actions":["read"]}]}'同步后,再执行第 6 步 Alice 的请求,应返回 {"allowed":false,"reason":1},表示显式 deny 优先。也可以按 Ctrl+C 停止 PMS 和 ADS,再用第 5 步命令启动。再次请求仍应拒绝 Alice,说明策略已保存在 MySQL 中。
策略变更应通过 PMS 或存储接口完成,确保数据与修订号在同一事务内提交。直接修改 SQL 不会自动触发 ADS 重载。数据库断线时,ADS 保持运行并重试同步,但检测到故障后默认返回 allowed:false 和错误。成功加载完整快照后才恢复授权,详见统一的存储故障与宽限期策略。ADS 启动时仍需要数据库可连接。
可选:预先建表,运行时不授予 DDL 权限
如果不允许服务账号自动建表,可在启动服务前,用初始化账号执行仓库中的同一份 schema.sql:
docker exec -i speedle-mysql mysql --user=root --password=SpeedleDemoRoot84 speedle < pkg/store/mysql/schema.sql将两个配置文件中的 MySQLInitSchema 都设置为 false。如果沿用了本指南前面的演示账号,可撤销 PMS 的初始化权限:
docker exec speedle-mysql mysql --user=root --password=SpeedleDemoRoot84 -e "REVOKE CREATE, REFERENCES ON speedle.* FROM 'speedle_pms'@'%';"此后 PMS 仅需 SELECT、INSERT、UPDATE、DELETE,ADS 保持只读。修改配置后重启两个服务。初始化 SQL 不会迁移已有表;不支持的结构版本会导致启动失败。
配置速查与故障排查
| 配置属性 | 命令行参数 | 环境变量 | 默认值 |
|---|---|---|---|
MySQLDSN |
--mysqlstore-dsn |
SPDL_MYSQLSTORE_DSN |
必填,必须包含数据库名 |
MySQLInitSchema |
--mysqlstore-init-schema |
SPDL_MYSQLSTORE_INIT_SCHEMA |
true |
MySQLPollInterval |
--mysqlstore-poll-interval |
SPDL_MYSQLSTORE_POLL_INTERVAL |
1s |
MySQLQueryTimeout |
--mysqlstore-query-timeout |
SPDL_MYSQLSTORE_QUERY_TIMEOUT |
10s |
选择后端的参数是 --store-type mysql,对应 SPDL_STORE_TYPE=mysql。配置优先级为:显式参数 → 非空环境变量 → 配置文件 → 默认值。连接远程数据库时,使用带可信服务端证书的主机名,并在 DSN 后添加 ?tls=true;自定义 CA 的配置请参阅驱动 TLS 文档。
| 现象 | 检查项 |
|---|---|
不识别 mysql 后端或参数 |
从包含 pkg/store/mysql 的源码重新编译两个服务。 |
| 连接被拒绝或访问被拒绝 | MySQL 是否就绪,DSN 地址、端口、密码及账号主机限制是否正确。 |
| 数据库不存在 | 先创建数据库,Speedle 只负责建表。 |
| 表不存在或 DDL 权限不足 | 先启动 PMS 或手动建表;只读 ADS 必须设置 MySQLInitSchema: false。 |
| 修改策略后未生效 | 两个 DSN 是否同库、ADS 是否启用 watch、是否已等待同步,以及 SPDL_* 环境变量是否覆盖了文件配置。 |
MySQL 不支持 Discover 访问请求收集和策略生成。事务、快照和恢复机制详见存储扩展。