Skip to content

Latest commit

 

History

History
429 lines (328 loc) · 11 KB

File metadata and controls

429 lines (328 loc) · 11 KB

AnyFast Cloud 本地开发启动指南

前置条件

工具 版本要求 安装方式
Go 1.22+ golang.org/dl
Docker Desktop 最新版 docker.com
Node.js 18+ nodejs.org (推荐用 nvm)
Make - macOS 自带,Linux: apt install make

验证安装:

go version      # go1.22.x
docker --version # Docker version 2x.x
node --version   # v18.x 或 v20.x
make --version   # GNU Make

第一步: 克隆项目并安装依赖

git clone https://github.com/anyfast/anyfast-cloud.git
cd anyfast-cloud

# 下载 Go 依赖
go mod tidy

第二步: 启动 MySQL + Redis

# 使用 docker compose 启动本地开发依赖
docker compose -f docker-compose.dev.yaml up -d

# 确认容器运行正常
docker ps

正常输出应看到两个容器:

容器名 端口 说明
anyfast-mysql 3306 MySQL 8.0,自动执行 init-db.sql
anyfast-redis 6379 Redis 7 Alpine

第三步: 验证数据库初始化

# 连接 MySQL 验证
docker exec -it anyfast-mysql mysql -uroot -proot anyfast -e "
  SELECT slug, name, type FROM tenants;
  SELECT username, email FROM users;
  SELECT role FROM user_roles;
  SELECT count(*) AS menu_count FROM menus;
  SELECT count(*) AS perm_count FROM permissions;
"

期望输出:

  • 1 个租户: platform / AnyFast Platform / platform
  • 1 个用户: admin / admin@anyfast.com
  • 1 个角色: owner
  • 17 条菜单记录
  • 多条权限记录

第四步: 修复 admin 密码 (如需要)

初始化脚本中的 bcrypt hash 对应密码 admin123。如果登录失败,可能是 hash 格式问题,手动生成:

# 使用 Go 生成正确的 bcrypt hash
go run -e 'package main
import (
    "fmt"
    "golang.org/x/crypto/bcrypt"
)
func main() {
    hash, _ := bcrypt.GenerateFromPassword([]byte("admin123"), bcrypt.DefaultCost)
    fmt.Println(string(hash))
}'

或者更简单地直接更新:

