Maven连不上Nexus?Connection refused/超时排查手册
做Java开发的人几乎都被Maven连不上仓库的问题折腾过。尤其当私服用的是Nexus时报错里出现“Connection refused”或者“Connect timeout”第一反应往往是“我去服务挂了”但排查下来经常发现Nexus本身活得好好的问题出在配置、网络、甚至镜像源上。我刚接手某个项目时连续三天都在跟这个报错搏斗最后把常见的坑都踩了一遍才意识到这类问题看似简单套路却很深。这份速查手册不是纯理论分析而是把我实际排查过的路径完整写下来。内容包括连接被拒绝的几种真实形态、根因分类、从客户端到服务端的逐层排查流程、Maven和Nexus配置细节、以及几个高频场景的实录。适合正在被仓库连接问题折磨的Java后端开发者也适合维护CI构建、负责私服稳定性的运维同事。照着顺序排查绝大多数连接问题都能在十分钟内定位。1. 先搞清楚“连接被拒绝”到底是怎么回事1.1 三种常见的报错形态Maven和Nexus之间的连接问题表面上都叫“连接被拒绝”但实际上报错信息分好几种如果从一开始就判断错方向后面全是白忙。第一种是TCP层的直接拒绝典型报错长这样[ERROR] Failed to execute goal ... Could not transfer artifact ... Caused by: org.apache.maven.wagon.TransferFailedException: Failed to transfer http://192.168.1.100:8081/repository/maven-public/ Error code 500, transfer failed.还有更直白的ConnectException: Connection refused: connect这种基本意味着客户端发出的TCP SYN包被对端直接RST或者无人应答常见于Nexus服务没启动、端口被防火墙拦截、或者客户端连错了IP和端口。第二种是连接超时报错类似ConnectException: Connect timed out和“拒绝”不同超时说明SYN包发出后一直没收到响应中间链路被丢弃的可能性更大。比如跨网段访问、安全组没放行、目标主机有iptables规则把包静默丢掉了。第三种最迷惑人管它能连通但Maven依然报“Connection refused”或者返回403/404。很多情况是HTTP层的问题比如配置的仓库名不存在、凭据错误、HTTPS证书不被信任或者Nexus那边强制了HTTPS而你还在用HTTP去连。这些报错经过Maven封装后错误信息往往也是“connection”开头容易让人误判成网络故障。1.2 影响范围与排查价值连接被拒绝看起来只是Maven命令执行失败但实际影响面比想象中大得多。本地开发环境还好说顶多是自己构建失败到了CI流水线里一旦Nexus连接异常所有依赖编译的模块都会在同一时间失败整个发布流程直接卡死。如果Nexus本身被配置成多个项目的统一依赖源那影响范围就是全研发团队。这类问题的排查价值在于它往往不只是“一次偶发故障”而是暴露了网络策略、配置管理、服务可用性监控上的薄弱点。我有一次排查到最后发现是CI构建机所在的子网变更了路由而Nexus那边的防火墙规则没同步更新导致所有新构建机都无法访问。这类问题如果只靠重启或者碰运气解决下次换一台机器还会再犯。所以很有必要把排查链路固化下来每次遇到“连接被拒绝”都按固定套路走效率能提升不少。2. 连接被拒绝的根因分类2.1 网络层根因排查这类问题我习惯先把根因分成四层网络层是第一个要排除的。网络层根因包括客户端和目标服务器之间路由不可达、防火墙主动拒绝、DNS解析出问题、甚至IPv6/IPv4地址族不匹配。举个例子某些服务器默认优先解析IPv6但Nexus服务只监听在IPv4地址上。如果客户端解析出的是IPv6地址连接就会超时或被拒绝。这个问题在本地经常被忽略因为看起来就是“连不上”ping又能通但实际上走的根本不是同一个协议栈。防火墙层面云平台安全组、本机iptables、或者企业内部防火墙都可能导致端口不可达。常见的是只放行了80和443而Nexus默认端口8081没开。或者Nexus部署在Docker里端口映射没做对导致外部访问无效。2.2 配置层根因配置层的坑更多。Maven的settings.xml里涉及多个关键配置mirror、server、profile、proxy。Nexus侧又涉及仓库类型、仓库URL、认证权限、匿名访问开关。最常见的情况是mirror配置错误比如把所有请求都镜像到一个错误地址或者镜像配置指向的URL少写了一个斜杠。还有server配置里的id与mirror里的id不一致导致Maven找不到对应的用户名密码或发送匿名请求被Nexus拒绝。另外Nexus仓库的URL并非随便填的。每个仓库有自己的Repository Manager如果填错请求会落到不存在的资源上Nexus可能直接返回404或403。Maven在解析插件和依赖时对各种状态码的处理方式不同有些404会被包装成连接异常。2.3 服务层根因服务层根因指的是Nexus本身运行不正常。可能是进程崩溃、JVM内存溢出、磁盘写满或者服务启动了但尚未监听端口。特别是磁盘满的情况Nexus虽然还活着但无法写入新的blob对外表现像是拒绝服务。另一个容易被忽略的是Nexus启动完成时间。某些机器上Nexus启动较慢端口监听出现后外部立即访问仍会被暂拒。如果CI构建脚本没有等待健康检查立刻发起连接就会偶发失败。2.4 认证鉴权层根因虽然“连接被拒绝”听起来不像是权限问题但认证失败很容易直接表现为连接失败。Nexus默认开了匿名访问的话可能还能下载一旦关闭匿名Maven请求没有带正确凭据Nexus会返回401或403。如果配置了代理仓库上游还需要另一个用户名密码这一层嵌套认证更容易出问题。此外Nexus中的用户可能在配置后被禁用或删除了。比如用户密码过期、角色被调整后失去权限这些变化不会立刻反映在Maven本地缓存里只有构建时才能暴露。3. 手工排查流程从客户端到服务端逐层验证3.1 第一步确认Nexus服务真的活着不管报错提示是什么第一步永远是确认服务端状态。直接上Nexus所在服务器用命令行查看端口监听ss -lntp | grep 8081如果输出中包含类似“LISTEN 0 100 0.0.0.0:8081”的行说明服务在监听。如果没有输出大概率Nexus进程没起来或者监听的不是这个端口。再看进程状态ps aux | grep nexus有Java进程不代表Nexus就健康。如果磁盘满了服务会处于半死不活状态。检查磁盘和内存df -h free -m如果blob存储所在分区使用率接近100%优先清理存储或扩容而不是继续排查网络。这一步先排除服务层问题能省很多时间。3.2 第二步验证客户端到服务端的网络链路服务端正常的话就要从客户端验证网络链路。最简单的命令是telnet看端口能不能通telnet 192.168.1.100 8081如果连接被拒绝会直接提示“Connection refused”。如果是超时命令会挂在那里直到超时。此时需要进一步用ping排除主机层面的问题再用traceroute看中间路由节点。如果telnet能连通说明TCP层没问题问题大概率在HTTP层或配置层。这时我习惯直接用curl测仓库URLcurl -v http://192.168.1.100:8081/repository/maven-public/注意看返回的HTTP状态码。如果返回200或302说明Nexus的Web层正常。如果返回401/403那问题在认证。如果返回404多半是仓库名或路径不对。如果客户端服务器有多个网络接口还要确认源地址选对没有。比如同时有内网和公网IP访问Nexus时走了错误出口也需要用“ip route get 192.168.1.100”来检查路由。3.3 第三步检查Maven配置网络没问题就该检查Maven的settings.xml了。执行如下命令确认当前生效的配置文件mvn help:effective-settings这个命令会打印合并后的有效配置重点关注mirrors和servers部分。一个常见错误是mirror配置成mirror idnexus/id urlhttp://192.168.1.100:8081/repository/maven-public/url mirrorOf*/mirrorOf /mirrorURL少了末尾斜杠在拼接依赖路径时可能产生错误地址。另一个常见错误是mirrorOf配置为“*”把所有请求都指向私服如果私服没有完整代理上游仓库部分依赖就会404。同时检查server配置server idnexus/id usernameadmin/username passwordxxxx/password /serverserver的id需要和mirror的id保持一致Maven才会自动匹配凭据。否则Maven以匿名身份请求Nexus一旦Nexus禁止匿名访问就会报Unauthorized。3.4 第四步在Nexus服务端找日志如果配置看起来没问题就需要去Nexus服务端看日志。Nexus的日志目录一般在安装目录下的“sonatype-work/nexus3/log”里常见的日志文件有“nexus.log”和“request.log”。其中request.log记录了每次HTTP请求的状态码非常有用。比如一条记录显示请求路径是“/repository/maven-public/”状态码是401那说明客户端确实连上了Nexus只是凭据不对。如果状态码是404说明路径不对仓库名配置错了。如果压根没有新增日志说明HTTP请求根本没到Nexus层问题还在网络或代理层。看日志时可以加个时间过滤比如用tail跟踪tail -f sonatype-work/nexus3/log/request.log然后在客户端重新执行一次Maven构建观察新记录。这种方式能直接确认请求是否到达以及Nexus具体拒绝原因。4. Maven与Nexus配置细节拆解4.1 settings.xml里的server与mirror到底怎么配很多人对Maven的server和mirror的关系理解得不够透彻导致配置反复出错。mirror的核心作用是拦截对远程仓库的请求改发到另一个地址它解决的是“从哪里下载”的问题。server的核心作用是给某个仓库id提供凭据信息它解决的是“用什么身份下载”的问题。两者通过id绑定。假设mirror的id是“my-nexus”那么在server里也要有id为“my-nexus”的配置。很多人习惯把server的id写成Nexus管理员账号名结果Maven完全匹配不上。一个稳健的配置模板是settings mirrors mirror idmy-nexus/id mirrorOf*/mirrorOf urlhttp://192.168.1.100:8081/repository/maven-public//url /mirror /mirrors servers server idmy-nexus/id usernamedeploy/username passwordencrypted-password/password /server /servers /settings实际项目中不建议明文保存密码Maven支持对server密码进行加密通过maven的settings-security.xml机制实现。如果担心配置泄露部署时用环境变量加占位符的方式也可行。4.2 仓库URL为什么不能随便填Nexus仓库URL有固定格式常见的仓库类型包括maven-central、maven-releases、maven-snapshots以及自定义的maven-public等。URL路径一定是“/repository/仓库名/”这里的“仓库名”是Nexus里定义的仓库名称大小写敏感。一个常见错误是把URL写成了Nexus的首页地址比如“http://ip:8081/”这能访问Nexus界面但Maven请求“/maven-public/xxx.jar”时路径不存在会返回404。在Maven的报错里有时会显示“Connection closed”或“transfer failed”其实根本不是网络问题。如果Nexus启用了HTTPS那么URL里必须使用“https://”。有些环境里有SSL证书拦截或者自签证书Maven默认校验证书失败也会报连接类错误。这种问题需要把证书导入到Java的cacerts里或者配置Maven信任该证书。4.3 HTTPS证书与代理引发的“假拒绝”所谓“假拒绝”是指网络和服务都正常但Maven仍然报连接失败。两个最大嫌疑是证书和代理。自签证书场景非常常见。私有部署Nexus时一般不会购买公有证书客户端Java环境默认不信任自签证书握手阶段就会断开。报错信息里通常出现“SSLHandshakeException”或“PKIX path building failed”很多人看到“SSL”就直接归类为网络问题其实只要把证书导入Java信任库即可keytool -import -trustcacerts -alias nexus -file nexus.crt -keystore $JAVA_HOME/lib/security/cacerts代理方面如果Maven配置了proxy用于访问外网内网Nexus可能被误走到代理代理服务器又无法访问内网地址导致连接卡住或失败。判断方法是看完整日志里是否出现代理服务器的IP或端口。也可以临时禁用proxy参数通过“-Dhttp.proxyHost -Dhttp.proxyPort”来覆盖。5. 高频场景实录与避坑清单5.1 场景一容器里跑Nexus现在不少团队把Nexus跑在Docker容器里。容器端口映射容易出错尤其当宿主机IP变了或者端口绑定到“127.0.0.1”上外部访问就会失败。假设用以下命令启动容器docker run -d -p 8081:8081 --name nexus nexus3外部访问“宿主机IP:8081”可以通因为端口绑定了所有网卡。但如果写成“-p 127.0.0.1:8081:8081”就只能本机访问其他机器连接就被拒绝。排查时可以先在宿主机上测试localhost访问能通而不能外部访问重点检查端口绑定方式和防火墙。容器内Nexus的日志需要进容器看磁盘空间也要映射到宿主机或外部存储卷。否则容器重启后数据丢失仓库重新初始化客户端缓存里的仓库名可能就失效了。5.2 场景二CI构建机偶发连接失败CI构建机上的问题通常更隐蔽因为不是每次都失败。可能白天构建量大Nexus连接数打满或者构建机用了动态IP刚好落在防火墙限制的网段。我之前就遇到过CI机器A能连Nexus机器B连接超时但B和A在同一个网段。最后发现Nexus的防火墙规则里按IP段做了白名单A的IP在白名单内B的IP不在。这类问题用telnet时超时是唯一的线索必须回头检查防火墙策略。还有一次是CI服务器的网络代理设置了“NO_PROXY”配置缺失导致内网Nexus被代理服务器转发代理服务器认为该地址不可达就直接返回错误。修复方法是确保“NO_PROXY”包含Nexus的域名和IP段。5.3 场景三Nexus迁移后大量403/404私服迁移是很典型的高发场景。把Nexus从旧服务器迁到新服务器后域名或IP变了Maven配置里还留着旧地址自然连接失败。如果保留了旧地址的DNS解析但新服务器上仓库名不一样请求返回404。迁移时最容易忽略的是仓库的匿名访问设置和用户权限。有些团队在旧环境开启了匿名访问迁移后因为安全考虑关掉了结果所有客户端都报401。解决方式不是重新开启匿名访问而是把Maven的server凭据发到各构建机同时定期更新密码。迁移还有一个隐藏点旧的Nexus实例可能有自定义的blob store迁移后如果关联路径没对应上仓库看起来存在但下载文件时返回异常。要确保新实例上的仓库都在健康状态看看“Browse”页面能否正常列出文件。5.4 速查表一条报错对应一个动作把常见报错和动作整理成速查表能帮团队节省大量沟通成本报错特征优先检查方向快速动作Connection refused服务端口、进程检查Nexus进程和端口监听Connect timed out防火墙、路由、安全组测试telnet检查中间网络节点SSLHandshakeException证书信任导入证书到Java cacerts401 Unauthorized凭据、匿名访问调整server配置或开启匿名403 Forbidden权限、仓库授权检查用户角色和仓库权限404 Not Found仓库名、URL路径核对Nexus实际仓库名表格不能替代排查但能帮新人在手忙脚乱时快速锁定区域。我自己的习惯是先把报错完整截图或贴到记事本再按表中方向逐项验证不要凭感觉改配置。6. 从速查走向预防构建稳定的仓库接入链6.1 网络层面怎么加固排查连接问题只是亡羊补牢稳定接入还得靠网络层面的规范化。私服连接最怕单点故障和不明变更。我给团队定的规范是Nexus必须绑定独立内网IP不随意改宿主机网络配置防火墙规则用配置管理工具维护每次变更走审批和通知。端口层面默认8081如果能固定就固定不要频繁变化。如果Nexus是HTTPS方式443端口容易和Web应用冲突最好用独立域名加反向代理。反向代理本身会引入新的连接层需要一并纳入监控。6.2 配置与账号管理规范Maven配置最怕乱了套。每个项目组的setting.xml最好统一由配置中心下发不要各人手工改。文件和组件的账号密码绝对不能放到代码仓库里建议使用配置管理平台或者凭据管理工具。账号管理方面不要所有人都用admin账号连私服。合理做法是给不同业务线建独立账号最小权限原则。这样出问题时从Nexus访问日志就能定位是哪个业务方。季度性轮换密码也是个好习惯避免密码泄露后长期无人察觉。6.3 日志与监控怎么搭Nexus的日志里藏着大量信息不监控就等于瞎跑。最基本的是监控端口存活用探活脚本定期HTTP请求Nexus根地址。再高级一点把request.log中的5xx、4xx状态码接入告警平台。一旦某个时间窗口内401或404数量突增立刻触发告警大概率能提前发现配置变更或凭据过期。我实际用的一个简单探活脚本是curl -k -s -o /dev/null -w %{http_code} http://localhost:8081/如果返回非200就发告警。这类脚本部署成本低但作用很大。毕竟连接被拒绝的痛苦很大一部分来自于“故障发生后才发现”事后处理永远比事前监控被动。最后再分享一个我自己的习惯所有连接类报错我都会先把Maven的-U参数加上强制检查远程依赖更新避免本地缓存掩盖真实问题。然后去看Nexus的request.log最后再看settings.xml。这个顺序帮我解决过很多次看似无解的报错也希望这份手册能帮你少踩几个坑。