44、【Agent】【OpenCode】本地代理分析(效果呈现)
【声明】本博客所有内容均为个人业余时间创作所述技术案例均来自公开开源项目如GithubApache基金会不涉及任何企业机密或未公开技术如有侵权请联系删除背景上篇 blog【Agent】【OpenCode】本地代理分析异步闭包机制提到了一个关键点代理收到 Open构建了请求对象然后发送请求内容后代理就 return 退出了解释了这里虽然https.request本身同步返回请求对象但整个 IO 是异步的涉及到 JavaScript 异步 闭包 流式处理中的核心机制proxyReq.end只是发出请求并不代表请求完成Node.js 的事件循环模块会持续监听网络事件当目标服务器 DashScope 返回响应头时Node.js 会自动调用回调函数(proxyRes) {...}即使外层函数已经 return回调依然能安全访问 res 等变量这就是闭包Closure在起作用而proxyRes是由系统在回调触发时新创建的对象下面继续分析OpenCode再解释下这里的接收回调函数首先是入参proxyRes这不是用户自定义的局部变量而是 Node.js 在触发接收回调时动态创建的参数每次收到一个响应系统都会新建一个proxyRes对象传进来也就是说这个对象在接收回调开始时才被定义生成另外是内存安全的问题之前提到过在运行时JavaScript 的引擎会发现内部接收回调函数使用到了外部的变量res于是引擎会保留对res变量的引用即使外层函数OpenCode 客户端对目标服务器的请求返回结束只要还有回调函数指的是这里的接收回调函数可能用到它res变量就不会被垃圾回收这是 JavaScript 闭包的标准行为在这里res客户端响应对象的生命周期由 Node.js 管理一旦proxyRes.pipe(res)完成之前说过pipe会自动end或出错所有引用会自然解除另外当 HTTP 连接关闭时res也会被自动清理所以也不会出现内存泄漏最后总结下这里本地代理的关键点客户端 OpenCode 的请求函数 return 返回后其定义的接收回调函数还能正常运行Node.js 的事件循环模块会触发这个接收 callback 的调用客户端 OpenCode 的请求函数 return 返回后其入参res变量还会继续存在由闭包机制保持引用以便接收回调函数实现透传proxyRes是接收 callback 被调用时新建的不是用户自定义的变量没有内存泄漏问题Node.js 会自动管理 HTTPS 连接的生命周期这也是 Node.js 流式代理的标准做法正是这种非阻塞式事件驱动的模型可以让 Node.s 能够高效处理成千上万的并发 AI 请求再贴一次本地代理的实现// dashscope-proxy.jsconsthttprequire(http);consthttpsrequire(https);constserverhttp.createServer((req,res){console.log( Received${req.method}${req.url});if(req.methodPOSTreq.url/v1/chat/completions){letbody;req.on(data,chunkbodychunk);req.on(end,(){// 从原始请求中获取 Authorization 头constauthHeaderreq.headers[authorization]||;constoptions{hostname:dashscope.aliyuncs.com,port:443,path:/compatible-mode/v1/chat/completions,method:POST,headers:{Authorization:authHeader,// 直接透传Content-Type:application/json,Content-Length:Buffer.byteLength(body)}};constproxyReqhttps.request(options,(proxyRes){res.writeHead(proxyRes.statusCode,proxyRes.headers);proxyRes.pipe(res);// 自动处理流式/非流式 自动 end()});proxyReq.on(error,(e){console.error(Proxy error:,e.message);res.writeHead(502);res.end(Bad Gateway);});proxyReq.write(body);proxyReq.end();});return;}res.writeHead(404);res.end(Not Found);});server.listen(2048,127.0.0.1,(){console.log(✅ DashScope proxy with full OpenCode Ollama compatibility running on http://127.0.0.1:2048);});OK本地代理分析完后把项目里opencode.json的api参数改一下改成创建的本地代理 URL这里设置的是2048端口号接着在终端输入nodedashscope-proxy.js启动代理程序可以看到端口已被代理程序占用新建另一个终端打开 OpenCode输入你是哪个模型可以看到 OpenCode 客户端的响应同时本地代理进行了两次请求的转发至于这里为什么会有两次请求后面 blog 会进行分析OK本篇先到这里如有疑问欢迎评论区留言讨论祝各位功力大涨技术更上一层楼更多内容见下篇 blog【Agent】【OpenCode】本地代理分析请求接收回调