新闻详情

新闻详情

首页 / 资讯中心 / 详情

Python自研内网穿透工具:从反向隧道到多路复用

发布时间:2026/10/1 1:14:02来源:尧图网络
Python自研内网穿透工具:从反向隧道到多路复用
内网穿透这个需求圈内人基本都绕不过去。前几天我在客户现场调试一个本地的Web服务入口就一个普通家庭宽带路由器没有公网IPv4IPv6也不稳定客户那边电脑在另一个城市我只能先在本地把服务跑起来再用一个小工具把服务“送”出去给客户临时访问。整个过程下来我发现这件事比想象中更能考验网络基本功而且市面上的现成工具要么免费版限制太多要么配置起来跟它的名字一样复杂。于是我又把之前写的一个基于Python的内网穿透小工具翻出来重新整理了一轮今天就把这个工具的设计思路、核心代码和实测结果完整写出来。这个工具叫proxynt本质上是一个用Python实现的内网穿透转发器解决的就是“没有公网IP也能让外部访问到内网服务”这回事。本文适合下面几类人手里有NAS、开发板、本地数据库想从外部安全访问的在公司内网调接口但需要给外部演示的以及想搞懂ngrok、frp这类工具底层到底怎么工作的。我会把隧道建立、流量转发、断线重连、安全加固这些关键点都拆开讲明白。1. 为什么非要自己写一个内网穿透从一次远程联调说起1.1 没有公网IP时的访问困境很多刚接触网络的人会有一个直觉只要知道目标机器的IP地址就能直接连上去。但在真实网络环境里这个直觉基本不成立。家庭宽带和绝大部分企业内网都部署了NATNAT设备会把内网的一堆私有IP映射到唯一的公网IP上而且默认只允许由内网主动发起的连接回来外部主动发起的新连接会在NAT设备上被直接丢掉。你就算知道了家里的公网IP也没法直接访问到内网里那台跑着服务的电脑。IPv4地址空间早就耗尽运营商现在基本不分配公网IPv4给普通宽带用户这就是最现实的困境。我自己家里的宽带一开始申请的时候还问过客服要公网IP那边的答复是“动态公网IP需要额外申请而且不一定有资源”。IPv6看起来是出路但很多地方的IPv6是半残状态部分网络环境仍然不通加上一些老旧设备根本不支持IPv6光这一项就能卡掉一半场景。在没有公网IP这个前提下要让外部访问到内网服务本质上只有一条路让内网机器主动向一台“有公网IP的机器”建立连接然后借助这台公网机器做流量中转。这就是内网穿透最核心的思路也是ngrok、frp这类工具能解决问题的根本原因。1.2 市面上的工具为什么不能完全满足我在决定写proxynt之前我其实认真用过几款主流的穿透工具这里做一个客观对比给大家一个参考。工具上手难度免费版限制协议自定义能力适合场景ngrok很低域名随机、连接数限制、带宽限制弱主要走它的官方服务快速演示、临时暴露Web服务frp中等无但需要自己准备公网服务器强配置项很细自建隧道、生产环境长期使用樱花内网穿透很低依赖它的客户端和服务器免费线路会排队一般玩游戏联机、临时共享proxynt中等无代码全在自己手里强协议自己想怎么改就怎么改学习原理、定制需求、轻量部署ngrok确实方便几行命令就能把localhost暴露出去可它免费版的随机域名每次都在变我做接口联调的时候客户那边需要频繁改配置很不友好。按域名收费的话个人项目长期用又有点不划算。frp功能非常强性能也很好但它更像一个“全家桶”配置项多到一定程度之后对只想快速开一个隧道的人来说反而是一种负担。樱花这类平台化服务核心数据都要经过第三方服务器放在自己家里的敏感服务心里总觉得不踏实。这些痛点叠加在一起促成了我自己写一个。市面上工具功能当然更全面但写proxynt的目的不是要“超越frp”而是想掌握每一行代码背后在做什么顺便满足一些自定义协议的需求。比如我需要在一个隧道里同时转发多个端口并且能自己控制客户端注册、心跳、最大连接数等逻辑这些在自研代码里都能轻量实现。1.3 proxynt的定位轻量、可读、能改造proxynt的设计目标从头到尾就三个词轻量、可读、能改造。它不会像frp那样提供几十个控制项而是只保留穿透最核心的部分公网服务端监听、内网客户端注册、隧道建立、流量多点转发、心跳与断线重连。整个代码量控制在合理范围读懂核心模块之后你可以很方便地给它增加新的能力比如多用户认证、域名分流、流量统计等。用Python写这个工具主要是看中了它的跨平台能力和快速开发的优势在Windows和Linux上都能直接跑。对性能要求不是极端的场景来说Python的socket编程完全能扛住尤其是开发调试、数据库远程管理、Web服务临时暴露这一类需求瓶颈更多在带宽和延迟而不是语言本身的效率。2. proxynt的架构拆解反向隧道、流量分发与协议设计2.1 三个角色公网Server、内网Client、本地Targetproxynt的运行模型可以用一句话概括内网客户端主动连公网服务端公网服务端再把外部“访客”的流量通过已经建立的隧道转发给内网客户端最后由内网客户端交给本地目标服务。整个过程涉及三个角色。公网Server中转节点部署在一台有公网IP的服务器上承担两个任务一是等访客连接二是维护与内网Client的隧道连接。内网Client隧道发起端运行在内网机器上主动向公网Server发起连接并在注册成功后等待数据。本地Target真正提供服务的一方可以是一个Flask应用、SSH服务、数据库端口也可以是路由器后台。用一个简单的拓扑图来说明访客机器 -- 公网Server(有公网IP) --隧道主动连接-- 内网Client -- 本地Target(例如:127.0.0.1:8000)访客机器访问的是公网Server的某个端口但数据流能一路延伸到内网里的目标服务就是因为中间那条“内网Client主动发起的隧道”在起作用。2.2 为什么选反向连接而不是端口映射“反向连接”这个词听起来有点绕其实就是让处于NAT后面的客户端主动往公网服务器连。为什么要这样做因为NAT设备只认“内网主动发起”的会话。如果公网服务器想直接连接内网机器数据包到达NAT设备时会被拦下来因为NAT翻译表里没有对应的记录。反向连接的好处是内网Client一次性把隧道搭好之后所有通信都复用这个已经存在的连接不需要在路由器上做任何配置也不需要提前申请公网IP只要内网Client能访问到公网服务器即可。这里唯一的前提是内网Client能访问外网这在绝大多数网络环境里都是满足的。2.3 协议边界设计一条隧道承载多路数据刚开始写proxynt的时候我犯过一个错误为了省事每来一个访客连接就新建一条内网Client到公网Server的连接。这种方案代码好写但问题也很明显公网Server维护的连接数会随着访客量线性增长内网Client如果暴露了好几个端口就要建立好多条隧道连接资源浪费非常严重。所以我重新设计了proxynt的协议边界让一条隧道连接承载多路数据。每一路数据都打上独立的连接ID放在自定义的Frame里。这个Frame就是proxynt通信的基本单位格式可以理解为[固定包头 | 类型 | 连接ID | 数据长度 | 数据负载]类型字段区分这是控制消息注册、心跳、关闭连接还是数据消息真正的业务流量。连接ID标识这一路数据属于哪个访客连接这样在一条物理隧道上就能并发跑多个连接。数据长度用于解决TCP流式传输中的粘包半包问题。这个设计和HTTP/2的多路复用思路有些相似都是把原本需要多个连接的场景压缩到一个连接上提升链路利用效率也简化了公网Server的监听逻辑。2.4 心跳与断线重连隧道不稳定的生存底线内网穿透场景里网络断线是常态。出租屋的WiFi不稳定、公司网络半夜会回收空闲连接、云服务器偶尔主动断开长时间没有流量的连接这些都是我实际遇到过的。如果隧道断了而两端的程序不知道数据就会卡死访客看到的现象就是“页面一直转圈永远打不开”。proxynt的处理方式是双向心跳。内网Client每30秒向公网Server发送一个Ping控制帧公网Server收到后回一个Pong帧。如果公网Server在90秒内没有收到内网Client的任何数据就认为隧道已死清理掉对应的连接状态内网Client如果在90秒内没有收到任何来自服务端的响应或者心跳就会主动断开并重新发起连接。这个“30秒心跳、90秒超时”的经验值来自实际踩坑。太频繁的心跳会白白占用带宽尤其对移动网络不友好太长的超时会让用户在断线后等待太久。如果你部署的环境网络更差可以把超时下调到45秒代价是偶尔会误判慢网络为断线。3. Python实现细节从socket转发到多路复用3.1 环境准备版本选择与一个干净的运行环境proxynt基于Python 3.8及以上版本测试主要用到了socket、threading、struct、json这些标准库没有引入任何第三方网络库。建议不要用系统自带的Python环境直接跑项目而是用venv隔离一个干净的环境避免后续装别的包时把隧道服务的依赖搞乱。如果你之前还没装过Python这里提供一个简单的环境准备流程。# Debian/Ubuntu系 sudo apt update sudo apt install python3 python3-venv python3-pip # 创建并激活虚拟环境 python3 -m venv proxynt-venv source proxynt-venv/bin/activate # 验证版本 python --versionWindows上的操作类似安装Python之后在项目目录执行python -m venv proxynt-venv然后进入proxynt-venv\Scripts\activate激活环境。这样管理器在哪台机器上跑都可以保证基础依赖是一致的。3.2 服务端核心逻辑监听、映射表、数据泵公网Server要干的活可以拆成几个明确的循环监听两个端口的连接一个端口面向内网Client我用--client-port标记一个端口面向访客我用--visitor-port标记。维护一张client_connection引用记录当前活跃的内网隧道。当访客连接到达时从隧道中分配一个新的连接ID然后启动两条转发线程把访客的数据通过隧道发给内网Client同时把内网Client回传的数据写给访客。核心代码大致长这样省略异常处理和日志后# 伪代码体现结构 def handle_visitor(visitor_sock, tunnel_sock, conn_id): # 数据泵访客 - 隧道 - 内网Client def pump_to_client(): while True: data visitor_sock.recv(4096) if not data: break frame pack_data_frame(conn_id, data) tunnel_sock.sendall(frame) send_close_frame(tunnel_sock, conn_id) visitor_sock.close() # 数据泵内网Client - 隧道 - 访客 def pump_to_visitor(data_buffer): if data_buffer.conn_id conn_id: visitor_sock.sendall(data_buffer.payload) t threading.Thread(targetpump_to_client) t.start()服务端之所以用“一连接一线程”的方式是因为访客连接量级通常不大。每个访客连接占用两个线程对prototype级别的项目完全够用。如果后续要支持上千并发再改成asyncio事件循环也不迟接口可以保持不动只换内部实现。3.3 客户端注册、隧道建立与双向数据流转客户端这边的逻辑要相对主动一些。它启动后先读取自己的配置公网Server地址、认证Token、要暴露的本地端口列表。然后做两件事。第一件事是建立隧道长连接。客户端连接公网Server的client-port发送一个注册包注册包里包含协议版本、Token、需要暴露的端口列表。服务端校验通过后隧道就进入ready状态之后所有数据帧都从这个连接上收发。第二件事是等待服务端指令。当服务端收到一条DATA数据帧时会解析出连接ID和对应的目标端口客户端这边用这个连接ID在本机发起对127.0.0.1:目标端口的连接然后建立双向转发。# 伪代码客户端处理数据帧 def on_data_frame(frame): target_port port_map.get(frame.conn_id) if target_port is None: return target_sock socket.create_connection((127.0.0.1, target_port)) # 把 frame.payload 写入目标服务 target_sock.sendall(frame.payload) # 目标服务的响应再封装成数据帧发回隧道 def read_and_send(): while True: data target_sock.recv(4096) if not data: break frame pack_data_frame(frame.conn_id, data) tunnel_sock.sendall(frame) threading.Thread(targetread_and_send, daemonTrue).start()这里有一个很容易踩的坑内网Client访问本地Target的时候一定要用127.0.0.1而不是局域网IP或者localhost。有些系统上localhost会优先解析成IPv6的::1而服务只监听了IPv4的127.0.0.1导致连接建立失败这个坑在Windows上尤其常见。3.4 Frame编解码如何解决粘包、半包的问题TCP是流协议没有消息边界。如果你连续sendall两帧数据接收方可能一次recv就把两帧都读到了这叫作粘包反过来如果你发送的数据很大接收方可能分好几次recv才读到完整的一帧这叫作半包。处理方式业界通用就是在应用层定义好自己的协议边界。proxynt的Frame头是12字节的固定长度定义如下import struct # 帧头格式类型1字节连接ID 4字节数据长度4字节保留3字节 HEADER_STRUCT struct.Struct(!B I I 3s) def pack_frame(frame_type, conn_id, payloadb): header HEADER_STRUCT.pack(frame_type, conn_id, len(payload), b\0\0\0) return header payload def read_frame(sock): header_data recv_exact(sock, HEADER_STRUCT.size) if header_data is None: return None frame_type, conn_id, length, _ HEADER_STRUCT.unpack(header_data) payload recv_exact(sock, length) return frame_type, conn_id, payloadrecv_exact这个功能很关键它必须循环接收直到收满指定的字节数再返回否则就会因为一次recv不到完整数据而出错。所有接收方最好不要直接调用recv来拼Frame而是统一用recv_exact封装这样在代码层面一次性地消灭掉半包问题。3.5 线程与I/O模型什么时候该换 asyncioproxynt目前用的是多线程模型每个活跃连接分配独立的转发线程。这样做的好处是实现直观代码容易读也方便调试。缺点则是线程数量会随着连接数线性增长量级到几千时会有明显的上下文切换开销。如果你的场景是“一台服务器同时服务几十上百个访客”多线程完全没问题。但如果你打算用它做高并发的生产网关建议把核心数据泵部分改成asyncio或selector事件循环。需要提醒的是改造时不要动Frame协议和连接注册逻辑只替换底层的I/O调度方式这样风险会小很多。我在本地测试中用selectors改造过一版数据泵在1000个并发连接下CPU占用比多线程版低了约40%但代码复杂度也同步上升。4. 部署和实测proxynt在不同网络环境下的表现4.1 一次最小可运行演示从云主机访问本地Flask为了验证proxynt的完整流程我在一台轻量云主机上部署了公网Server在一台家庭内网电脑上部署了客户端目标是暴露本地一个Flask服务。整个启动流程如下。先在云主机上启动公网Serverpython server.py --listen-port 9000 --client-port 9001 \ --token YourToken123 --log-level info参数含义listen-port 9000是访客要连接的端口client-port 9001接受内网Client注册token用于认证。然后在家庭电脑上启动客户端python client.py --server your-server.com:9001 \ --token YourToken123 \ --expose 8000:127.0.0.1:8000--expose参数表示把公网Server的9000端口对应到本地127.0.0.1:8000的Flask服务上。启动之后外部访客直接访问http://your-server.com:9000就能看到家里那台机器上Flask返回的页面。实际测试中关键是先确认两个服务之间能通。如果云主机上开了防火墙一定要放行9000和9001这两个TCP端口否则后面的调试会很被动。4.2 压测结果延迟、吞吐量、空闲连接我拿一个小型Flask接口做了AB测试和手动压测对比无隧道直连和通过proxynt隧道的差异。结果如下场景平均延迟吞吐量备注本机直连Flask0.4ms约5000 req/s纯本机回环内网机器直连Flask1.2ms约4200 req/s局域网内通过proxynt隧道访问28ms约800 req/s家庭宽带上行受限通过proxynt隧道访问云主机带宽充足9ms约2400 req/s瓶颈在家庭宽带上行延迟增加主要是两个原因一是数据多走了一条公网服务器的中转路径多了一次WAN往返二是家庭宽带的上行带宽通常很小导致吞吐量上不去。如果你的内网穿透主要用来访问大文件或者跑内部网站建议优先关注本地上行带宽这往往比服务器和代码优化更影响最终体验。4.3 断线重连实测直接拔网线后发生了什么断线重连是穿透工具最容易被忽视又最重要的能力。我在测试时直接把内网客户端的网线拔掉观察云主机上的日志。日志显示服务端在约30秒后没有收到心跳再过90秒超时标记隧道失效。之后插回网线客户端在启动重连逻辑后重新建立隧道整个过程大概耗时3到10秒。这里有一个经验云主机对空闲TCP连接有回应当策略可能在一段时间没有流量后主动断开连接但两端程序不一定能立刻感知。这就要求心跳间隔不能太长。proxynt默认30秒心跳能有效减少这类被中间设备悄悄断开的情况。你部署到生产环境后建议专门观察一下把心跳间隔调整到适合你自己网络的程度。4.4 跨平台踩坑Windows、Linux、macOS的差异我在Windows和Linux上都运行过proxynt发现几个容易被忽略的点。第一个是防火墙。Windows第一次运行Python进程时会弹窗询问是否允许网络通信如果没点允许访客流量就无法进入。Linux上则要注意云主机的安全组和本地iptables规则。第二个是socket的SIGPIPE问题。Linux下往一个已经关闭的socket写数据默认会导致进程收到SIGPIPE信号从而退出必须在代码里设置signal.signal(signal.SIGPIPE, signal.SIG_IGN)忽略掉或者捕获异常。Windows平台没有这个信号所以这段逻辑只对类Unix系统有意义。第三个是全双工关闭的问题。socket.close()会直接关闭整个socket如果有两个线程同时在读和写一个线程关闭后另一个线程可能还会往已关闭的句柄上写数据。更稳妥的做法是调用shutdown(socket.SHUT_RDWR)后再close()确保读写两端都被正确终止。5. 安全性设计内网穿透最容易忽略的护栏5.1 Token认证只是及格线不是安全万能药proxynt的认证机制是Token。客户端向服务端发起注册时在控制帧里带上Token服务端校验通过后才把隧道状态置为ready。这个机制能挡住“不知道Token”的随机连接但它有几个前提Token本身不能太短传输过程不能明文暴露服务端要有一定的暴力破解防护。建议生成Token时直接用一个较长的随机字符串比如python -c import secrets; print(secrets.token_urlsafe(32))像123456、password这类弱Token在公网上就是裸奔几秒钟就能被扫描器尝试出来。另外服务端对同一IP的连接失败次数做限制连续失败5次就ban掉一段时间能有效降低被爆破的风险。5.2 数据加密TLS封装必不可少默认情况下proxynt的Frame是明文传输的。如果你穿透的是重要服务建议在前面加一层TLS加密。Python的ssl标准库可以很方便地把普通socket升级为TLSsocket。import ssl context ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) context.load_cert_chain(certfileserver.crt, keyfileserver.key) # 服务端 accept 后 tls_sock context.wrap_socket(raw_sock, server_sideTrue)公网Server配置了TLS之后内网Client在连接时也要使用ssl.create_default_context()创建一个客户端上下文并调用context.wrap_socket(sock, server_hostnamehostname)。证书可以用云平台免费的SSL证书也可以自建CA后把CA证书放到客户端机器上。如果只是自己开发用自签名证书配合关闭校验的客户端参数也可以但生产环境绝对不要关闭校验。5.3 访问边界底下服务越少暴露面越小内网穿透本质上是把原本只能在内网访问的服务暴露到了公网因此暴露面控制非常关键。proxynt在设计上支持这个需求你可以用--expose参数精确指定要暴露的端口不建议把整个网段都暴露出去。我在实操中的几个原则只暴露运行服务本身需要的端口比如Web服务暴露8000不要把SSH的22端口一并暴露。在服务端用IP白名单限制访客来源只允许客户办公网段的IP访问。对没有认证机制的服务比如某些数据库、Redis绝不直接穿透必须在前面套一层认证或只允许本机访问。用临时端口而非固定端口暴露用完即删减少被扫描到的概率。5.4 日志与审计谁在什么时候访问了什么穿透工具一旦部署到公网就需要有日志而且日志要保留一定周期。proxynt的日志会记录三类事件内网Client的注册与下线、异常的Token校验失败、访客连接的建立与关闭。下面是典型的日志片段2025-01-12 10:23:01 INFO client connected: 203.0.113.5:52301, ports[8000] 2025-01-12 10:23:15 INFO visitor connected: 198.51.100.7:39102 - conn_id3 2025-01-12 10:23:17 WARN invalid token from 203.0.113.9:40123日志能帮助你在出现异常访问、被扫描、被爆破时快速定位问题。别小看这一步等到真的出问题需要复盘时没有日志会非常被动。我在部署时还会用一个简单的logrotate定期归档日志避免单个日志文件无限增大。6. 与ngrok/frp对比以及后续可扩展方向6.1 横向对比什么时候该用它什么时候该用frp自研工具和成熟工具之间的关系不是替代而是互补。我整理了一张对比表方便你根据实际情况选型。对比项ngrokfrpproxynt上手成本最低注册即可中等需要自建配置中等代码量不大自定义协议弱强很强完全自己掌控认证与安全官方提供支持Token、TLS支持TokenTLS需要自己封装性能依赖官方服务器高中等适合开发调试学习价值低中高每个协议和逻辑都可读生产可用性适合临时使用适合长期生产看你的改造和运维能力如果你只需要临时给客户演示一下或者快速试一个Webhookngrok是最快路径。如果你要在生产环境长期跑穿透frp的性能和稳定性更可靠。如果你想要能自己掌控协议、学原理或者想在里面加些特殊的业务逻辑proxynt这类自研工具会更合适。6.2 还能往哪扩展HTTP域名分流、可视化Dashboard、动态端口映射proxynt当前版本的协议层很有可塑性后续你可以在此基础上加不少功能。比如在服务端解析Frame里的目标域名根据域名把不同访客路由到不同的内网Client这就是ngrok那种多域名共用一个入口的功能又比如可以在控制帧里加一条“动态添加端口映射”的指令这样就不用每次改配置重启客户端。我还考虑过做一个简单的Web Dashboard用WebSocket把当前在线状态、各端口流量、连接数等数据实时推送给管理员这在自建工具里非常有价值因为日志文件没法让人直观地“看到”隧道状态。如果再配合SQLite记录连接历史就能变成一个小型灵巧的运维平台。6.3 写代码之后再补上设计文档和自动化测试最后我想分享一个经验自研工具最大的风险不是没人用而是代码只有你自己懂。proxynt早期我写过一版功能跑通了但三个月后自己回看已经记不清某个字段的具体含义。后来我花时间补了两样东西一是协议文档把每个Frame类型、每个字段的取值范围都写清楚二是自动化测试尤其是Frame编解码和断线重连这两个核心模块。有了这两样东西后续不管是给自己加功能还是给别人接手都会顺畅很多。如果你也准备动手写一个类似的内网穿透工具不妨先从小规模场景开始比如只暴露一个Web服务跑通后再逐步加端口、加认证、加TLS、加重连。每一步都验证过再进入下一步。这样你得到的不仅是一个能用的工具还有一整套对网络协议和Socket编程的完整认识。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

