Skip to content

跨服通信(CrossServer SDK)

1.2.0-beta 起,ArcartXSuite 将跨服能力收敛为宿主侧统一 SDK,各模块不再各自维护 Redis Pub/Sub 或 BungeeCord 专用频道。

设计原则

原则说明
子服侧总线跨服逻辑在子服 axs-coreCrossServerService 中实现,模块只注册通道与业务 payload
统一信封所有模块共用 JSON CrossServerEnvelope(HMAC 可选),不再各模块自定义 wire 格式
双后端Redis Pub/Sub 与 BungeeCord/Velocity Forward 可同时启用,出站双发、入站去重
Proxy 非总线ArcartXSuite-Proxy 负责认证路由,不是跨服消息总线;跨服消息走子服 SDK
无旧版兼容已移除各模块 transport.redis / transport.proxy 等独立配置

架构示意

┌────────────────────────────────────────────────────────────────────────────┐
│  Chat / Tab / Mail / Market / Announcer / OnlineRewards / EntityTracker …  │
│       openChannel("chat", config, consumer)                                │
└────────────────────────────┬───────────────────────────────────────────────┘
                             │ 模块 payload(字符串/JSON/YAML)

┌─────────────────────────────────────────────────────────────────┐
│  CrossServerService(axs-core)                                 │
│  · 封装 CrossServerEnvelope(module, nodeId, messageId, sign)   │
│  · 出站:Redis PUBLISH + Proxy Forward(可选)                   │
│  · 入站:验签 → message-id 去重 → 跳过本 node → 按 module 分发    │
└──────────────┬──────────────────────────────┬───────────────────┘
               │                              │
        Redis  │ AXS:CROSS                    │ BungeeCord Forward
               │                              │ AXS_CROSS
               ▼                              ▼
         其他子服 CrossServerService

配置分层

宿主 config.yml — 连接与全局策略

所有子服共用同一套连接参数(Redis 地址、Proxy 频道、签名密钥等),每台子服 node-id 必须不同

yaml
cross-server:
  node-id: "lobby-1"          # 每台子服唯一,用于去重与来源识别
  dedupe-ttl-ms: 60000        # 入站 message-id 去重窗口
  max-payload-chars: 524288   # 单条 payload 上限(字符)
  redis:
    enabled: true
    host: "192.168.1.100"
    port: 6379
    password: ""
    database: 0
    channel: "AXS:CROSS"      # 全模块共用频道
    connect-timeout-ms: 5000
  proxy:
    enabled: false            # 可与 Redis 同时 true
    messenger-channel: "AXS_CROSS"
    forward-target: "ALL"
  signature:
    enabled: true
    secret: "your-shared-secret"
    verify: true
字段说明
node-id当前子服节点 ID。留空时回退为 Bukkit 服务器名
dedupe-ttl-ms同一 messageId 在此窗口内只处理一次(Redis + Proxy 双通道防重复)
max-payload-chars超过上限的 payload 会被拒绝;Tab 大快照建议依赖 Redis
redis.channel默认 AXS:CROSS所有子服、所有模块共用
proxy.messenger-channel默认 AXS_CROSS,与旧版各模块独立频道不同
signature启用后出站 HMAC-SHA256;verify: true 时入站必须验签通过

Proxy 通道限制

BungeeCord Plugin Messaging 单包约 32KB。超大 payload(如 Tab 全量快照)在 Proxy 通道会被跳过,仅走 Redis。生产环境多服 Tab 同步强烈建议启用 Redis

无在线玩家时 Proxy 出站

Proxy Forward 需要至少一名在线玩家作为载体。若子服长期零在线,仅 Proxy 无法发出跨服消息;此时应启用 Redis 或保证有常驻假人/管理员在线。

模块 ArcartX*.yml — 仅开关与可选覆盖

各模块统一使用 cross-server 节,不再配置 Redis host、Proxy channel 等连接信息。

yaml
cross-server:
  enabled: true
  # 可选:仅覆盖本模块的后端开关(继承宿主默认)
  # redis:
  #   enabled: true
  # proxy:
  #   enabled: false

模块 cross-server.enabled: false 时不会注册通道,也不会收发跨服消息。

Wire 协议

外层信封 CrossServerEnvelope(JSON)

