news 2026/9/12 23:17:56

Cloudflare Workers VPC 连接实战:基于 TCP Sockets API 打通私有网络

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Cloudflare Workers VPC 连接实战:基于 TCP Sockets API 打通私有网络

Cloudflare Workers VPC 连接实战:基于 TCP Sockets API 打通私有网络

【免费下载链接】skillsSkills Catalog for Codex项目地址: https://gitcode.com/GitHub_Trending/skills4/skills

导读

本文以 Cloudflare Workers 的TCP Sockets APIcloudflare:sockets)为核心,系统讲解如何让 Worker 通过出站 TCP 连接访问 AWS、Azure、GCP、本地数据中心等私有网络中的资源,并联合 Cloudflare Tunnel、Hyperdrive、Smart Placement 组成完整的私有网络接入方案。读完本文,你将掌握connect()的完整 API 用法、TLS/StartTLS 三种加密模式、Wrangler 配置与多环境部署、Worker + Tunnel 的架构搭建,以及重试、超时、SSRF 防护等生产级实战模式。

说明:本文对应仓库 workers-vpc 参考文档 系列(含 api.md、configuration.md、patterns.md、gotchas.md)。该文档体系隶属于本仓库cloudflare-deployskill(见 SKILL.md 中 "Networking & Connectivity" 产品索引)。注意:本文档讲述的是 TCP Sockets API;更新的 Workers VPC Services 产品(仅支持 HTTP 的 service binding,内置 SSRF 防护)目前处于 beta 阶段(2025+),属另一套独立文档。

技术选型:先回答"该用哪个"

面对"Worker 需要访问私有网络资源"的需求,第一件事不是写代码,而是按需选型。下面是文档给出的快速决策表:

需求使用原因
私有网络中的 HTTP/HTTPS APIVPC Services(beta,独立文档)SSRF 安全、声明式绑定
PostgreSQL/MySQL 数据库Hyperdrive连接池、缓存、链路优化
自定义 TCP 协议(SSH、MQTT、私有协议)TCP Sockets(本文主题)完全掌控线上协议
简单 HTTP、追求最低延迟TCP Sockets + Smart Placement手动优化链路
把内网服务暴露到公网(入站方向)Cloudflare Tunnel非 Worker 专属能力

何时该用 TCP Sockets

适合使用 TCP Sockets 的场景:

  • ✅ 需要直接控制线上协议(如 Postgres 线上协议、SSH、Redis RESP)
  • ✅ 非 HTTP 协议(MQTT、SMTP、自定义二进制协议)
  • ✅ 需要 StartTLS 或自定义 TLS 协商
  • ✅ 需要通过 TCP 流式传输二进制数据

不要使用 TCP Sockets 的场景:

  • ❌ 只是需要 HTTP/HTTPS(请用fetch()或 VPC Services)
  • ❌ 需要 PostgreSQL/MySQL(请用 Hyperdrive 做连接池)
  • ❌ 需要 WebSocket(请用 Workers 原生 WebSocket 能力)

这个取舍背后是明确的工程理由:TCP Sockets 给你的是"裸线上协议"级别的控制力,代价是你要自己处理协议细节、连接生命周期与安全边界。仓库的 gotchas.md 中"何时使用替代方案"一节进一步印证了这一原则:数据库场景推荐 Hyperdrive(自带连接池与缓存)、HTTP 场景推荐fetch()(更简单、内置)、需要 SSRF 保护的 HTTP 场景则等待 VPC Services(beta)提供声明式绑定。

快速开始:一个最小可运行的示例

在 Worker 中发起 TCP 连接,核心只有一个函数connect(),从cloudflare:sockets模块导入:

import { connect } from 'cloudflare:sockets'; export default { async fetch(req: Request): Promise<Response> { // 连接私有服务 const socket = connect( { hostname: "db.internal.company.net", port: 5432 }, { secureTransport: "on" } ); try { await socket.opened; // 等待连接建立 const writer = socket.writable.getWriter(); await writer.write(new TextEncoder().encode("QUERY\r\n")); await writer.close(); const reader = socket.readable.getReader(); const { value } = await reader.read(); return new Response(value); } finally { await socket.close(); // 始终关闭 socket } } };

注意三个关键点:await socket.opened确保连接成功后才读写;写入与读取分别通过writable/readable两个 Web Stream;finallyawait socket.close()保证无论成功失败都释放连接。try/finally关闭模式是本 API 最核心的规范(详见下文"最佳实践")。

TCP Sockets API 详解

connect()函数签名

function connect( address: SocketAddress, options?: SocketOptions ): Socket

创建一条到指定地址的出站 TCP 连接。

SocketAddress:目标地址

interface SocketAddress { hostname: string; // DNS 主机名或 IP 地址 port: number; // TCP 端口(1-65535,排除被屏蔽端口) }
字段类型说明示例
hostnamestring目标主机名或 IP"db.internal.net""10.0.1.50"
portnumberTCP 端口号543244322

DNS 名称在连接时解析。支持 IPv4、IPv6 以及私有 IP(10.x、172.16.x、192.168.x)。

SocketOptions:连接选项

interface SocketOptions { secureTransport?: "off" | "on" | "starttls"; allowHalfOpen?: boolean; }
字段类型默认值说明
secureTransport"off" \| "on" \| "starttls""off"TLS 模式
allowHalfOpenbooleanfalse是否允许半开连接

secureTransport三种模式的适用场景:

模式行为适用场景
"off"纯 TCP,不加密测试、内部可信网络
"on"立即进行 TLS 握手HTTPS、安全数据库、SSH
"starttls"先明文连接,之后用startTls()升级Postgres、SMTP、IMAP

allowHalfOpen默认false时,关闭读流会自动关闭写流;设为true后读写流相互独立,适合需要半开连接语义的自定义协议。

Socket 接口

interface Socket { // 数据流 readable: ReadableStream<Uint8Array>; writable: WritableStream<Uint8Array>; // 连接状态 opened: Promise<SocketInfo>; closed: Promise<void>; // 方法 close(): Promise<void>; startTls(): Socket; }
  • readable:用于读取数据的流,通过getReader()消费。const { done, value } = await reader.read();每次读取一个 chunk。
  • writable:用于写入数据的流,通过getWriter()发送。写入后建议await writer.close()通知对端写入结束。
  • opened:连接成功时 resolve、失败时 reject 的 Promise,可拿到SocketInforemoteAddresslocalAddress,均可能为undefined):
interface SocketInfo { remoteAddress?: string; // 可能为 undefined localAddress?: string; // 可能为 undefined } try { const info = await socket.opened; } catch (error) { // 连接失败 }
  • closed:socket 完全关闭(双向)时 resolve 的 Promise。
  • close():优雅关闭连接,会等待待写入数据完成。务必在finally中调用
const socket = connect({ hostname: "api.internal", port: 443 }); try { // 使用 socket } finally { await socket.close(); }
  • startTls():将连接升级为 TLS,仅当创建时指定了secureTransport: "starttls"才可用。升级后必须使用返回的新 socket,而不是原 socket:
const socket = connect( { hostname: "db.internal", port: 5432 }, { secureTransport: "starttls" } ); // 先发送协议专用的 StartTLS 命令 const writer = socket.writable.getWriter(); await writer.write(new TextEncoder().encode("STARTTLS\r\n")); // 升级为 TLS - 使用返回的 socket,而不是原来的 const secureSocket = socket.startTls(); const secureWriter = secureSocket.writable.getWriter();

StartTLS 的典型协议是 SMTP、IMAP、Postgres:这些协议先以明文建立会话,客户端发送STARTTLS命令、等待服务端确认 OK 后,再调用startTls()升级为加密通道(时机错误会触发 TLS 错误,详见后文"常见坑")。

完整示例与快速参考

import { connect } from 'cloudflare:sockets'; export default { async fetch(req: Request): Promise<Response> { const socket = connect({ hostname: "echo.example.com", port: 7 }, { secureTransport: "on" }); try { await socket.opened; const writer = socket.writable.getWriter(); await writer.write(new TextEncoder().encode("Hello, TCP!\n")); await writer.close(); const reader = socket.readable.getReader(); const { value } = await reader.read(); return new Response(value); } finally { await socket.close(); } } };

常用操作速查表:

任务代码
导入import { connect } from 'cloudflare:sockets';
连接connect({ hostname: "host", port: 443 })
带 TLSconnect(addr, { secureTransport: "on" })
StartTLS握手后socket.startTls()
写入await writer.write(data); await writer.close();
读取const { value } = await reader.read();
错误处理try { await socket.opened; } catch { }
始终关闭try { } finally { await socket.close(); }

Wrangler 配置与多环境部署

基础配置

TCP Sockets 在 Workers 运行时默认可用,无需任何特殊配置。一个最简wrangler.jsonc

{ "name": "private-network-worker", "main": "src/index.ts", "compatibility_date": "2025-01-01" }

环境变量:连接信息不写死在代码里

{ "vars": { "DB_HOST": "10.0.1.50", "DB_PORT": "5432" } }
interface Env { DB_HOST: string; DB_PORT: string; } export default { async fetch(req: Request, env: Env): Promise<Response> { const socket = connect({ hostname: env.DB_HOST, port: parseInt(env.DB_PORT) }); } };

注意:vars中的值都是字符串,port需要parseInt()转换。

多环境(staging / production)配置

{ "vars": { "DB_HOST": "localhost" }, "env": { "staging": { "vars": { "DB_HOST": "staging-db.internal.net" } }, "production": { "vars": { "DB_HOST": "prod-db.internal.net" } } } }

部署时用--env指定环境:wrangler deploy --env stagingwrangler deploy --env production。这让你可以用同一份代码、不同的目标地址做隔离发布。

密钥管理:敏感凭据用 Secret

数据库口令、TLS 私钥等敏感信息不要放进wrangler.jsonc,应使用wrangler secret

wrangler secret put DB_PASSWORD # 按提示输入值

在 Worker 中通过env.DB_PASSWORD读取,用于协议握手或身份认证。这是文档明确强调的安全边界:vars会随代码进入版本库,secrets只存在于运行时。

本地开发

使用wrangler dev调试。注意:本地模式可能无法访问私有网络,开发阶段应使用公网端点或 mock 服务器:

const config = process.env.NODE_ENV === 'dev' ? { hostname: 'localhost', port: 5432 } // Mock : { hostname: 'db.internal.example.com', port: 5432 }; // Production

连接串解析

很多配置系统以连接串形式给出数据库地址,可解析出 host 与 port:

function parseConnectionString(connStr: string): SocketAddress { const url = new URL(connStr); // e.g., "postgres://10.0.1.50:5432/mydb" return { hostname: url.hostname, port: parseInt(url.port) || 5432 }; }

兼容性说明

TCP Sockets 在所有现代 Workers 运行时均可用,设置当前日期(如"compatibility_date": "2025-01-01")即可,无需任何特殊 compatibility flags。部署前可先按 SKILL.md 的要求执行npx wrangler whoami确认已认证,CI/CD 场景设置CLOUDFLARE_API_TOKEN环境变量。

架构模式:Worker + Tunnel 打通私有网络

TCP Sockets 本身只解决了"出站 TCP"问题,而私有网络通常没有公网入口。文档给出的标准架构是Worker + Cloudflare Tunnel组合:

┌─────────┐ ┌─────────────┐ ┌──────────────┐ ┌─────────────┐ │ Worker │────▶│ TCP Socket │────▶│ Tunnel │────▶│ Private │ │ │ │ (this API) │ │ (cloudflared)│ │ Network │ └─────────┘ └─────────────┘ └──────────────┘ └─────────────┘
  1. Worker 向 Tunnel 主机名发起 TCP socket 连接
  2. Tunnel 端点将流量路由到私有 IP
  3. 响应沿 Tunnel 原路返回 Worker

数据链路为:Worker (TCP Socket) → Tunnel hostname → cloudflared → Private Network

快速搭建步骤

  1. 在私有网络内的服务器上安装 cloudflared(详见 Tunnel 参考文档)
  2. 创建隧道cloudflared tunnel create my-private-network
  3. config.yml中配置路由
tunnel: <TUNNEL_ID> credentials-file: /path/to/<TUNNEL_ID>.json ingress: - hostname: db.internal.example.com service: tcp://10.0.1.50:5432 - service: http_status:404 # 必需的兜底规则
  1. 运行隧道cloudflared tunnel run my-private-network
  2. 从 Worker 连接
const socket = connect( { hostname: "db.internal.example.com", port: 5432 }, // Tunnel 主机名 { secureTransport: "on" } );

从仓库的 Tunnel 配置参考 可以补充几个深化点:

  • ingress 规则自上而下匹配,第一条命中生效,支持精确主机名、通配符主机名("*.example.com")、路径正则(path: \.(jpg|png|css|js)$),service: http_status:404兜底规则必须有
  • service 类型支持tcp://localhost:2222ssh://localhost:22rdp://localhost:3389unix:/path/to/socket等,本文的数据库场景走tcp://
  • 配置后可用cloudflared tunnel ingress validate校验配置、cloudflared tunnel ingress rule https://foo.example.com模拟匹配;
  • 生产环境更推荐token 化隧道cloudflared tunnel --no-autoupdate run --token <TOKEN>),路由在 Cloudflare Dashboard(Zero Trust > Networks > Tunnels)集中管理,无需分发配置文件、改动即时生效。

配合 Smart Placement 降低延迟

在 Worker 多次访问私有后端时,可开启 Smart Placement 让 Worker 自动迁移到离后端更近的位置执行:

{ "placement": { "mode": "smart" } }

Workers 会观察与 TCP socket 目标之间的连接延迟,自动选择更优的执行位置。详见 Smart Placement 参考。

数据库场景优先 Hyperdrive

如果目标是 PostgreSQL/MySQL,强烈建议优先使用 Hyperdrive而非裸 TCP socket,它自带连接池(省去每次请求的 TCP/TLS/auth 握手往返)、边缘建连与查询缓存(非变更查询默认 60s TTL):

{ "hyperdrive": [{ "binding": "DB", "id": "<HYPERDRIVE_ID>" }] }

创建配置:npx wrangler hyperdrive create my-db --connection-string="postgres://user:pass@host:5432/db"。完整配置见 Hyperdrive 参考。这也与主文档"最佳实践"第 3 条"数据库用 Hyperdrive"一致:原始 Postgres 线上协议复杂度高(启动、认证、查询消息),生产环境不应在裸 socket 上重造轮子。

实战模式:从协议到生产级错误处理

仓库的 patterns.md 提供了大量可直接落地的模式。

读取全部数据

TCP 是流式传输,一次read()拿不到完整报文,需要循环累积:

async function readAll(socket: Socket): Promise<Uint8Array> { const reader = socket.readable.getReader(); const chunks: Uint8Array[] = []; while (true) { const { done, value } = await reader.read(); if (done) break; chunks.push(value); } const total = chunks.reduce((sum, c) => sum + c.length, 0); const result = new Uint8Array(total); let offset = 0; for (const chunk of chunks) { result.set(chunk, offset); offset += chunk.length; } return result; }

流式响应:socket 直接接 HTTP Response

// 将 socket 数据直接流式写入 HTTP 响应 const socket = connect({ hostname: "stream.internal", port: 9000 }, { secureTransport: "on" }); const writer = socket.writable.getWriter(); await writer.write(new TextEncoder().encode("STREAM\n")); await writer.close(); return new Response(socket.readable);

协议示例:Redis RESP 与 MQTT

Redis RESP(发送*2\r\n$3\r\nGET\r\n$<keylen>\r\n<key>\r\n,接收$<len>\r\n<data>\r\n$-1\r\n表示 null):

const socket = connect({ hostname: "redis.internal", port: 6379 }); const writer = socket.writable.getWriter(); await writer.write(new TextEncoder().encode(`*2\r\n$3\r\nGET\r\n$3\r\nkey\r\n`));

MQTT(CONNECT 报文0x10 <len> 0x00 0x04 "MQTT" 0x04 <flags> ...,PUBLISH 报文0x30 <len> <topic_len> <topic> <message>):

const socket = connect({ hostname: "mqtt.broker", port: 1883 }); const writer = socket.writable.getWriter(); // CONNECT: 0x10 <len> 0x00 0x04 "MQTT" 0x04 <flags> ... // PUBLISH: 0x30 <len> <topic_len> <topic> <message>

PostgreSQL:文档明确提示生产环境用 Hyperdrive,因为裸 Postgres 协议非常复杂(startup、auth、query 消息)。

错误处理三件套

指数退避重试:

async function connectWithRetry(addr: SocketAddress, opts: SocketOptions, maxRetries = 3): Promise<Socket> { for (let i = 1; i <= maxRetries; i++) { try { const socket = connect(addr, opts); await socket.opened; return socket; } catch (error) { if (i === maxRetries) throw error; await new Promise(r => setTimeout(r, 1000 * Math.pow(2, i - 1))); // 指数退避 } } throw new Error('Unreachable'); }

超时控制(API 没有内置超时,必须用Promise.race()自行实现):

async function connectWithTimeout(addr: SocketAddress, opts: SocketOptions, ms = 5000): Promise<Socket> { const socket = connect(addr, opts); const timeout = new Promise<never>((_, reject) => setTimeout(() => reject(new Error('Timeout')), ms)); await Promise.race([socket.opened, timeout]); return socket; }

主备降级:

async function connectWithFallback(primary: string, fallback: string, port: number): Promise<Socket> { try { const socket = connect({ hostname: primary, port }, { secureTransport: "on" }); await socket.opened; return socket; } catch { return connect({ hostname: fallback, port }, { secureTransport: "on" }); } }

安全模式:SSRF 防护

TCP Sockets 给了"任意出站连接"的能力,必须防 SSRF——不能让用户可控的目标直达内部服务。标准做法是严格白名单:

const ALLOWED_HOSTS = ['db.internal.company.net', 'api.internal.company.net', /^10\.0\.1\.\d+$/]; function isAllowed(hostname: string): boolean { return ALLOWED_HOSTS.some(p => p instanceof RegExp ? p.test(hostname) : p === hostname); } export default { async fetch(req: Request): Promise<Response> { const target = new URL(req.url).searchParams.get('host'); if (!target || !isAllowed(target)) return new Response('Forbidden', { status: 403 }); const socket = connect({ hostname: target, port: 443 }); // Use socket... } };

白名单同时支持精确字符串与正则两种匹配。

连接池

每次请求新建 TCP 连接开销很大,可以自建小型连接池复用(注意池大小受平台并发限制约束):

class SocketPool { private pool = new Map<string, Socket[]>(); async acquire(hostname: string, port: number): Promise<Socket> { const key = `${hostname}:${port}`; const sockets = this.pool.get(key) || []; if (sockets.length > 0) return sockets.pop()!; const socket = connect({ hostname, port }, { secureTransport: "on" }); await socket.opened; return socket; } release(hostname: string, port: number, socket: Socket): void { const key = `${hostname}:${port}`; const sockets = this.pool.get(key) || []; if (sockets.length < 3) { sockets.push(socket); this.pool.set(key, sockets); } else socket.close(); } }

多协议网关

用同一个 Worker 暴露多种协议的连通性探测能力(以 Redis PING 为例):

interface Protocol { name: string; defaultPort: number; test(host: string, port: number): Promise<string>; } const PROTOCOLS: Record<string, Protocol> = { redis: { name: 'redis', defaultPort: 6379, async test(host, port) { const socket = connect({ hostname: host, port }); try { const writer = socket.writable.getWriter(); await writer.write(new TextEncoder().encode('*1\r\n$4\r\nPING\r\n')); writer.releaseLock(); const reader = socket.readable.getReader(); const { value } = await reader.read(); return new TextDecoder().decode(value || new Uint8Array()); } finally { await socket.close(); } } } }; export default { async fetch(req: Request): Promise<Response> { const url = new URL(req.url); const proto = url.pathname.slice(1); // /redis const host = url.searchParams.get('host'); if (!host || !PROTOCOLS[proto]) return new Response('Invalid', { status: 400 }); const result = await PROTOCOLS[proto].test(host, parseInt(url.searchParams.get('port') || '') || PROTOCOLS[proto].defaultPort); return new Response(result); } };

常见坑与排查指南

仓库的 gotchas.md 汇总了平台限制与高频错误,这里全部列出。

平台限制

限制项
每个请求的最大并发 socket 数6(硬限制)
socket 生命周期与请求同生命周期
连接超时平台决定,无配置项
  • 超出 6 个连接会直接抛错,解决方式是分批处理(每批 ≤6):
for (let i = 0; i < hosts.length; i += 6) { const batch = hosts.slice(i, i + 6).map(h => connect({ hostname: h, port: 443 })); await Promise.all(batch.map(async s => { /* use */ await s.close(); })); }
  • 被屏蔽的目标:Cloudflare 自身 IP(如 1.1.1.1)、localhost(127.0.0.1)、端口 25(SMTP)、Worker 自己的 URL,均因安全原因被禁止。解决办法是使用公网 IP 或 Tunnel 主机名。
  • 作用域限制:在全局作用域创建的 socket 会失败,因为 socket 与请求生命周期绑定,必须在 handler 内创建(export default { async fetch() { const socket = connect(...); } })。

常见错误对照

错误信息原因解决方案
proxy request failed目标被屏蔽(Cloudflare IP / localhost / 25 端口)、DNS 失败、网络不可达校验目标、使用 Tunnel 主机名、try/catch 兜底
TCP Loop detectedWorker 连接到了自身连接外部服务,不要连 Worker 自己的主机名
Port 25 prohibitedSMTP 端口被屏蔽改用 Email Workers API 处理邮件
socket is not open关闭后还在读写始终用 try/finally 保证关闭顺序
连接超时API 无内置超时Promise.race()自行实现(见上文超时模式)

TLS/SSL 陷阱

  • StartTLS 时机:必须先发送协议专用 STARTTLS 命令、等待服务端 OK,再调用socket.startTls(),过早升级会失败。
  • 证书校验:自签名证书会失败。要么使用正规证书,要么走 Cloudflare Tunnel(由 Tunnel 处理 TLS 终止)。

性能与数据处理的坑

  • 不建连接池:每次请求新建连接开销大。数据库场景直接换 Hyperdrive(内置池化)。
  • 不用 Smart Placement:后端延迟高时,在wrangler.jsonc开启{ "placement": { "mode": "smart" } }
  • 忘记关闭 socket:资源泄漏,务必try/finally { await socket.close(); }
  • 假设一次读完:TCP 分块到达,必须循环reader.read()直到done === true
  • 编码错误:明确指定编码,如new TextDecoder('iso-8859-1').decode(data)

调试技巧

  1. 记录连接信息const info = await socket.opened; console.log(info.remoteAddress);
  2. 先用公网服务验证:可先用 tcpbin.com:4242 之类的 echo 服务器测试基本连通性
  3. 验证 Tunnelcloudflared tunnel info <name>cloudflared tunnel route ip list(私有网络路由场景)

最佳实践清单

综合 README.md 与全系列文档,落地时遵循以下原则:

  1. 始终关闭 socket——用try/finally包裹,finallyawait socket.close()
  2. 校验目标地址——用白名单防 SSRF,绝不让用户输入直接决定连接目标;
  3. 数据库用 Hyperdrive——连接池与缓存远胜裸 TCP,且省去实现 Postgres/MySQL 线上协议的复杂度;
  4. HTTP 优先fetch()——只有非 HTTP 或需要线上协议控制时才用 TCP;
  5. 配合 Smart Placement——降低到私有网络的端到端延迟;
  6. 分批处理并发——单请求内并发 socket 不超过 6 个;
  7. 密钥走wrangler secret,地址等非敏感配置走vars,并用env区分 staging/production。

相关技术导航

  • Hyperdrive:PostgreSQL/MySQL 连接池化与缓存
  • Cloudflare Tunnel:安全访问私有网络(含 configuration.md 的 ingress 规则与 networking.md 网络预检)
  • Smart Placement:让 Worker 自动就近后端
  • Workers:承载本文所有代码的运行时
  • 同目录配套阅读顺序:api.md(接口与类型)→ configuration.md(Wrangler 配置与 Tunnel 集成)→ patterns.md(实战模式)→ gotchas.md(限制与排查)
  • VPC Services(beta, 2025+):仅 HTTP 的 service binding、内置 SSRF 保护,属独立文档体系,后续可关注

【免费下载链接】skillsSkills Catalog for Codex项目地址: https://gitcode.com/GitHub_Trending/skills4/skills

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 23:17:03

手机远程指挥AI编码:云端沙箱+Claude Code+Codex 完整实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 23:16:02

积分系统缓存架构评审:Caffeine+Redis多级缓存完整实践

开评审会之前&#xff0c;我其实没想到一个积分系统的缓存改造能吵得这么热闹。争论的焦点不是Redis够不够用&#xff0c;而是—要不要在Redis前面再加一层本地缓存。当时摆在桌上的方案有三套&#xff1a;纯Redis、Caffeine单机缓存、CaffeineRedis多级缓存。积分系统这个业务…

作者头像 李华
网站建设 2026/9/12 23:14:10

Pi Agent 环境变量完全指南:进程标记、会话注入与运行时配置

Pi Agent 环境变量完全指南&#xff1a;进程标记、会话注入与运行时配置 【免费下载链接】scientific-agent-skills Turn any AI agent into an AI Scientist. The #1 Agent Skills library for science, used by 190,000 scientists worldwide. 165 ready-to-use validated sk…

作者头像 李华
网站建设 2026/9/12 23:09:09

推客系统佣金规则动态配置技术解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 23:08:41

Beads 多 Agent 协作指南:任务分配、工作交接与冲突序列化

Beads 多 Agent 协作指南&#xff1a;任务分配、工作交接与冲突序列化 【免费下载链接】beads Beads - A memory upgrade for your coding agent 项目地址: https://gitcode.com/GitHub_Trending/beads1/beads 本指南面向使用 Beads 驱动多个 AI Agent 协同工作的场景&a…

作者头像 李华
网站建设 2026/9/12 23:08:30

电池类设备低功耗安全握手方案设计与优化实战

1. 项目概述与核心痛点1.1 为什么“安全握手”会成为电池类设备的头号难题做硬件这么多年&#xff0c;我最怕的不是功能做不出来&#xff0c;而是功能做出来了&#xff0c;设备却活不过一个冬天。电池类智能设备&#xff0c;从蓝牙门锁、温湿度传感器到智能穿戴&#xff0c;几乎…

作者头像 李华