十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Effect 平台 Deno 套接字服务端升级:统一 node-shared 实现、新增 reader 级 TLS 升级支持与迁移指南

Effect 平台 Deno 套接字服务端升级:统一 node-shared 实现、新增 reader 级 TLS 升级支持与迁移指南 Effect 平台 Deno 套接字服务端升级统一 node-shared 实现、新增 reader 级 TLS 升级支持与迁移指南【免费下载链接】effectBuild production-ready applications in TypeScript项目地址: https://gitcode.com/GitHub_Trending/ef/effect导读本篇基于 Effect 生态仓库中的变更说明changeset文件讲解effect/platform-deno在最新迭代中对DenoSocketServer的底层实现调整它不再使用 Deno 原生实现而是复用effect/platform-node-shared的 Node 套接字服务端从而让被接受的 TCP 连接支持以 reader 作用域reader-scoped为粒度的服务端 TLS 升级。你将掌握新的make/layer参数形态host替代hostname、{ path }替代{ transport: unix, path }、Deno 版本要求2.8.3 及以上以及本次变更在源码层面的实现原理与实测用例验证。一、变更概览一次针对 Deno 套接字服务端的底层重构该变更说明.changeset/pre/eff-972-deno-socket-server.md同时涉及两个包均以patch级别发布包名变更级别说明effect/platform-denopatch套接字服务端实现切换到 node-shared 版本effect/platform-node-sharedpatch底层能力被 Deno 平台复用并承载 reader 作用域的 TLS 升级逻辑核心结论一句话Deno 平台现在使用 node-shared 的套接字服务端因此被接受的 TCP 连接能够支持以 reader 作用域为单位的服务端 TLS 升级即先以明文 TCP 接受连接、在读取阶段按需升级为 TLS 的 STARTTLS 式能力。从源码结构可以直接看到这一结论Deno 平台的套接字服务端模块 packages/platform/deno/src/DenoSocketServer.ts 全文只有一行导出语句export * from effect/platform-node-shared/NodeSocketServer也就是说DenoSocketServer现在等价于 node-shared 的NodeSocketServer命名空间其make、layer、makeTls、layerTls、makeWebSocket、layerWebSocket等构造器与 Layer 全部来自后者。包级入口 packages/platform/deno/src/index.ts 中DenoSocketServer子模块的导出保持不变export * as DenoSocketServer from ./DenoSocketServer.ts因此对外 API 命名不受影响。二、为什么这样做reader 作用域的 TLS 升级2.1 变更动机变更说明原文明确指出动机Use the node-shared socket server on Deno so accepted TCP connections support reader-scoped server TLS upgrades.即让 Deno 上被接受accepted的 TCP 连接具备 reader 作用域的服务端 TLS 升级能力。从源码实现看这一能力由Socket.Reader上的upgrade操作承载。在 packages/platform/node-shared/src/NodeSocket.ts 的fromDuplex中reader返回{ pull, upgrade }两个成员其中upgrade允许在读取阶段将底层连接升级为 TLS服务端场景tlsServer: true下fromDuplex使用secure事件作为升级完成标志客户端场景使用secureConnect参见 NodeSocket.ts 的const secureEvent isServer ? secure : secureConnect服务端升级要求同时提供key与cert否则以SocketUpgradeError失败升级完成后会通过Tls.TLSSocket包装原始连接并继续透传读写参见 NodeSocket.ts 的upgrade实现。这正是“reader 作用域”的含义升级动作不是发生在接受连接时而是在 handler 获取 reader 之后、按需触发每次连接的升级状态upgradeAvailable也由 reader 的 scope 生命周期管理scope 结束即失效。2.2 升级语义细节Node 实现在 NodeSocket.ts 中升级前会做参数校验服务端场景必须同时提供key与cert否则报错 server TLS upgrade requires both key and cert客户端场景同样要求key与cert成对出现可选参数包括ca、passphrase、alpnProtocols、requestCert、rejectUnauthorized其中key与passphrase使用Redacted类型承载避免密钥以明文形式直接暴露。值得注意的是Deno 平台的客户端升级走的是Deno.startTls见 DenoSocket.ts 的fromConn它不支持客户端证书因此key、cert、passphrase、requestCert在 Deno 客户端升级中不生效且rejectUnauthorized: false仅关闭主机名校验、证书链校验仍然生效。本次变更解决的是服务端一侧让 Deno 服务端通过 node-shared 实现获得完整的、与 Node 一致的服务端 TLS 升级能力。三、Breaking Changes 与迁移指南变更说明列出的破坏性变更集中于DenoSocketServer.make与DenoSocketServer.layer的参数形态以及运行时版本要求。下面逐一给出新旧对比与迁移方法。3.1 TCP 监听hostname→host变更前Deno 原生参数DenoSocketServer.make({ hostname: 127.0.0.1, port: 8080 })变更后Node listen 选项即node:net的Net.ServerOpts Net.ListenOptionsDenoSocketServer.make({ host: 127.0.0.1, port: 8080 })layer的用法同步变化DenoSocketServer.layer({ host: 127.0.0.1, port: 8080 })从源码看make与layer的类型签名已切换为options: Net.ServerOpts Net.ListenOptionsNodeSocketServer.ts这正是 Nodenet.Server.listen的选项集合因此支持host、port、backlog、exclusive、ipv6Only、reusePort等 Node 标准监听选项。3.2 Unix 套接字{ transport: unix, path }→{ path }变更前DenoSocketServer.make({ transport: unix, path: /tmp/echo.sock })变更后DenoSocketServer.make({ path: /tmp/echo.sock })layer同理DenoSocketServer.layer({ path: /tmp/echo.sock })在 node-shared 实现中服务端监听后会把绑定的地址归一化为NetAddress.SocketAddress字符串形式的server.address()映射为UnixPathAddressAddressInfo对象映射为InetAddressV4/InetAddressV6见 NodeSocketServer.ts 的socketAddressFromNode。因此你可以通过server.address拿到标准化的NetAddress结果测试中即以此断言地址类型与端口。3.3 运行时要求Deno 2.8.3 及以上变更说明明确Deno 2.8.3 或更新版本为必需条件。原因是 node-shared 套接字服务端依赖 Deno 的node:net/node:tls兼容层。源码中对此有专门适配NodeSocketServer.ts 通过const isDeno Deno in globalThis检测运行环境在 Deno 下不显式调用conn.pause()因为 Deno 的node:net兼容层在显式 pause 之后会破坏readable事件分发见 NodeSocketServer.ts 与 NodeSocket.ts 的注释说明。这意味着升级到该版本前请确认部署环境的 Deno 版本不低于 2.8.3否则可能出现兼容层行为异常。四、源码级解析node-shared 服务端如何工作理解本次变更建议通读 packages/platform/node-shared/src/NodeSocketServer.ts。该模块把node:net的 TCP/Unix 服务端、node:tls的 TLS 服务端以及ws的 WebSocket 服务端统一封装为 scoped 的SocketServer.SocketServer服务核心是内部函数makeNetServerNodeSocketServer.ts创建并监听createServer()创建底层 server随后server.listen(listenOptions)并通过DeferredraceFirst将监听错误如端口占用转化为SocketServerError挂起连接在run被调用之前所有到达的连接被记录在pendingMap 中并保持暂停避免数据丢失按需接管run(handler)被调用时把之前的 pending 连接逐一交给新的onConnection回调用Fiber.runIn(scope)将每个连接的 handler 织入独立 Fiber并在 handler 结束时关闭 scope作用域清理服务端作为Effect.acquireRelease资源scope 结束时销毁所有 pending 连接并关闭底层 serverNodeSocketServer.ts。每个被接受的连接会通过NodeSocket.fromDuplex(..., { tlsServer: true })包装为Socket.Socket同时以Context提供NodeSocket.NetSocket服务标签让 handler 能访问底层 Nodenet.SocketNodeSocketServer.ts。TLS 服务端则使用makeTls/layerTls监听secureConnection事件握手失败的连接被直接销毁、服务端继续监听NodeSocketServer.ts。五、迁移后的正确用法附测试用例佐证仓库测试 packages/platform/deno/test/DenoSocketServer.test.ts 完整演示了迁移后的 API 形态可直接作为迁移参考。5.1 TCP echo 服务端import * as DenoSocketServer from effect/platform-deno/DenoSocketServer const server yield* DenoSocketServer.make({ host: 127.0.0.1, port: 0 }) const address server.address // address._tag InetAddressV4 yield* server.run(echo).pipe(Effect.forkScoped)注意port: 0表示由系统分配空闲端口实际端口可通过server.address获取测试断言address.port不为 0。客户端连接使用DenoSocket.makeTcp({ hostname, port })注意客户端连接参数仍是hostname只有服务端监听参数改为host两者不要混淆。5.2 Unix 套接字 echo 服务端const server yield* DenoSocketServer.make({ path: /tmp/echo.sock }) // server.address._tag UnixPathAddress yield* server.run(echo).pipe(Effect.forkScoped) // 客户端连接保持原有形态 const socket yield* DenoSocket.makeTcp({ transport: unix, path })5.3 服务端 TLS 升级本次变更的核心能力测试用例 upgrades a plain server connection to TLSDenoSocketServer.test.ts演示了如何在 handler 中对普通 TCP 连接按需升级为 TLSconst server yield* DenoSocketServer.make({ host: 127.0.0.1, port: 0 }) yield* server.run((socket) echo(socket, { cert, key: Redacted.make(key) // 密钥以 Redacted 承载 }) ).pipe(Effect.forkScoped) // 客户端同样在 reader 阶段升级并传入 CA 信任锚 const socket yield* DenoSocket.makeTcp({ hostname, port }) const output yield* sendHelloDeno(socket, { ca: [ca] })其中服务端 handler 的核心逻辑为const { pull, upgrade } yield* socket.reader if (upgradeOptions ! undefined) { yield* upgrade(upgradeOptions) // 读取阶段按需升级 TLS }这正是“reader 作用域的 TLS 升级”服务端以明文 TCP 接受连接handler 在 reader 阶段调用upgrade完成STARTTLS式升级之后读写都走 TLS 通道。测试使用仓库内置的测试证书packages/platform/deno/test/fixtures/tls/ 下的ca.pem、cert.pem、key.pem断言升级后仍能正确完成 echo 往返。5.4 资源关闭语义测试 closes with a pending pre-run connectionDenoSocketServer.test.ts验证了在run尚未被调用时关闭服务端 scope挂起的连接也会被正确清理且关闭过程在 1 秒内完成。这印证了makeNetServer中 finalizer 对 pending 连接的销毁逻辑。六、真实使用场景Effect Cluster 在 Deno 上的套接字服务端该变更并非孤立存在——DenoSocketServer正是 Effect Cluster 在 Deno 平台上的套接字传输底座。packages/platform/deno/src/DenoClusterSocket.ts 中的layerSocketServer直接使用迁移后的DenoSocketServer.layerreturn DenoSocketServer.layer({ host: listenAddress.value.host, port: listenAddress.value.port })其监听地址取自ShardingConfig.runnerListenAddress回退到runnerAddress。这意味着本次参数迁移会同步影响Deno 平台上 Cluster runner 的套接字监听配置——在 Deno 2.8.3 下Cluster 套接字服务端同样获得 reader 作用域 TLS 升级能力为跨节点加密通信例如在不可信网络上运行的 runner 间传输提供了按连接粒度开启 TLS 的手段。七、迁移清单与注意事项升级前请对照以下清单完成迁移升级 Deno 运行时到 2.8.3 或更新版本搜索代码中DenoSocketServer.make/DenoSocketServer.layer的所有调用点将 TCP 监听的hostname参数改为host将 Unix 监听的{ transport: unix, path }对象改为{ path }确认客户端连接 APIDenoSocket.makeTcp参数不变仍为{ hostname, port }或{ transport: unix, path }如需服务端 TLS 升级在 handler 的 reader 阶段调用upgrade({ key, cert })其中key使用Redacted.make包装key与cert必须成对提供若代码中依赖server.address注意其类型已归一化为NetAddress.SocketAddressTCP 为InetAddressV4/InetAddressV6Unix 为UnixPathAddress读取 IP 使用NetAddress.formatIp读取 Unix 路径使用.path回归验证 Cluster 场景如适用layerSocketServer的监听参数已随迁移改变确认ShardingConfig中的监听地址配置与新的host参数语义一致。结语本次effect/platform-deno的 patch 变更通过将DenoSocketServer收敛到effect/platform-node-shared的 Node 实现为 Deno 平台补齐了 reader 作用域的服务端 TLS 升级能力同时带来两处明确的破坏性参数变更与一个版本门槛。源码与测试均已同步更新DenoSocketServer.ts、NodeSocketServer.ts、DenoSocketServer.test.ts按上文清单迁移即可平滑升级并在 Deno 上获得与 Node 一致、按连接粒度可控的 TLS 套接字服务能力。【免费下载链接】effectBuild production-ready applications in TypeScript项目地址: https://gitcode.com/GitHub_Trending/ef/effect创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表