WebSphere 8.5遗留应用调用外部Rest API报Connection reset问题
针对WebSphere 8.5遗留应用调用外部API时出现java.net.SocketException: Connection reset的问题,结合Quarkus应用可正常调用的对比,从代码、容器配置、SSL/网络三个维度逐一排查:
一、代码层面问题排查
修复语法错误
代码中con.setRequestProperty(Key", "ab58ebddf2b7dc");存在引号缺失问题,应修正为:con.setRequestProperty("Key", "ab58ebddf2b7dc");缺失引号会导致请求头无法正确设置,可能触发服务器端异常。
移除GET请求的
setDoOutput(true)setDoOutput(true)是为POST/PUT等带请求体的方法设计的,GET请求设置该属性会强制HttpURLConnection以POST模式发送请求,与服务器预期的GET方法冲突,进而引发连接重置。直接删除该行代码即可。完善响应流处理与连接关闭
当前代码仅获取响应码但未读取响应流,服务器端可能因连接未正常释放主动重置连接。需添加流读取逻辑,并在finally块中关闭连接:public ResponseEntity<Challenge> init(){ HttpURLConnection con = null; try { System.out.println("###LivenessService.init() - API Test - DEV Server"); URL url = new URL(urlInit); con = (HttpURLConnection) url.openConnection(); con.setRequestProperty("Key", "ab58ebddf2b7dc"); con.setUseCaches(false); con.setRequestMethod("GET"); con.setRequestProperty("Content-Type","application/json"); // 添加超时设置 con.setConnectTimeout(5000); con.setReadTimeout(10000); int responseCode = con.getResponseCode(); System.out.println("###LivenessService.init() - chamada efetuada com sucesso"); System.out.println("### - "+responseCode); // 读取响应流(无论成功失败) if (responseCode == HttpURLConnection.HTTP_OK) { try (BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()))) { String line; while ((line = in.readLine()) != null) { // 即使不需要内容,也要读取以完成连接生命周期 } } } else { try (BufferedReader in = new BufferedReader(new InputStreamReader(con.getErrorStream()))) { String line; while ((line = in.readLine()) != null) { System.out.println("### Error response: "+line); } } } }catch(Exception e){ e.printStackTrace(); } finally { if (con != null) { con.disconnect(); } } // 补充原方法缺失的返回逻辑 return ResponseEntity.ok(...); }
二、WebSphere 8.5容器配置排查
检查SSL/TLS版本兼容性
WebSphere 8.5默认可能仅启用TLS 1.0/1.1,而外部API可能要求TLS 1.2及以上版本,导致SSL握手失败触发连接重置。- 登录WebSphere管理控制台,路径:
安全 > SSL证书和密钥管理 > SSL配置 > 选择对应SSL配置 > 质量保护(QoP)设置 - 将协议修改为
TLSv1.2,保存后重启服务器。
- 登录WebSphere管理控制台,路径:
验证代理配置
WebSphere可能配置了全局出站代理,而该代理未放行目标API的域名/端口,导致连接被拦截。- 路径:
服务器 > 服务器类型 > WebSphere应用服务器 > 选择服务器 > 服务器基础结构 > Java和进程管理 > 进程定义 > Java虚拟机 > 自定义属性 - 检查是否存在
http.proxyHost、http.proxyPort等代理属性,若存在需确认代理是否允许访问目标API地址,或直接删除代理属性(同一网络无需代理时)。
- 路径:
信任证书检查
外部API的SSL证书可能未被WebSphere的信任库识别,导致SSL握手失败。- 导出外部API的根证书(可通过浏览器访问API地址后导出)
- 登录WebSphere控制台,路径:
安全 > SSL证书和密钥管理 > 密钥存储库 > 选择DefaultTrustStore > 签名者证书 > 添加 - 导入导出的根证书,保存后重启服务器。
主机名验证设置
WebSphere默认开启严格的主机名验证,若API证书中的主机名与请求URL的主机名不匹配,会触发SSL握手失败。- 路径:
安全 > SSL证书和密钥管理 > SSL配置 > 选择对应SSL配置 > 高级SSL设置 - 将
主机名验证设置为无(测试环境临时使用),或确保证书主机名与请求URL完全一致。
- 路径:
Java安全权限检查
WebSphere的Java安全管理器可能限制了出站网络连接权限。- 找到服务器的
java.policy文件(通常位于${WAS_HOME}/profiles/${PROFILE_NAME}/properties目录) - 添加以下权限规则,允许访问目标API的端口:
permission java.net.SocketPermission "api.example.com:443", "connect,resolve";
替换
api.example.com:443为实际的API地址和端口。- 找到服务器的
三、网络层面辅助排查
- 使用WebSphere服务器上的
curl命令测试目标API的连通性,确认网络链路正常:curl -H "Key: ab58ebddf2b7dc" https://api.example.com/your-path - 抓包分析:在WebSphere服务器上使用
tcpdump抓取与API的通信包,查看是否存在SSL握手失败、数据包丢失等情况,定位连接重置的具体阶段。
内容的提问来源于stack exchange,提问作者Savio Barros