字段类型说明
protocolint固定 1
modulestring模块通道 ID,如 chattabmail
nodeIdstring发送方子服 node-id
messageIdstringUUID,全局去重用
timestamplong毫秒时间戳
payloadstring模块业务载荷(UTF-8 文本)
signaturestringHMAC-SHA256(signature.enabled 时)
  • RedisPUBLISH AXS:CROSS <整段 JSON>
  • ProxyBungeeCordForwardAXS_CROSS,body = 整段 JSON

内层 payload(模块自定义)

SDK 只负责信封与路由;业务格式由各模块定义,例如:

模块channel IDpayload 格式
ChatchatChat 信封 JSON
TabtabTab 快照 JSON
AnnouncerannouncerYAML AnnouncerEnvelope
Mailmailrefresh:{uuid}
OnlineRewardsonlinerewardsrefresh:{uuid}
MarketmarketLISTING_CREATED:{id} 等短文本
EntityTrackerentitytrackerBEST_DAMAGE\t... / KILL_RECORD\t... Tab 分隔
WarehousewarehouseLOCK\t{sharedId}\t... / UNLOCK\t{sharedId}\t...

已接入模块

模块配置文件典型用途
ChatArcartXChat.yml频道消息跨服;频道文件内 cross-server: true
TabArcartXTab.yml在线列表快照同步;Tab 定义 cross-server: true
AnnouncerArcartXAnnouncer.ymlgbroadcast / gbroadcastnow 手动公告
MailArcartXMail.yml新邮件到达后刷新其他子服收件箱 UI
OnlineRewardsArcartXOnlineRewards.yml签到/补签/管理操作后刷新
MarketArcartXMarket.yml拍卖事件广播(Redis 缓存仍用模块内 redis 节)
EntityTrackerArcartXEntityTracker.ymlBoss 死亡结算后同步各服玩家最高伤害(player_boss_best_damage
WarehouseArcartXWarehouse.yml共享仓库编辑锁 LOCK / UNLOCK(需 MySQL 共享库 + shared.enabled

Market 的 redis 节仅用于拍卖列表缓存cache-ttl-seconds),与跨服 Pub/Sub 无关。

EntityTracker 需同时开启根级 cross-server.enablednew-features.cross-server-ranking.enabled;Redis/Proxy 连接见宿主 config.yml

Warehouse 跨服编辑锁需:shared.enabled: true、模块 cross-server.enabled: true、各子服共用同一 MySQL 仓库库。

多服部署清单

  1. 宿主 config.yml:配置 cross-server(Redis/Proxy/签名/node-id)
  2. 每台子服 node-id 唯一(如 lobbysurvivalcreative
  3. 各模块 cross-server.enabled: true
  4. 共享数据:Mail / OnlineRewards / Chat 禁言等需 MySQL 共享库
  5. 重载/axs reload all 或分模块 reload;观察控制台 [CrossServer] 已启动
  6. 验证:模块 status 命令(如 /axs chat status)查看跨服通道是否 active

开发者 API

模块通过 ModuleContext.crossServer() 获取 CrossServerAPI

java
CrossServerChannel channel = context.crossServer().openChannel(
    "mymodule",
    configuration.crossServer(),
    delivery -> handlePayload(delivery.payload())
);

// 出站
channel.publish(myPayloadString);

// 关闭(模块 onDisable)
channel.close();

配置解析:

java
CrossServerChannelConfig cfg = CrossServerChannelConfigs.fromSection(
    yaml.getConfigurationSection("cross-server")
);

详见 ModuleContext — crossServer()

与 ArcartXSuite-Proxy 的关系

组件职责
CrossServerService(子服)跨服游戏数据:聊天、Tab、邮件刷新、拍卖同步等
ArcartXSuite-Proxy(代理端)Yggdrasil 多源认证、离线拦截、账号类型标记

两者独立部署、独立配置。跨服消息不需要在 Proxy 插件中额外配置频道(子服 SDK 直接使用 BungeeCord Forward)。

故障排查

现象可能原因
其他子服收不到消息宿主 cross-server.redis/proxy 未启用;模块 cross-server.enabled: false
消息重复正常:双后端会双发,SDK 按 messageId 去重
Tab 跨服不完整仅 Proxy 且 payload 超 32KB → 启用 Redis
验签失败各子服 signature.secret 不一致或未配置
Proxy 发不出子服无在线玩家;改用 Redis

基于 GPL-3.0 许可发布