45、【Agent】【OpenCode】本地代理分析(请求&接收回调)

【声明】本博客所有内容均为个人业余时间创作,所述技术案例均来自公开开源项目(如Github,Apache基金会),不涉及任何企业机密或未公开技术,如有侵权请联系删除

背景

上篇 blog
【Agent】【OpenCode】本地代理分析(效果呈现)

分析了其中的接收回调函数,提到了入参 proxyRes 不是用户自定义的局部变量,而是 Node.js 在触发接收回调时,动态创建的参数,每次收到一个响应,系统都会新建一个 proxyRes 对象传进来,另外分析了内存安全的问题,提到客户端响应对象 res 的生命周期由 Node.js 管理,一旦 proxyRes.pipe(res) 完成,或者当 HTTP 连接关闭时,res 会被自动清理,不会出现内存泄漏,最后总结了下本地代理的关键点,正是这种非阻塞式,事件驱动的模型,可以让 Node.s 能够高效处理成千上万的并发 AI 请求,然后改掉 opencode.json 中的 api 为本地代理的 URL,启用本地代理,再打开 OpenCode 客户端,发送请求,可以看到代理的转发过程,下面继续分析

OpenCode

上篇 blog 已经演示了本地代理的启动和运行,下面最后再解释下 http.createServer 的工作机制,以及它和 https.request 接收回调之间的关系


首先,http.createServer 创建的是一个请求处理函数

javascript 复制代码
const server = http.createServer((req, res) => {
  // 请求处理函数(Request Handler)
});

其中

  • 返回值 :一个 http.Server 实例(server.listen 可监听端口)
  • 参数 (req, res) => {...} :本质也是个回调函数(就像 https.request 创建的接收回调一样),Node.js 称之为请求监听器(request listener)

每当有客户端(OpenCode)发起 HTTP 请求到本地代理时,Node.js 就会自动调用这个函数,简单来说,createServer 创建的是当有用户访问时,要做什么的逻辑

然后是触发条件,只有当外部客户端,比如 OpenCode,浏览器,curl 命令向本地代理的 Node.js 服务器发起 HTTP 请求时,才会触发 ,举个例子

  • 运行服务器:server.listen(2048)
  • OpenCode 客户端发送请求:POST http://localhost:2048/v1/chat/completions
  • Node.js 收到 TCP 连接,解析 HTTP 请求
  • 自动调用 createServer 定义的请求处理函数 (req, res) => {...},其中 req 为 OpenCode 发来的请求对象(包含 method,url,headers,body 等),res 为要写回给 OpenCode 的响应对象

关键点:(req, res) => {...} 只被入站请求触发,链路如下

然后是目标服务器 DashScope 的响应,接收 DashScope 的响应和 createServer 就没关系了,也不会触发 (req, res) => {...},而是触发 https.request 定义的接收回调函数 (proxyRes) => {...},所以总结下这两个事件如下

  • OpenCode 客户端:负责发送请求,处理函数为 http.createServer 创建的 (req, res) => {...},由 Node.js 调用,触发时机为收到外部 HTTP 请求
  • DashScope 目标服务器:负责返回响应,处理函数为 https.request 创建的 (proxyRes) => {...},同样由 Node.js 调用,触发时机为收到上游服务器的 HTTPS 响应

其数据流向如下

可以看到,这两个回调是独立的,一个是主动请求后结果处理,本地代理去找目标服务器,另一个则是被动接收,目标服务器来找本地代理

另外,每个请求都有独立的作用域和生命周期,即使同时有 100 个 OpenCode 请求,每个请求都会有自己的 (req, res) 和自己的 https.request,Node.js 通过闭包和事件循环确保数据彼此之间互不串扰

javascript 复制代码
http.createServer((req_from_opencode, res_to_opencode) => {
  // 这个作用域只属于 OpenCode 的这一次请求

  const proxyReq = https.request(dashscope_options, (res_from_dashscope) => {
    // 这个回调属于此次向 DashScope 发起的请求后的响应
    // 但它能访问外层的 res_to_opencode(闭包!)
    res_to_opencode.writeHead(res_from_dashscope.statusCode, ...);
    res_from_dashscope.pipe(res_to_opencode);
  });

  proxyReq.end(body);
});

OK,本篇先到这里,如有疑问,欢迎评论区留言讨论,祝各位功力大涨,技术更上一层楼!!!更多内容见下篇 blog
【Agent】【OpenCode】本地代理增强(日志记录)

相关推荐
不懂的浪漫5 分钟前
把 AI Skill 做成系统:路由、领域技能、自我复盘和进化飞轮
人工智能·ai·skill
等风来不如迎风去12 分钟前
【win11】最佳性能:fix 没有壁纸,一直黑屏
网络·人工智能
云云只是个程序马喽15 分钟前
AI漫剧创作系统开发定制指南
人工智能·小程序·php
Elastic 中国社区官方博客34 分钟前
Elastic 和 Cursor 合作 加速 上下文工程 与 coding agents
大数据·人工智能·elasticsearch·搜索引擎·全文检索
迦南的迦 亚索的索36 分钟前
AI_12_Dify_平台介绍
人工智能
HIT_Weston39 分钟前
68、【Agent】【OpenCode】用户对话提示词(任务执行流程)
人工智能·agent·opencode
ting94520001 小时前
Micro1 超详细深度解析:架构原理、部署实战、性能评测与落地应用全指南
人工智能·架构
冰西瓜6001 小时前
深度学习的数学原理(三十三)—— Transformer编码器完整实现
人工智能·深度学习·transformer
科研前沿1 小时前
镜像孪生VS视频孪生核心技术产品核心优势
大数据·人工智能·算法·重构·空间计算
DreamBoy@1 小时前
Mnemra:一键剪藏,让灵感真正可复用(一键从Ai对话页面到飞书云文档,浏览器插件方便好用)
人工智能