弹性连接:构建容错 API 客户端 - Openclaw Skills
作者:互联网
2026-03-30
什么是 弹性连接?
弹性连接(Resilient Connections)是为寻求增强网络层稳定性以应对分布式系统不可预测性的开发人员提供的技术蓝图。该技能提供了一系列经过实战检验的模式——包括指数退避和断路器——旨在确保您的应用程序在外部服务发生故障时仍能保持稳定。
通过集成 Openclaw Skills 中的这些模式,开发人员可以防止级联故障,并在短暂的服务中断期间提供无缝的用户体验。无论您是在管理实时 WebSocket 流还是标准的 RESTful API 调用,这些策略都能提供现代生产环境所需的容错能力。
下载入口:https://github.com/openclaw/skills/tree/main/skills/wpank/resiliant-connections
安装与下载
1. ClawHub CLI
从源直接安装技能的最快方式。
npx clawhub@latest install resiliant-connections
2. 手动安装
将技能文件夹复制到以下位置之一
全局模式~/.openclaw/skills/
工作区
/skills/
优先级:工作区 > 本地 > 内置
3. 提示词安装
将此提示词复制到 OpenClaw 即可自动安装。
请帮我使用 Clawhub 安装 resiliant-connections。如果尚未安装 Clawhub,请先安装(npm i -g clawhub)。
弹性连接 应用场景
- 构建需要处理瞬时网络故障或服务停机而不崩溃的 API 客户端。
- 实现必须自动重新连接并带有抖动延迟以维持状态的实时 WebSocket 连接。
- 创建需要通过主数据源、备份数据源和缓存数据源实现优雅降级的生产系统。
- 使用 Openclaw Skills 中标准化的重试逻辑保护下游服务免受惊群效应的影响。
- 使用提供的针对 fetch 或 WebSocket 协议的模式包装器初始化弹性客户端。
- 配置错误处理逻辑,以区分瞬时 500 系列错误和永久性 400 系列客户端错误。
- 应用带有随机抖动的指数退避,以分散重试尝试并减轻服务器压力。
- 通过断路器状态机监控故障阈值,以在长期停机期间触发电路并防止不必要的请求。
- 提供回退机制或缓存数据,以确保在等待服务恢复时 UI 仍能正常运行。
弹性连接 配置指南
要将此技能添加到您的开发环境并开始构建稳健的连接,请运行以下命令:
npx clawhub@latest install resilient-connections
弹性连接 数据架构与分类体系
该技能将其逻辑组织为模块化的 TypeScript 模式和可重用的接口。用于管理连接状态的主要数据结构包括:
| 组件 | 描述 |
|---|---|
| RetryOptions | 配置最大重试次数、基础延迟、最大延迟和抖动设置。 |
| CircuitState | 代表状态机的枚举:Closed(正常)、Open(故障)和 HalfOpen(测试)。 |
| FetchOptions | 标准 RequestInit 的扩展,增加了超时和重试计数属性。 |
| ReconnectingWebSocket | 一个基于类的结构,管理套接字连接的生命周期、事件处理程序和退避。 |
name: resilient-connections
model: standard
description: Patterns for building resilient API clients and real-time connections with retry logic, circuit breakers, and graceful degradation. Use when building production systems that need to handle failures. Triggers on retry logic, circuit breaker, connection resilience, exponential backoff, API client, fault tolerance.
Resilient Connections
Build API clients and real-time connections that handle failures gracefully with retries, circuit breakers, and fallbacks.
Installation
OpenClaw / Moltbot / Clawbot
npx clawhub@latest install resilient-connections
When to Use
- Building API clients that need to handle transient failures
- Real-time connections that should reconnect automatically
- Systems that need graceful degradation
- Any production system calling external services
Pattern 1: Exponential Backoff
interface RetryOptions {
maxRetries: number;
baseDelay: number;
maxDelay: number;
jitter?: boolean;
}
async function withRetry(
fn: () => Promise,
options: RetryOptions
): Promise {
const { maxRetries, baseDelay, maxDelay, jitter = true } = options;
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
if (attempt === maxRetries) throw error;
// Calculate delay with exponential backoff
let delay = Math.min(baseDelay * 2 ** attempt, maxDelay);
// Add jitter to prevent thundering herd
if (jitter) {
delay = delay * (0.5 + Math.random());
}
await sleep(delay);
}
}
throw new Error('Unreachable');
}
// Usage
const data = await withRetry(
() => fetch('/api/data').then(r => r.json()),
{ maxRetries: 3, baseDelay: 1000, maxDelay: 30000 }
);
Pattern 2: Circuit Breaker
enum CircuitState {
Closed, // Normal operation
Open, // Failing, reject requests
HalfOpen, // Testing if recovered
}
class CircuitBreaker {
private state = CircuitState.Closed;
private failures = 0;
private lastFailure = 0;
constructor(
private threshold: number = 5,
private timeout: number = 30000
) {}
async execute(fn: () => Promise): Promise {
if (this.state === CircuitState.Open) {
if (Date.now() - this.lastFailure > this.timeout) {
this.state = CircuitState.HalfOpen;
} else {
throw new Error('Circuit breaker is open');
}
}
try {
const result = await fn();
this.onSuccess();
return result;
} catch (error) {
this.onFailure();
throw error;
}
}
private onSuccess() {
this.failures = 0;
this.state = CircuitState.Closed;
}
private onFailure() {
this.failures++;
this.lastFailure = Date.now();
if (this.failures >= this.threshold) {
this.state = CircuitState.Open;
}
}
}
Pattern 3: Resilient Fetch Wrapper
interface FetchOptions extends RequestInit {
timeout?: number;
retries?: number;
}
async function resilientFetch(
url: string,
options: FetchOptions = {}
): Promise {
const { timeout = 10000, retries = 3, ...fetchOptions } = options;
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
const fetchWithTimeout = async () => {
try {
const response = await fetch(url, {
...fetchOptions,
signal: controller.signal,
});
if (!response.ok && response.status >= 500) {
throw new Error(`Server error: ${response.status}`);
}
return response;
} finally {
clearTimeout(timeoutId);
}
};
return withRetry(fetchWithTimeout, {
maxRetries: retries,
baseDelay: 1000,
maxDelay: 10000,
});
}
Pattern 4: Reconnecting WebSocket
class ReconnectingWebSocket {
private ws: WebSocket | null = null;
private retries = 0;
private maxRetries = 10;
constructor(
private url: string,
private onMessage: (data: unknown) => void
) {
this.connect();
}
private connect() {
this.ws = new WebSocket(this.url);
this.ws.onopen = () => {
this.retries = 0;
};
this.ws.onmessage = (event) => {
this.onMessage(JSON.parse(event.data));
};
this.ws.onclose = () => {
if (this.retries < this.maxRetries) {
const delay = Math.min(1000 * 2 ** this.retries, 30000);
this.retries++;
setTimeout(() => this.connect(), delay);
}
};
}
send(data: unknown) {
if (this.ws?.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify(data));
}
}
close() {
this.maxRetries = 0; // Prevent reconnection
this.ws?.close();
}
}
Pattern 5: Graceful Degradation
async function fetchWithFallback(
primary: () => Promise,
fallback: () => Promise,
cache?: T
): Promise {
try {
return await primary();
} catch (primaryError) {
console.warn('Primary failed, trying fallback:', primaryError);
try {
return await fallback();
} catch (fallbackError) {
console.warn('Fallback failed:', fallbackError);
if (cache !== undefined) {
console.warn('Using cached data');
return cache;
}
throw fallbackError;
}
}
}
// Usage
const data = await fetchWithFallback(
() => fetchFromPrimaryAPI(),
() => fetchFromBackupAPI(),
cachedData
);
Related Skills
- Meta-skill: ai/skills/meta/realtime-dashboard/ — Complete realtime dashboard guide
- realtime-react-hooks — Hook usage
- websocket-hub-patterns — Server patterns
NEVER Do
- NEVER retry non-idempotent requests — POST/PUT might succeed but fail to respond
- NEVER use fixed delays — Always add jitter to prevent thundering herd
- NEVER retry 4xx errors — Client errors won't resolve themselves
- NEVER keep circuit open forever — Always have a timeout to half-open
- NEVER hide connection failures — Show users the degraded state
Quick Reference
// Exponential backoff
const delay = Math.min(baseDelay * 2 ** attempt, maxDelay);
// With jitter
const jitteredDelay = delay * (0.5 + Math.random());
// Retry check
const shouldRetry =
error.status >= 500 ||
error.code === 'ETIMEDOUT' ||
error.code === 'ECONNRESET';
// Circuit breaker states
Closed -> (failures >= threshold) -> Open
Open -> (timeout elapsed) -> HalfOpen
HalfOpen -> (success) -> Closed
HalfOpen -> (failure) -> Open
相关推荐
专题
+ 收藏
+ 收藏
+ 收藏
+ 收藏
+ 收藏
最新数据
相关文章
韩国发票:自动化估价单与税务发票 - Openclaw Skills
小红书文案教练:爆款笔记生成器 - Openclaw Skills
慕尼黑 MVG & S-Bahn 实时追踪命令行工具 - Openclaw Skills
Reddit 研究技能:自动化社群洞察 - Openclaw Skills
豆包聊天:带有联网搜索功能的免费 AI 对话 - Openclaw Skills
NightPatch:自动化工作流优化 - Openclaw 技能
国产 AI 视频生成器:Wan2.6 与可灵集成 - Openclaw Skills
Sonos Announce:智能音频状态恢复 - Openclaw Skills
Hypha Payment:P2P 代理协作与 USDT 结算 - Openclaw Skills
Cashu Emoji:隐藏代币编解码 - Openclaw Skills
AI精选
