|
|
1 month ago | |
|---|---|---|
| cache | 1 month ago | |
| client | 2 months ago | |
| common | 1 month ago | |
| config | 2 months ago | |
| handler | 1 month ago | |
| live | 2 months ago | |
| logger | 3 months ago | |
| middleware | 2 months ago | |
| mock | 2 months ago | |
| model | 1 month ago | |
| mqtt | 1 month ago | |
| route | 2 months ago | |
| service | 1 month ago | |
| sql | 1 month ago | |
| token | 2 months ago | |
| tool | 2 months ago | |
| vo | 1 month ago | |
| websocket | 3 months ago | |
| DESIGN.md | 2 months ago | |
| Makefile | 3 months ago | |
| README.md | 1 month ago | |
| config-prod.yaml | 1 month ago | |
| config.yaml | 2 months ago | |
| go.mod | 2 months ago | |
| go.sum | 2 months ago | |
| main.go | 2 months ago | |
| publish-prod.sh | 2 months ago | |
README.md
laic-backend
低空智控平台 后端 Go 服务。
生产部署
部署脚本参考 D:/GoProject/roller-service/roller-manage/publish-prod.sh,使用 Supervisor 管理服务。
服务器准备
在生产服务器安装 Supervisor。生产配置保存在仓库根目录的 config-prod.yaml,部署脚本会将它上传为服务器部署目录中的 config.yaml:
sudo apt update
sudo apt install supervisor -y
sudo systemctl enable --now supervisor
生产配置至少包含:
oss:
endpoint: https://obs.cn-east-2.myhuaweicloud.com
access-key: 实际的华为云 OBS AK
secret-key: 实际的华为云 OBS SK
bucket: gcs-edu
region: cn-east-2
use-ssl: true
后端启动时直接读取部署目录下的 config.yaml。本地开发不设置 LAIC_CONFIG_FILE 时读取本地 config.yaml;Supervisor 显式设置 LAIC_CONFIG_FILE=config.yaml。
执行部署
修改 publish-prod.sh 顶部的 REMOTE、REMOTE_DIR 和服务参数,然后执行:
chmod +x publish-prod.sh
./publish-prod.sh
脚本会完成:
- 交叉编译 Linux amd64 二进制。
- 创建远程部署目录、日志目录和备份目录。
- 备份旧二进制和
config.yaml(首次部署没有旧文件时跳过)。 - 将本地
config-prod.yaml上传为远程config.yaml。 - 更新 Supervisor 配置、重启服务并检查状态。
- 启动失败时自动恢复最近的旧二进制。
首次部署前确认远程服务器已安装并运行 Supervisor:
sudo apt update
sudo apt install supervisor -y
sudo systemctl enable --now supervisor
查看状态和日志:
sudo supervisorctl status laic-backend-prod
sudo tail -f /usr/local/laic-backend-prod/log/info.log
sudo tail -f /usr/local/laic-backend-prod/log/err.log
部署目录和服务名可以在 publish-prod.sh 顶部调整。回滚时,脚本会使用远程 backup/ 目录中最近的二进制备份;也可以手工恢复后执行:
sudo supervisorctl restart laic-backend-prod
Payment and SIM schema reconciliation
If a production database was upgraded from an older partial release, back it
up first and then run sql/019_reconcile_payment_schema.sql. The migration is
repeatable and fills missing traffic_order.updated_at, payment fields, pending
order guards, and normalizes legacy empty payment idempotency keys. It also
creates the payment/SIM tables. It does not create orders, charge users, or
create SIM cards. Verify the schema and platform resource pool after it finishes, then
restart the backend before retrying payment.
AGPay returns the WeChat QR code as binary image/png. The backend converts it
to a JSON-safe providerPayload data URI (data:image/png;base64,...); clients
should use that value directly as the image src and must not UTF-8 decode the
original response body.
Live session device event uniqueness
live_session.uk_live_session_device_event was originally built directly on
device_event_id. MySQL unique indexes treat multiple NULL values as
distinct but multiple empty strings as duplicates, so only one live session
without a reported device event could exist at a time. Creating a second live
session then failed with:
Error 1062 (23000): Duplicate entry '' for key 'live_session.uk_live_session_device_event'
Run sql/023_live_session_device_event_nullable.sql on any database created
before this fix. It adds a device_event_key generated column
(NULLIF(device_event_id, '')) and moves the unique index onto it. The
migration is repeatable. sql/001_schema.sql already contains the fixed
schema for new databases.
Live stop convergence
stopping is never moved back to an active phase (starting/streaming/
reconnecting). Any transition that did so would make the reconciler see an
active session again and publish another video.stop_stream, producing an
unbounded stop loop when the edge no longer knows the session.
If the edge restarts dock-video-relay, it returns to idle and rejects the
stop with VIDEO_SESSION_MISMATCH (protocol section 5.2.4; the mock uses
SESSION_NOT_FOUND). Both codes mark the session stopped immediately.
Otherwise the session stays stopping and is forced to stopped after 120
seconds (stopForceAfter), including when the stop command times out because
the edge is offline. That bound also keeps
uk_live_session_active_dock released so the dock can start a new session.
Live session lifetime
A live session's absolute deadline comes from live.max-session-seconds (falling
back to live.auth-expire-seconds when unset). It is sent to the edge as
video.start_stream.expiresAt and also bounds the signed push/play URLs, so it
cannot be extended mid-session: re-sending video.start_stream with a different
expiresAt changes the params digest and the edge rejects it with
COMMAND_ID_CONFLICT (protocol section 5.1/6).
Idle shutdown is therefore handled by viewer leases, not by that deadline: with
no active lease the session is stopped after live.stop-grace-seconds, while a
viewer that keeps calling the heartbeat endpoint keeps the stream alive until
the absolute deadline. The production value is 2 hours (max-session-seconds: 7200); raise it if users need longer continuous viewing. A stopping session
is forced to stopped after 120 seconds even if the edge keeps reporting
streaming=true, so a stuck publisher cannot block the dock from starting a new
session.
Live billing bitrate
Live billing now charges the average bitrate the edge reports in
state/video.bitrateBps (the protocol's expectedBitrateBps, 1 Mbps by
default) instead of the session peak maxBitrateBps (1.5 Mbps). Run
sql/024_live_session_billing_bitrate.sql before deploying; it adds
live_session.billing_bitrate_bps. The migration is repeatable and
sql/001_schema.sql already contains the column for new databases. Until the
edge reports a bitrate the charged value falls back to max_bitrate_bps.
Live start params rehearsal
video.start_stream retries must resend the exact same params because the
edge compares a params digest for commandId idempotency. The push URL carries
a short-lived credential and is therefore stored in Redis under
laic:live:startparams:{commandId} (never in MySQL, per the live backend
design, section 11) and replayed verbatim on retry.
Test traffic grant
For QA environments, set the following configuration explicitly (it defaults to disabled):
testing:
allow-traffic-grant: true
An authenticated administrator can then credit a regular user without creating a payment order:
POST /v1/admin/traffic/test-grants
Content-Type: application/json
{"userId":8243938201600,"amountGb":10,"reason":"live test"}
The operation updates the user snapshot, appends a test_grant traffic ledger
entry, invalidates the Redis balance cache, and writes an operation log. Keep
the switch disabled in production after testing.