docs: 初始化 Docs 仓库
This commit is contained in:
15
deploy/dbhub/dbhub.toml
Normal file
15
deploy/dbhub/dbhub.toml
Normal file
@@ -0,0 +1,15 @@
|
||||
[[sources]]
|
||||
id = "takeout_app"
|
||||
dsn = "postgres://app_user:AppUser112233@120.53.222.17:5432/takeout_app_db"
|
||||
|
||||
[[sources]]
|
||||
id = "takeout_identity"
|
||||
dsn = "postgres://identity_user:IdentityUser112233@120.53.222.17:5432/takeout_identity_db"
|
||||
|
||||
[[sources]]
|
||||
id = "takeout_dictionary"
|
||||
dsn = "postgres://dictionary_user:DictionaryUser112233@120.53.222.17:5432/takeout_dictionary_db"
|
||||
|
||||
[[sources]]
|
||||
id = "takeout_hangfire"
|
||||
dsn = "postgres://hangfire_user:HangFire112233@120.53.222.17:5432/takeout_hangfire_db"
|
||||
47
deploy/postgres/README.md
Normal file
47
deploy/postgres/README.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# PostgreSQL 部署脚本
|
||||
|
||||
本目录提供在测试/预发布环境快速拉起 PostgreSQL 的脚本,复用线上同名数据库与账号,方便迁移/恢复。
|
||||
|
||||
## 目录结构
|
||||
|
||||
- `create_databases.sql`:创建四个业务库与对应角色(可多次执行,存在则跳过)。
|
||||
- `bootstrap.ps1`:PowerShell 包装脚本,调用 `psql` 执行 SQL。
|
||||
|
||||
## 前置条件
|
||||
|
||||
1. 已安装 PostgreSQL 12+,并能以管理员身份访问(默认使用 `postgres`)。
|
||||
2. 本地已配置 `psql` 可执行命令。
|
||||
|
||||
## 使用方法
|
||||
|
||||
```powershell
|
||||
cd deploy/postgres
|
||||
.\bootstrap.ps1 `
|
||||
-Host 120.53.222.17 `
|
||||
-Port 5432 `
|
||||
-AdminUser postgres `
|
||||
-AdminPassword "超级管理员密码"
|
||||
```
|
||||
|
||||
脚本会:
|
||||
|
||||
1. 创建/更新以下角色与库:
|
||||
- `app_user` / `takeout_app_db`
|
||||
- `identity_user` / `takeout_identity_db`
|
||||
- `dictionary_user` / `takeout_dictionary_db`
|
||||
- `hangfire_user` / `takeout_hangfire_db`
|
||||
2. 为库设置 COMMENT,授予 Schema `public` 的 CRUD 权限。
|
||||
3. 输出执行日志,失败时终止。
|
||||
|
||||
## 自定义
|
||||
|
||||
- 如需修改密码或新增库,编辑 `create_databases.sql` 后重新运行脚本。
|
||||
- 若在本地拉起测试库,可把 `Host` 指向 `localhost`,其余参数保持一致。
|
||||
|
||||
## 常见问题
|
||||
|
||||
| 问题 | 处理方式 |
|
||||
| --- | --- |
|
||||
| `psql : command not found` | 确认 PostgreSQL bin 目录已加入 PATH。 |
|
||||
| `permission denied to create database` | 改用具有 `CREATEDB` 权限的管理员执行脚本。 |
|
||||
| 需要删除库 | 先 `DROP DATABASE xxx`,再运行脚本重新创建。 |
|
||||
37
deploy/postgres/bootstrap.ps1
Normal file
37
deploy/postgres/bootstrap.ps1
Normal file
@@ -0,0 +1,37 @@
|
||||
param(
|
||||
[string]$Host = "120.53.222.17",
|
||||
[int]$Port = 5432,
|
||||
[string]$AdminUser = "postgres",
|
||||
[string]$AdminPassword = ""
|
||||
)
|
||||
|
||||
if (-not (Get-Command psql -ErrorAction SilentlyContinue)) {
|
||||
throw "psql command not found. Add PostgreSQL bin directory to PATH."
|
||||
}
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($AdminPassword)) {
|
||||
Write-Warning "AdminPassword not provided. You will be prompted by psql."
|
||||
}
|
||||
|
||||
$sqlPath = Join-Path $PSScriptRoot "create_databases.sql"
|
||||
if (-not (Test-Path $sqlPath)) {
|
||||
throw "Cannot find create_databases.sql under $PSScriptRoot."
|
||||
}
|
||||
|
||||
$env:PGPASSWORD = $AdminPassword
|
||||
|
||||
$arguments = @(
|
||||
"-h", $Host,
|
||||
"-p", $Port,
|
||||
"-U", $AdminUser,
|
||||
"-f", $sqlPath
|
||||
)
|
||||
|
||||
Write-Host "Executing create_databases.sql on $Host:$Port as $AdminUser ..."
|
||||
& psql @arguments
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "psql returned non-zero exit code ($LASTEXITCODE)."
|
||||
}
|
||||
|
||||
Write-Host "PostgreSQL databases and roles ensured successfully."
|
||||
102
deploy/postgres/create_databases.sql
Normal file
102
deploy/postgres/create_databases.sql
Normal file
@@ -0,0 +1,102 @@
|
||||
-- Reusable provisioning script for Takeout SaaS PostgreSQL databases.
|
||||
-- Execute with a superuser (e.g. postgres). Safe to re-run.
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'app_user') THEN
|
||||
CREATE ROLE app_user LOGIN PASSWORD 'AppUser112233';
|
||||
END IF;
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'identity_user') THEN
|
||||
CREATE ROLE identity_user LOGIN PASSWORD 'IdentityUser112233';
|
||||
END IF;
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'dictionary_user') THEN
|
||||
CREATE ROLE dictionary_user LOGIN PASSWORD 'DictionaryUser112233';
|
||||
END IF;
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'hangfire_user') THEN
|
||||
CREATE ROLE hangfire_user LOGIN PASSWORD 'HangFire112233';
|
||||
END IF;
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'logs_user') THEN
|
||||
CREATE ROLE logs_user LOGIN PASSWORD 'Logs112233';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_database WHERE datname = 'takeout_app_db') THEN
|
||||
CREATE DATABASE takeout_app_db OWNER app_user ENCODING 'UTF8';
|
||||
END IF;
|
||||
END $$;
|
||||
COMMENT ON DATABASE takeout_app_db IS 'Takeout SaaS 业务域数据库';
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_database WHERE datname = 'takeout_identity_db') THEN
|
||||
CREATE DATABASE takeout_identity_db OWNER identity_user ENCODING 'UTF8';
|
||||
END IF;
|
||||
END $$;
|
||||
COMMENT ON DATABASE takeout_identity_db IS 'Takeout SaaS 身份域数据库';
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_database WHERE datname = 'takeout_dictionary_db') THEN
|
||||
CREATE DATABASE takeout_dictionary_db OWNER dictionary_user ENCODING 'UTF8';
|
||||
END IF;
|
||||
END $$;
|
||||
COMMENT ON DATABASE takeout_dictionary_db IS 'Takeout SaaS 字典域数据库';
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_database WHERE datname = 'takeout_hangfire_db') THEN
|
||||
CREATE DATABASE takeout_hangfire_db OWNER hangfire_user ENCODING 'UTF8';
|
||||
END IF;
|
||||
END $$;
|
||||
COMMENT ON DATABASE takeout_hangfire_db IS 'Takeout SaaS 调度/Hangfire 数据库';
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_database WHERE datname = 'takeout_logs_db') THEN
|
||||
CREATE DATABASE takeout_logs_db OWNER logs_user ENCODING 'UTF8';
|
||||
END IF;
|
||||
END $$;
|
||||
COMMENT ON DATABASE takeout_logs_db IS 'Takeout SaaS 审计/日志数据库';
|
||||
|
||||
-- Ensure privileges and default schema permissions
|
||||
\connect takeout_app_db
|
||||
GRANT CONNECT, TEMP ON DATABASE takeout_app_db TO app_user;
|
||||
GRANT USAGE ON SCHEMA public TO app_user;
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app_user;
|
||||
GRANT USAGE, SELECT, UPDATE ON ALL SEQUENCES IN SCHEMA public TO app_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO app_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT USAGE, SELECT, UPDATE ON SEQUENCES TO app_user;
|
||||
|
||||
\connect takeout_identity_db
|
||||
GRANT CONNECT, TEMP ON DATABASE takeout_identity_db TO identity_user;
|
||||
GRANT USAGE ON SCHEMA public TO identity_user;
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO identity_user;
|
||||
GRANT USAGE, SELECT, UPDATE ON ALL SEQUENCES IN SCHEMA public TO identity_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO identity_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT USAGE, SELECT, UPDATE ON SEQUENCES TO identity_user;
|
||||
|
||||
\connect takeout_dictionary_db
|
||||
GRANT CONNECT, TEMP ON DATABASE takeout_dictionary_db TO dictionary_user;
|
||||
GRANT USAGE ON SCHEMA public TO dictionary_user;
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO dictionary_user;
|
||||
GRANT USAGE, SELECT, UPDATE ON ALL SEQUENCES IN SCHEMA public TO dictionary_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO dictionary_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT USAGE, SELECT, UPDATE ON SEQUENCES TO dictionary_user;
|
||||
|
||||
\connect takeout_hangfire_db
|
||||
GRANT CONNECT, TEMP ON DATABASE takeout_hangfire_db TO hangfire_user;
|
||||
GRANT USAGE ON SCHEMA public TO hangfire_user;
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO hangfire_user;
|
||||
GRANT USAGE, SELECT, UPDATE ON ALL SEQUENCES IN SCHEMA public TO hangfire_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO hangfire_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT USAGE, SELECT, UPDATE ON SEQUENCES TO hangfire_user;
|
||||
|
||||
\connect takeout_logs_db
|
||||
GRANT CONNECT, TEMP ON DATABASE takeout_logs_db TO logs_user;
|
||||
GRANT USAGE ON SCHEMA public TO logs_user;
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO logs_user;
|
||||
GRANT USAGE, SELECT, UPDATE ON ALL SEQUENCES IN SCHEMA public TO logs_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO logs_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT USAGE, SELECT, UPDATE ON SEQUENCES TO logs_user;
|
||||
89
deploy/postgres/migrate_logs_to_logs_db.sql
Normal file
89
deploy/postgres/migrate_logs_to_logs_db.sql
Normal file
@@ -0,0 +1,89 @@
|
||||
-- 日志库迁移脚本(请在 psql 中按步骤执行)
|
||||
|
||||
-- 1. 在日志库创建表结构(takeout_logs_db)
|
||||
\connect takeout_logs_db
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tenant_audit_logs (
|
||||
"Id" bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
"TenantId" bigint NOT NULL,
|
||||
"Action" integer NOT NULL,
|
||||
"Title" character varying(128) NOT NULL,
|
||||
"Description" character varying(1024),
|
||||
"OperatorId" bigint,
|
||||
"OperatorName" character varying(64),
|
||||
"PreviousStatus" integer,
|
||||
"CurrentStatus" integer,
|
||||
"CreatedAt" timestamp with time zone NOT NULL,
|
||||
"UpdatedAt" timestamp with time zone,
|
||||
"DeletedAt" timestamp with time zone,
|
||||
"CreatedBy" bigint,
|
||||
"UpdatedBy" bigint,
|
||||
"DeletedBy" bigint
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS "IX_tenant_audit_logs_TenantId" ON tenant_audit_logs ("TenantId");
|
||||
|
||||
CREATE TABLE IF NOT EXISTS merchant_audit_logs (
|
||||
"Id" bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
"MerchantId" bigint NOT NULL,
|
||||
"Action" integer NOT NULL,
|
||||
"Title" character varying(128) NOT NULL,
|
||||
"Description" character varying(1024),
|
||||
"OperatorId" bigint,
|
||||
"OperatorName" character varying(64),
|
||||
"CreatedAt" timestamp with time zone NOT NULL,
|
||||
"UpdatedAt" timestamp with time zone,
|
||||
"DeletedAt" timestamp with time zone,
|
||||
"CreatedBy" bigint,
|
||||
"UpdatedBy" bigint,
|
||||
"DeletedBy" bigint,
|
||||
"TenantId" bigint NOT NULL
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS "IX_merchant_audit_logs_TenantId_MerchantId" ON merchant_audit_logs ("TenantId", "MerchantId");
|
||||
|
||||
CREATE TABLE IF NOT EXISTS operation_logs (
|
||||
"Id" bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
"OperationType" character varying(64) NOT NULL,
|
||||
"TargetType" character varying(64) NOT NULL,
|
||||
"TargetIds" text,
|
||||
"OperatorId" character varying(64),
|
||||
"OperatorName" character varying(128),
|
||||
"Parameters" text,
|
||||
"Result" text,
|
||||
"Success" boolean NOT NULL,
|
||||
"CreatedAt" timestamp with time zone NOT NULL,
|
||||
"UpdatedAt" timestamp with time zone,
|
||||
"DeletedAt" timestamp with time zone,
|
||||
"CreatedBy" bigint,
|
||||
"UpdatedBy" bigint,
|
||||
"DeletedBy" bigint
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS "IX_operation_logs_CreatedAt" ON operation_logs ("CreatedAt");
|
||||
CREATE INDEX IF NOT EXISTS "IX_operation_logs_OperationType_CreatedAt" ON operation_logs ("OperationType", "CreatedAt");
|
||||
|
||||
CREATE TABLE IF NOT EXISTS member_growth_logs (
|
||||
"Id" bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
"MemberId" bigint NOT NULL,
|
||||
"ChangeValue" integer NOT NULL,
|
||||
"CurrentValue" integer NOT NULL,
|
||||
"Notes" character varying(256),
|
||||
"OccurredAt" timestamp with time zone NOT NULL,
|
||||
"CreatedAt" timestamp with time zone NOT NULL,
|
||||
"UpdatedAt" timestamp with time zone,
|
||||
"DeletedAt" timestamp with time zone,
|
||||
"CreatedBy" bigint,
|
||||
"UpdatedBy" bigint,
|
||||
"DeletedBy" bigint,
|
||||
"TenantId" bigint NOT NULL
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS "IX_member_growth_logs_TenantId_MemberId_OccurredAt" ON member_growth_logs ("TenantId", "MemberId", "OccurredAt");
|
||||
|
||||
-- 2. 迁移数据(建议使用 pg_dump/pg_restore 或应用侧批量拷贝)
|
||||
-- 示例:pg_dump -t tenant_audit_logs -t merchant_audit_logs -t operation_logs -t member_growth_logs takeout_app_db > logs_dump.sql
|
||||
-- psql -d takeout_logs_db -f logs_dump.sql
|
||||
|
||||
-- 3. 在业务库删除旧日志表(takeout_app_db)
|
||||
\connect takeout_app_db
|
||||
DROP TABLE IF EXISTS tenant_audit_logs;
|
||||
DROP TABLE IF EXISTS merchant_audit_logs;
|
||||
DROP TABLE IF EXISTS operation_logs;
|
||||
DROP TABLE IF EXISTS member_growth_logs;
|
||||
34
deploy/prometheus/alert.rules.yml
Normal file
34
deploy/prometheus/alert.rules.yml
Normal file
@@ -0,0 +1,34 @@
|
||||
groups:
|
||||
- name: takeoutsaas-app
|
||||
interval: 30s
|
||||
rules:
|
||||
- alert: HighErrorRate
|
||||
expr: |
|
||||
sum(rate(http_server_request_duration_seconds_count{http_response_status_code=~"5.."}[5m]))
|
||||
/ sum(rate(http_server_request_duration_seconds_count[5m])) > 0.05
|
||||
for: 5m
|
||||
labels:
|
||||
severity: critical
|
||||
annotations:
|
||||
summary: "API 5xx 错误率过高"
|
||||
description: "过去 5 分钟 5xx 占比超过 5%,请检查依赖或发布"
|
||||
|
||||
- alert: HighP95Latency
|
||||
expr: |
|
||||
histogram_quantile(0.95, sum(rate(http_server_request_duration_seconds_bucket[5m])) by (le, service_name))
|
||||
> 1
|
||||
for: 5m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
summary: "API P95 延迟过高"
|
||||
description: "过去 5 分钟 P95 超过 1s,请排查热点接口或依赖"
|
||||
|
||||
- alert: InstanceDown
|
||||
expr: up{job=~"admin-api|mini-api|user-api"} == 0
|
||||
for: 2m
|
||||
labels:
|
||||
severity: critical
|
||||
annotations:
|
||||
summary: "实例不可达"
|
||||
description: "Prometheus 抓取失败,实例处于 down 状态"
|
||||
28
deploy/prometheus/prometheus.yml
Normal file
28
deploy/prometheus/prometheus.yml
Normal file
@@ -0,0 +1,28 @@
|
||||
global:
|
||||
scrape_interval: 15s
|
||||
evaluation_interval: 30s
|
||||
|
||||
rule_files:
|
||||
- alert.rules.yml
|
||||
|
||||
scrape_configs:
|
||||
- job_name: admin-api
|
||||
metrics_path: /metrics
|
||||
static_configs:
|
||||
- targets: ["admin-api:8080"]
|
||||
labels:
|
||||
service: admin-api
|
||||
|
||||
- job_name: mini-api
|
||||
metrics_path: /metrics
|
||||
static_configs:
|
||||
- targets: ["mini-api:8080"]
|
||||
labels:
|
||||
service: mini-api
|
||||
|
||||
- job_name: user-api
|
||||
metrics_path: /metrics
|
||||
static_configs:
|
||||
- targets: ["user-api:8080"]
|
||||
labels:
|
||||
service: user-api
|
||||
34
deploy/redis/README.md
Normal file
34
deploy/redis/README.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# Redis 部署脚本
|
||||
|
||||
本目录提供可复用的 Redis 配置,既可在本地通过 Docker Compose 启动,也可将 `redis.conf` 拷贝到现有服务器,确保与线上一致。
|
||||
|
||||
## 1. 部署步骤 (裸机)\n\n1. 将 \\
|
||||
edis.conf\\ 拷贝到服务器(例如 /etc/redis/redis.conf)。\n2. 根据需要修改数据目录(\\dir\\)和绑定地址。\n3. 使用系统服务或 \\
|
||||
edis-server redis.conf\\ 启动。\n4. 确认开放端口 6379,保证通过 \\
|
||||
edis-cli -h <host> -a <pwd> ping\\ 可访问。\n\n## 2. 配置说明\n\n- \\
|
||||
equirepass\\ 已设置为 MsuMshk112233。\n- 启用 appendonly(AOF),并每秒 fsync。\n- \\maxmemory-policy\\ 为 allkeys-lru,适合缓存场景。\n- \\protected-mode no\\ 允许远程连接,需结合安全组或防火墙限制来源 IP。\n\n## 3. 常用命令使用 `redis.conf`
|
||||
|
||||
1. 把 `redis.conf` 拷贝到服务器 `/etc/redis/redis.conf`(或自定义目录)。
|
||||
2. 修改 `dir` 指向实际数据目录。
|
||||
3. 使用系统服务或 `redis-server redis.conf` 启动。
|
||||
|
||||
关键配置已包含:
|
||||
|
||||
- `requirepass`(密码)
|
||||
- `protected-mode no`(允许远程连接)
|
||||
- `appendonly yes` + `appendfsync everysec`
|
||||
- `maxmemory-policy allkeys-lru`
|
||||
|
||||
## 3. 常用命令
|
||||
|
||||
在应用或 CLI 中使用:
|
||||
|
||||
```bash
|
||||
redis-cli -h 49.232.6.45 -p 6379 -a MsuMshk112233 ping
|
||||
```
|
||||
|
||||
`appsettings.*.json` 的格式:`"Redis": "49.232.6.45:6379,password=MsuMshk112233,abortConnect=false"`
|
||||
|
||||
## 4. 备份
|
||||
|
||||
- RDB 文件:`dump.rdb`
|
||||
25
deploy/redis/redis.conf
Normal file
25
deploy/redis/redis.conf
Normal file
@@ -0,0 +1,25 @@
|
||||
bind 0.0.0.0
|
||||
port 6379
|
||||
protected-mode no
|
||||
|
||||
requirepass MsuMshk112233
|
||||
|
||||
timeout 0
|
||||
tcp-keepalive 300
|
||||
|
||||
daemonize no
|
||||
|
||||
loglevel notice
|
||||
databases 16
|
||||
|
||||
save 900 1
|
||||
save 300 10
|
||||
save 60 10000
|
||||
|
||||
appendonly yes
|
||||
appendfilename "appendonly.aof"
|
||||
appendfsync everysec
|
||||
|
||||
dir /data
|
||||
|
||||
maxmemory-policy allkeys-lru
|
||||
Reference in New Issue
Block a user