Appearance
源码:labs/java/bridge-hybrid/bridge-timeout-layering-simulation/src/BridgeTimeoutLayeringSimulation.java
- 原始路径:
labs/java/bridge-hybrid/bridge-timeout-layering-simulation/src/BridgeTimeoutLayeringSimulation.java - 类型:
java
java
import java.util.Map;
/**
* 桥接调用超时分层仿真(对应 docs/05-bridge-hybrid/11)。
*
* 核心思想:桥接调用的「超时」不是一个数——运输层就绪、单次 RPC、
* 用户操作 UI、HTTP 读超时是四件事,必须分层建模。
*
* 纯 Java CLI(无外部依赖,用压缩等待模拟真实计时以便快速跑完)。
* 运行:javac -d out src/BridgeTimeoutLayeringSimulation.java && java -cp out BridgeTimeoutLayeringSimulation
*/
public class BridgeTimeoutLayeringSimulation {
// 四层超时语义(数值不可合并)
static final long TRANSPORT_READY_MS = 3000; // waitForBridge:超时仍 resolve,防卡死
static final long SINGLE_RPC_MS = 15000; // 单次 RPC 默认
static final long USER_OP_DISABLE_WEB_TIMER = -1; // 依赖用户操作:Web 侧不计时
static final long HTTP_READ_MS = 120000; // 上传等多图弱网慢操作
// 每通道独立超时表
static final Map<String, Long> channelTimeout = Map.of(
"getDeviceInfo", SINGLE_RPC_MS,
"requestPayment", USER_OP_DISABLE_WEB_TIMER, // 等用户操作,Native 关页才结束
"openGallery", USER_OP_DISABLE_WEB_TIMER,
"appUploadOss", HTTP_READ_MS);
public static void main(String[] args) throws InterruptedException {
System.out.println("=== 四层超时分离 ===");
System.out.println(" TRANSPORT_READY(waitForBridge) = " + TRANSPORT_READY_MS
+ "ms,超时仍 resolve(防卡死页面)");
System.out.println(" SINGLE_RPC 默认 = " + SINGLE_RPC_MS + "ms");
System.out.println(" USER_OP 通道:Web 侧关闭计时(requestPayment/openGallery)");
System.out.println(" HTTP_READ(appUploadOss) = " + HTTP_READ_MS + "ms(多图压缩+OSS 弱网慢)");
// 场景1:运输层未在窗口内就绪 → waitForBridge 超时仍 resolve(不卡死)
System.out.println();
System.out.println("=== 场景1:waitForBridge 超时仍 resolve ===");
boolean bridgeReady = false; // 模拟未就绪
boolean resolved = waitForBridge(bridgeReady, TRANSPORT_READY_MS);
System.out.println(" 桥未就绪,但 waitForBridge 返回: resolved=" + resolved
+ "(页面继续跑,不因桥缺失卡死)");
// 场景2:requestPayment 是用户操作通道,Web 侧不计时
System.out.println();
System.out.println("=== 场景2:用户操作通道关闭 Web 侧计时 ===");
long t = channelTimeout.get("requestPayment");
System.out.println(" requestPayment Web 侧计时="
+ (t == USER_OP_DISABLE_WEB_TIMER ? "关闭(等用户操作/Native 关页)" : "开启 " + t + "ms"));
System.out.println(" 若 Web 侧强行计时 15s:用户正在选支付方式 → 15s 到点误判失败 ❌");
System.out.println(" 正确:Web 侧不计时,由 Native 界面关闭事件结束 ✅");
// 场景3:阶梯 backoff
System.out.println();
System.out.println("=== 场景3:阶梯冷却 backoff ===");
for (long backoff : new long[]{1000, 2000, 4000}) {
System.out.println(" 重试冷却 " + backoff + "ms");
}
System.out.println();
System.out.println("=== 结论 ===");
System.out.println(" · 运输层就绪 / 单次 RPC / 用户操作 UI / HTTP 读超时 是四件事,必须分层建模");
System.out.println(" · 用户操作通道禁用 Web 侧计时,否则会把『用户正在操作』误判成超时失败");
}
/** 模拟 waitForBridge:到达窗口即返回 true(即使桥仍未就绪),绝不抛异常卡死页面 */
static boolean waitForBridge(boolean ready, long windowMs) throws InterruptedException {
long waited = Math.min(windowMs, ready ? 0 : windowMs);
Thread.sleep(Math.min(waited, 50)); // 演示用,压缩真实等待
return true; // 关键:超时也返回 true(resolved),不抛、不卡
}
}