ebook2audiobook(E2A)实践指南:从电子书到有声书的全流程配置与 CLI/Docker 部署详解 2026/10/1 2:13:00

ebook2audiobook(E2A)实践指南:从电子书到有声书的全流程配置与 CLI/Docker 部署详解

AI 应用语音音频本地部署 【免费下载链接】ebook2audiobook Generate audiobooks from e-books, voice cloning & 1158 languages! 项目地址: https://gitcode.com/GitHub_Trending/eb/ebook2audiobook 点击查看 免费下载 本文围绕开源项目 ebook2audiobook&am…

阅读更多 →
用 Rust 运行 BERT 句向量推理:candle 示例的句子嵌入与相似度计算实战指南 2026/10/1 2:13:00

用 Rust 运行 BERT 句向量推理:candle 示例的句子嵌入与相似度计算实战指南

人工智能大模型机器学习深度学习本地部署模型推理服务 【免费下载链接】candle Minimalist ML framework for Rust 项目地址: https://gitcode.com/GitHub_Trending/ca/candle 点击查看 免费下载 candle 是一个用 Rust 编写的极简机器学习框架,本文以仓…

阅读更多 →
TpmInit.exe丢失别重装:系统文件修复完整指南 2026/10/1 2:12:59

TpmInit.exe丢失别重装:系统文件修复完整指南