# 先生成 hash
HASH=$(docker exec anyfast-mysql mysql -uroot -proot -N -e "
  SELECT '\$2a\$10\$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy';
")

# 如果需要更新密码
docker exec anyfast-mysql mysql -uroot -proot anyfast -e "
  UPDATE users SET password = '\$2a\$10\$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy' WHERE username = 'admin';
"

默认管理员账号: admin / admin123

第五步: 启动 auth 服务

# 终端 1: 启动 auth 服务 (端口 8080)
make dev-auth

等价于:

ANYFAST_SERVER_HTTP_PORT=8080 ANYFAST_SERVER_GRPC_PORT=50051 go run ./cmd/auth/

看到以下日志说明启动成功:

auth HTTP server listening on :8080 (version=dev)

快速验证:

# 健康检查
curl http://localhost:8080/health
# 期望: {"service":"auth","status":"ok"}

# 获取登录页品牌信息
curl http://localhost:8080/oauth/login?tenant=platform
# 期望: {"tenant_name":"AnyFast Platform","logo_url":"","theme_color":"#6c8cff"}

# 登录
curl -X POST http://localhost:8080/oauth/login \
  -H "Content-Type: application/json" \
  -d '{"tenant": "platform", "account": "admin", "password": "admin123"}'
# 期望: {"access_token":"eyJ...","expires_in":86400,"user":{...}}

保存 access_token! 后续步骤会用到。

第六步: 启动 core 服务

# 终端 2: 启动 core 服务 (端口 8081)
make dev-core

等价于:

ANYFAST_SERVER_HTTP_PORT=8081 ANYFAST_SERVER_GRPC_PORT=50052 go run ./cmd/core/

看到以下日志说明启动成功:

core HTTP server listening on :8081 (version=dev)

快速验证:

# 设置 token 变量 (替换为上一步获取的值)
TOKEN="eyJhbGciOiJIUzI1NiIs..."

# 健康检查
curl http://localhost:8081/health
# 期望: {"service":"core","status":"ok"}

# 获取菜单 (需要 JWT)
curl http://localhost:8081/api/menus \
  -H "Authorization: Bearer $TOKEN"
# 期望: {"menus":[...],"permissions":[...]}

# 创建 API Key
curl -X POST http://localhost:8081/api/tokens \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "测试 Key"}'
# 期望: {"id":1,"name":"测试 Key","full_key":"sk-...","key_prefix":"sk-...","quota":-1,"rate_limit":60,"status":"active"}

# 查询 API Key 列表
curl http://localhost:8081/api/tokens \
  -H "Authorization: Bearer $TOKEN"
# 期望: {"items":[...],"pagination":{...}}

第七步: 启动其他服务 (可选)

billing-svc、config-syncer、adapter-svc 在本地开发中通常不需要启动:

服务 是否必须 说明
auth-svc 登录/鉴权依赖
core-svc 前端所有 API 调用
billing-svc 需要 Kafka,本地可跳过
config-syncer 需要 Kafka + Higress,本地可跳过
adapter-svc 仅非标模型开发时需要

如果需要启动:

# 终端 3 (需先启动本地 Kafka)
make dev-billing

# 终端 4 (需先启动本地 Kafka)
make dev-syncer

# 终端 5
make dev-adapter    # 端口 8082

第八步: 启动前端

# 终端 3 (或新终端): 启动前端
cd web
npm install
npm run dev

前端默认在 http://localhost:3000 启动。

环境变量 (已在代码中设置默认值,通常不需要额外配置):

变量 默认值 说明
NEXT_PUBLIC_API_URL http://localhost:8081 Core API 地址
NEXT_PUBLIC_AUTH_URL http://localhost:8080 Auth API 地址

如需自定义,创建 web/.env.local:

NEXT_PUBLIC_API_URL=http://localhost:8081
NEXT_PUBLIC_AUTH_URL=http://localhost:8080

访问前端: 打开 http://localhost:3000,使用 admin / admin123 登录。

端口映射总览

端口 服务 协议 说明
3000 前端 (Next.js) HTTP 开发服务器,热重载
3306 MySQL TCP Docker 容器映射
6379 Redis TCP Docker 容器映射
8080 auth-svc HTTP 认证服务
8081 core-svc HTTP 核心业务服务
8082 adapter-svc HTTP 非标适配器 (可选)
50051 auth-svc gRPC gRPC 端口
50052 core-svc gRPC gRPC 端口

环境变量覆盖

所有配置都可以通过环境变量覆盖,前缀 ANYFAST_,层级用 _ 连接:

# 示例: 修改 MySQL 连接
ANYFAST_MYSQL_PRIMARY=192.168.1.100:3306 \
ANYFAST_MYSQL_USERNAME=dev \
ANYFAST_MYSQL_PASSWORD=dev123 \
make dev-auth

# 示例: 修改 JWT 过期时间
ANYFAST_JWT_EXPIRE_HOUR=1 make dev-auth

常用覆盖项:

环境变量 默认值 说明
ANYFAST_SERVER_HTTP_PORT 8080 HTTP 端口
ANYFAST_MYSQL_PRIMARY 127.0.0.1:3306 MySQL 地址
ANYFAST_MYSQL_USERNAME root MySQL 用户名
ANYFAST_MYSQL_PASSWORD root MySQL 密码
ANYFAST_REDIS_ADDR 127.0.0.1:6379 Redis 地址
ANYFAST_JWT_SECRET dev-secret-... JWT 密钥
ANYFAST_JWT_EXPIRE_HOUR 24 JWT 过期小时数
ANYFAST_KAFKA_BROKERS 127.0.0.1:9092 Kafka 地址
ANYFAST_OTEL_ENDPOINT (空) OTel Collector 地址

Kafka 本地开发说明

Kafka 在本地开发中是可选的。

core-svc 创建 Producer 时,如果 Kafka brokers 为空或连接失败,会使用 Noop Producer 模式:

// NewProducer: brokers 为空时返回 noop producer
func NewProducer(brokers []string) *Producer {
    if len(brokers) == 0 || brokers[0] == "" {
        return &Producer{writers: nil}  // noop
    }
    // ...
}

// Publish: noop 模式直接返回 nil
func (p *Producer) Publish(...) error {
    if p.writers == nil {
        return nil  // noop mode
    }
    // ...
}

这意味着:

  • core-svc 正常工作,创建租户/Token 等操作不受影响
  • 但不会发送 Kafka 事件,config-syncer 不会感知到变化
  • billing-svc 不会处理用量数据

如果需要完整测试 Kafka 流程:

# 使用 docker 启动本地 Kafka
docker run -d --name kafka \
  -p 9092:9092 \
  -e KAFKA_CFG_NODE_ID=0 \
  -e KAFKA_CFG_PROCESS_ROLES=controller,broker \
  -e KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093 \
  -e KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@localhost:9093 \
  -e KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER \
  bitnami/kafka:3.7

常见问题

Q1: make dev-auth 报 "connect primary: dial tcp 127.0.0.1:3306: connection refused"

原因: MySQL 容器未启动或未就绪。

解决:

# 检查容器状态
docker ps -a | grep anyfast-mysql

# 如果未运行,重新启动
docker compose -f docker-compose.dev.yaml up -d

# 等待 MySQL 就绪 (有 healthcheck,约 30 秒)
docker compose -f docker-compose.dev.yaml ps

Q2: 登录返回 "invalid credentials"

可能原因:

  1. 密码不对: 默认密码是 admin123
  2. bcrypt hash 异常: 某些环境下 init-db.sql 中的 hash 可能被转义

解决: 参考第四步重新生成 hash。

Q3: curl /api/menus 返回空菜单

可能原因: 角色-菜单关联数据未初始化。

解决:

docker exec -it anyfast-mysql mysql -uroot -proot anyfast -e "
  SELECT count(*) FROM role_menus WHERE role = 'owner';
"
# 如果是 0,重新执行初始化脚本
docker exec -i anyfast-mysql mysql -uroot -proot anyfast < scripts/init-db.sql

Q4: Redis 连接报 "sentinel" 相关错误

原因: 本地开发使用单节点 Redis,不需要 Sentinel。

检查: 确保 configs/config.yamlredis.master_name 为空:

redis:
  addr: "127.0.0.1:6379"
  master_name: ""         # 留空 = 单节点模式

Q5: 前端启动后页面白屏或报 CORS 错误

原因: 后端 CORS 配置仅允许 localhost:3000

解决:

  1. 确保前端在 3000 端口运行: npm run dev (默认 3000)
  2. 如果改了端口,需要修改 internal/pkg/middleware/cors.go 中的 AllowOrigins

Q6: 端口被占用

# 查看端口占用
lsof -i :8080
lsof -i :3306

# 杀掉占用进程
kill -9 <PID>

# 或使用其他端口
ANYFAST_SERVER_HTTP_PORT=8090 make dev-auth

Q7: go mod tidy 报下载错误

# 设置 Go 代理 (国内)
go env -w GOPROXY=https://goproxy.cn,direct
go mod tidy

热重载说明

热重载 说明
Go 后端 修改代码后需要 Ctrl+C 重新 make dev-xxx
前端 Next.js 自动热重载,保存文件即生效
MySQL 修改 init-db.sql 后需重建容器或手动执行 SQL

如果需要 Go 后端自动重载,可安装 air:

go install github.com/air-verse/air@latest

# 使用 air 启动 (自动监听文件变化)
ANYFAST_SERVER_HTTP_PORT=8080 air -c .air.toml -- ./cmd/auth/

完整启动顺序

# 终端 1: 基础设施
docker compose -f docker-compose.dev.yaml up -d

# 等待 30 秒确保 MySQL 就绪

# 终端 2: auth 服务
make dev-auth

# 终端 3: core 服务
make dev-core

# 终端 4: 前端
cd web && npm install && npm run dev

# 浏览器打开 http://localhost:3000
# 用 admin / admin123 登录