You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jenkins流水线执行Smoke Test时请求超时问题排查

问题分析与修复方案

从你的日志和代码来看,核心问题是Connection refused被Jenkins的httpRequest插件映射为408超时,导致流水线异常终止,同时你的重试逻辑和错误处理也存在一些不合理的地方。下面具体拆解问题并给出修复方案:

1. 当前代码存在的核心问题

  • 重试逻辑不分场景:不管是网络连接错误(比如连接拒绝、超时)还是版本不匹配,都会触发重试。但版本不匹配是部署结果错误,重试多少次都没用,属于无效重试。
  • httpRequest默认处理太严苛:默认情况下,插件会把底层连接错误(比如Connection refused)映射为408超时,且只要响应码不在100-399范围就直接抛出异常,让你无法灵活处理这类场景。
  • 批量检测的重试粒度不合理:遍历多个端口时,只要一个端口失败就终止整个循环并全量重试,会重复检测已经成功的端口,浪费资源。

2. 修复后的Pipeline代码

void smoketests() {
    SMOKE_TEST_PORTS.each { port ->
        // 对每个端口单独执行重试逻辑,避免全量重复检测
        retry(3) {
            try {
                String url = isReleaseBranch() ? "https://<url>:${port}/actuator/info" : "http://<url>:${port}/actuator/info"
                
                // 自定义httpRequest配置,接管错误处理
                def response = httpRequest(
                    consoleLogResponseBody: true,
                    timeout: 60,
                    httpMode: 'GET',
                    ignoreSslErrors: true,
                    url: url,
                    ignoreReturnCode: true, // 不自动抛出异常,自己处理响应
                    validResponseCodes: '' // 清空默认的有效响应码范围
                )

                // 专门处理连接拒绝类错误
                if (response.status == 408 || response.content.contains("Connection refused")) {
                    throw new IOException("Failed to connect to ${url}: ${response.content}")
                }

                // 处理非2xx的正常响应错误
                if (response.status < 200 || response.status >= 300) {
                    throw new Exception("Unexpected status code ${response.status} for ${url}")
                }

                // 解析响应并校验版本
                def responseJson = readJSON(text: response.content)
                if (!responseJson.build.version.equals(POM.getVersion())) {
                    // 版本不匹配直接终止,不重试
                    throw new IllegalStateException("Version mismatch: expected ${POM.getVersion()}, got ${responseJson.build.version}")
                }

                println "Smoke test passed for ${url}"
            } catch (IOException e) {
                // 仅网络类异常触发重试,休眠后抛出异常让retry捕获
                println "Network error: ${e.message}, retrying after 20s..."
                sleep(time: 20, unit: 'SECONDS')
                throw e
            } catch (IllegalStateException e) {
                // 版本不匹配直接终止流程
                println e.message
                throwError("Smoke test failed due to version mismatch")
            } catch (Exception e) {
                // 其他未知错误直接终止
                println "Unexpected error: ${e.message}"
                throwError("Smoke test failed unexpectedly")
            }
        }
    }

    if (isReleaseBranch()) {
        sendMattermostMsg("released ${PROJECT} with version ${POM.getVersion()} on UAT")
    }
}

3. 关键改进说明

  • 按端口独立重试:每个端口的检测逻辑单独重试,避免一个端口失败导致所有端口重复检测。
  • 异常类型区分处理:
    • 仅网络类异常(IOException)触发重试,重试前休眠20秒。
    • 版本不匹配的异常直接终止流程,不做无效重试。
  • 接管httpRequest错误处理:通过ignoreReturnCode: true关闭插件默认的异常抛出逻辑,自己处理连接错误和响应码,更灵活。
  • 清晰的错误日志:每种错误场景都有明确的日志输出,便于后续排查问题。

额外排查建议

你提到浏览器能正常访问但流水线请求失败,还可以检查:

  • Jenkins代理服务器是否能访问目标端口(比如防火墙规则、网络路由限制)。
  • 目标应用的/actuator/info端点是否对Jenkins代理的IP开放权限。

内容的提问来源于stack exchange,提问作者m1well

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 12:42:41