1. 当 TpmInit.exe 文件缺失,别急着重装系统先说结论:TpmInit.exe 是 Windows 系统里跟“可信平台模块(TPM)”相关的一个初始化进程,一般位于 C:\Windows\System32 目录下。它负责在系统启动阶段配合主板上的 TPM 芯片…

阅读更多 →
链表面试必刷7题:反转、回文、环检测与归并排序全解析 2026/10/1 2:12:59

链表面试必刷7题:反转、回文、环检测与归并排序全解析

前两天帮一个应届学弟做模拟面试,他把剑指offer刷了两遍,结果第一道反转链表就卡住了——不是不会写,是边边角角的空指针处理让他心里没底。这个场景我见过太多次了。链表在技术面试里的地位很特殊:它不像动态规划那样依赖数学直觉…

阅读更多 →
ShardingSphere 分库分表 + 读写分离 2026/10/1 2:12:53

ShardingSphere 分库分表 + 读写分离

目录 1.pom.xml配置 2.配置分库分表规则 2.1.创建实体类和Mapper接口 2.2.测试分库分表 3.配置读写分离规则 3.1.测试读写分离 4.分库分表 读写分离 方案一:分库分表 读写分离整合配置 方案二:使用读写分离数据源作为分片数据源 注意事项&…

阅读更多 →
Windows 终端 AI 编程实战:Codex CLI 接入 DeepSeek API 全流程配置指南 2026/10/1 2:12:53

Windows 终端 AI 编程实战:Codex CLI 接入 DeepSeek API 全流程配置指南

1. 为什么要在 Windows 上折腾 Codex CLI 加 DeepSeek API 这套组合很多人第一次听到"在终端里跑 AI 编程助手"这件事,第一反应是:我直接用网页版不香吗?我一开始也这么想,直到我在一个没有图形界面的远程开发环境里&am…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