From a866de1754bd81fca2c72e5beced4288700903d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=97=BA=E9=98=B3?= Date: Tue, 10 Oct 2023 21:20:43 -0500 Subject: [PATCH] [Improvement][Alert] HTTP Related Alert plugin add retry logic (#14972) * add RetryHandler for http client * fix spotless * update --- .../alert/api/HttpServiceRetryStrategy.java | 73 +++++++++++++++++++ .../plugin/alert/dingtalk/DingTalkSender.java | 6 +- .../plugin/alert/feishu/HttpRequestUtil.java | 7 +- .../plugin/alert/http/HttpSender.java | 6 +- .../alert/pagerduty/PagerDutySender.java | 4 +- .../plugin/alert/slack/SlackSender.java | 5 +- .../plugin/alert/telegram/TelegramSender.java | 6 +- .../alert/webexteams/WebexTeamsSender.java | 4 +- .../plugin/alert/wechat/WeChatSender.java | 9 ++- 9 files changed, 107 insertions(+), 13 deletions(-) create mode 100644 dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-api/src/main/java/org/apache/dolphinscheduler/alert/api/HttpServiceRetryStrategy.java diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-api/src/main/java/org/apache/dolphinscheduler/alert/api/HttpServiceRetryStrategy.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-api/src/main/java/org/apache/dolphinscheduler/alert/api/HttpServiceRetryStrategy.java new file mode 100644 index 0000000000..dfe2c3d5c4 --- /dev/null +++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-api/src/main/java/org/apache/dolphinscheduler/alert/api/HttpServiceRetryStrategy.java @@ -0,0 +1,73 @@ +/* + * Licensed to Apache Software Foundation (ASF) under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Apache Software Foundation (ASF) licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.dolphinscheduler.alert.api; + +import org.apache.http.HttpEntityEnclosingRequest; +import org.apache.http.HttpRequest; +import org.apache.http.NoHttpResponseException; +import org.apache.http.client.HttpRequestRetryHandler; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.protocol.HttpContext; + +import java.io.IOException; +import java.io.InterruptedIOException; +import java.net.SocketException; +import java.net.UnknownHostException; + +import javax.net.ssl.SSLException; + +public class HttpServiceRetryStrategy implements HttpRequestRetryHandler { + + public static final HttpServiceRetryStrategy retryStrategy = new HttpServiceRetryStrategy(); + + private static final int RETRY_COUNT = 3; + + private static final long RETRY_INTERVAL_TIME = 2000L; + + @Override + public boolean retryRequest(IOException exception, int executionCount, HttpContext httpContext) { + if (executionCount > RETRY_COUNT) { + return false; + } + + if (exception instanceof SSLException) { + return false; + } + + if (exception instanceof UnknownHostException || + exception instanceof InterruptedIOException + || exception instanceof NoHttpResponseException + || exception instanceof SocketException) { + // retry interval time + try { + Thread.sleep(RETRY_INTERVAL_TIME); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + return true; + } + + HttpClientContext clientContext = HttpClientContext.adapt(httpContext); + HttpRequest request = clientContext.getRequest(); + + // Retry if the request is considered idempotent + return !(request instanceof HttpEntityEnclosingRequest); + } +} diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSender.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSender.java index 010cfc1a5d..c0070ac11c 100644 --- a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSender.java +++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSender.java @@ -18,6 +18,7 @@ package org.apache.dolphinscheduler.plugin.alert.dingtalk; import org.apache.dolphinscheduler.alert.api.AlertResult; +import org.apache.dolphinscheduler.alert.api.HttpServiceRetryStrategy; import org.apache.dolphinscheduler.common.utils.JSONUtils; import org.apache.commons.codec.binary.Base64; @@ -108,11 +109,12 @@ public final class DingTalkSender { HttpHost httpProxy = new HttpHost(proxy, port); CredentialsProvider provider = new BasicCredentialsProvider(); provider.setCredentials(new AuthScope(httpProxy), new UsernamePasswordCredentials(user, password)); - return HttpClients.custom().setDefaultCredentialsProvider(provider).build(); + return HttpClients.custom().setRetryHandler(HttpServiceRetryStrategy.retryStrategy) + .setDefaultCredentialsProvider(provider).build(); } private static CloseableHttpClient getDefaultClient() { - return HttpClients.createDefault(); + return HttpClients.custom().setRetryHandler(HttpServiceRetryStrategy.retryStrategy).build(); } private static RequestConfig getProxyConfig(String proxy, int port) { diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/HttpRequestUtil.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/HttpRequestUtil.java index 2ba373df08..c981175610 100644 --- a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/HttpRequestUtil.java +++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/HttpRequestUtil.java @@ -17,6 +17,8 @@ package org.apache.dolphinscheduler.plugin.alert.feishu; +import org.apache.dolphinscheduler.alert.api.HttpServiceRetryStrategy; + import org.apache.http.HttpHost; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; @@ -40,9 +42,10 @@ public final class HttpRequestUtil { HttpHost httpProxy = new HttpHost(proxy, port); CredentialsProvider provider = new BasicCredentialsProvider(); provider.setCredentials(new AuthScope(httpProxy), new UsernamePasswordCredentials(user, password)); - return HttpClients.custom().setDefaultCredentialsProvider(provider).build(); + return HttpClients.custom().setRetryHandler(HttpServiceRetryStrategy.retryStrategy) + .setDefaultCredentialsProvider(provider).build(); } else { - return HttpClients.createDefault(); + return HttpClients.custom().setRetryHandler(HttpServiceRetryStrategy.retryStrategy).build(); } } diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpSender.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpSender.java index 9aeb7ab3c9..bdd6cf15cd 100644 --- a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpSender.java +++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpSender.java @@ -18,6 +18,7 @@ package org.apache.dolphinscheduler.plugin.alert.http; import org.apache.dolphinscheduler.alert.api.AlertResult; +import org.apache.dolphinscheduler.alert.api.HttpServiceRetryStrategy; import org.apache.dolphinscheduler.common.utils.JSONUtils; import org.apache.commons.lang3.StringUtils; @@ -28,7 +29,7 @@ import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import java.io.IOException; @@ -106,7 +107,8 @@ public final class HttpSender { } public String getResponseString(HttpRequestBase httpRequest) throws IOException { - CloseableHttpClient httpClient = HttpClientBuilder.create().build(); + CloseableHttpClient httpClient = + HttpClients.custom().setRetryHandler(HttpServiceRetryStrategy.retryStrategy).build(); CloseableHttpResponse response = httpClient.execute(httpRequest); HttpEntity entity = response.getEntity(); return EntityUtils.toString(entity, DEFAULT_CHARSET); diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-pagerduty/src/main/java/org/apache/dolphinscheduler/plugin/alert/pagerduty/PagerDutySender.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-pagerduty/src/main/java/org/apache/dolphinscheduler/plugin/alert/pagerduty/PagerDutySender.java index fb586cd255..568faf167b 100644 --- a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-pagerduty/src/main/java/org/apache/dolphinscheduler/plugin/alert/pagerduty/PagerDutySender.java +++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-pagerduty/src/main/java/org/apache/dolphinscheduler/plugin/alert/pagerduty/PagerDutySender.java @@ -18,6 +18,7 @@ package org.apache.dolphinscheduler.plugin.alert.pagerduty; import org.apache.dolphinscheduler.alert.api.AlertResult; +import org.apache.dolphinscheduler.alert.api.HttpServiceRetryStrategy; import org.apache.dolphinscheduler.common.utils.JSONUtils; import org.apache.http.HttpStatus; @@ -69,7 +70,8 @@ public final class PagerDutySender { private AlertResult send(AlertResult alertResult, String url, String requestBody) throws IOException { HttpPost httpPost = constructHttpPost(url, requestBody); - CloseableHttpClient httpClient = HttpClients.createDefault(); + CloseableHttpClient httpClient = + HttpClients.custom().setRetryHandler(HttpServiceRetryStrategy.retryStrategy).build(); try { CloseableHttpResponse response = httpClient.execute(httpPost); diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackSender.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackSender.java index aeb1782452..60b2f8281a 100644 --- a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackSender.java +++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackSender.java @@ -17,6 +17,7 @@ package org.apache.dolphinscheduler.plugin.alert.slack; +import org.apache.dolphinscheduler.alert.api.HttpServiceRetryStrategy; import org.apache.dolphinscheduler.common.utils.JSONUtils; import org.apache.commons.lang3.StringUtils; @@ -65,7 +66,9 @@ public final class SlackSender { * @return slack response */ public String sendMessage(String title, String content) { - try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + try ( + CloseableHttpClient httpClient = + HttpClients.custom().setRetryHandler(HttpServiceRetryStrategy.retryStrategy).build()) { Map paramMap = new HashMap<>(); paramMap.put(SlackParamsConstants.SLACK_BOT_NAME, botName); paramMap.put(SlackParamsConstants.TEXT, title); diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-telegram/src/main/java/org/apache/dolphinscheduler/plugin/alert/telegram/TelegramSender.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-telegram/src/main/java/org/apache/dolphinscheduler/plugin/alert/telegram/TelegramSender.java index cc85c8ea21..8aba9f5c2b 100644 --- a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-telegram/src/main/java/org/apache/dolphinscheduler/plugin/alert/telegram/TelegramSender.java +++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-telegram/src/main/java/org/apache/dolphinscheduler/plugin/alert/telegram/TelegramSender.java @@ -19,6 +19,7 @@ package org.apache.dolphinscheduler.plugin.alert.telegram; import org.apache.dolphinscheduler.alert.api.AlertData; import org.apache.dolphinscheduler.alert.api.AlertResult; +import org.apache.dolphinscheduler.alert.api.HttpServiceRetryStrategy; import org.apache.dolphinscheduler.common.utils.JSONUtils; import org.apache.commons.lang3.StringUtils; @@ -239,14 +240,15 @@ public final class TelegramSender { } private static CloseableHttpClient getDefaultClient() { - return HttpClients.createDefault(); + return HttpClients.custom().setRetryHandler(HttpServiceRetryStrategy.retryStrategy).build(); } private static CloseableHttpClient getProxyClient(String proxy, int port, String user, String password) { HttpHost httpProxy = new HttpHost(proxy, port); CredentialsProvider provider = new BasicCredentialsProvider(); provider.setCredentials(new AuthScope(httpProxy), new UsernamePasswordCredentials(user, password)); - return HttpClients.custom().setDefaultCredentialsProvider(provider).build(); + return HttpClients.custom().setRetryHandler(HttpServiceRetryStrategy.retryStrategy) + .setDefaultCredentialsProvider(provider).build(); } private static RequestConfig getProxyConfig(String proxy, int port) { diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/main/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexTeamsSender.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/main/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexTeamsSender.java index f651631c89..cd9ca87157 100644 --- a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/main/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexTeamsSender.java +++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/main/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexTeamsSender.java @@ -19,6 +19,7 @@ package org.apache.dolphinscheduler.plugin.alert.webexteams; import org.apache.dolphinscheduler.alert.api.AlertData; import org.apache.dolphinscheduler.alert.api.AlertResult; +import org.apache.dolphinscheduler.alert.api.HttpServiceRetryStrategy; import org.apache.dolphinscheduler.common.utils.JSONUtils; import org.apache.http.HttpStatus; @@ -77,7 +78,8 @@ public final class WebexTeamsSender { } private void send(AlertResult alertResult, AlertData alertData) throws IOException { - CloseableHttpClient httpClient = HttpClients.createDefault(); + CloseableHttpClient httpClient = + HttpClients.custom().setRetryHandler(HttpServiceRetryStrategy.retryStrategy).build(); try { HttpPost httpPost = constructHttpPost(getMessage(alertData), botAccessToken); diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSender.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSender.java index 67360aec9c..4b49e0436d 100644 --- a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSender.java +++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSender.java @@ -24,6 +24,7 @@ import static org.apache.dolphinscheduler.plugin.alert.wechat.WeChatAlertConstan import org.apache.dolphinscheduler.alert.api.AlertConstants; import org.apache.dolphinscheduler.alert.api.AlertResult; +import org.apache.dolphinscheduler.alert.api.HttpServiceRetryStrategy; import org.apache.dolphinscheduler.common.utils.JSONUtils; import org.apache.commons.lang3.StringUtils; @@ -80,7 +81,9 @@ public final class WeChatSender { } private static String post(String url, String data) throws IOException { - try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + try ( + CloseableHttpClient httpClient = + HttpClients.custom().setRetryHandler(HttpServiceRetryStrategy.retryStrategy).build()) { HttpPost httpPost = new HttpPost(url); httpPost.setEntity(new StringEntity(data, WeChatAlertConstants.CHARSET)); CloseableHttpResponse response = httpClient.execute(httpPost); @@ -133,7 +136,9 @@ public final class WeChatSender { private static String get(String url) throws IOException { String resp; - try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + try ( + CloseableHttpClient httpClient = + HttpClients.custom().setRetryHandler(HttpServiceRetryStrategy.retryStrategy).build();) { HttpGet httpGet = new HttpGet(url); try (CloseableHttpResponse response = httpClient.execute(httpGet)) { HttpEntity entity = response.getEntity();