package com.alibaba.doris.common.adminservice.connenctor;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.alibaba.doris.common.util.IPAddressUtil;
public class AdminConnector {
private static final Log logger = LogFactory.getLog(AdminConnector.class);
private static AdminConnector instance = new AdminConnector();
//fetcher to acess remote admin server for configuration changes.(main)
private ConfigFetcher mainAdminFetcher = new ConfigFetcher();
//The back up admin fetcher
private ConfigFetcher backupAdminFetcher = new ConfigFetcher();
public static AdminConnector getInstance() {
return instance;
}
private AdminConnector() {
}
public void init(Properties properties) {
// initialize main fetcher
String mainAdminUrl = properties.getProperty("doris.config.adminserver.main.url");
if (mainAdminUrl != null) {
properties.put("doris.config.adminserver.url", mainAdminUrl);
}
mainAdminFetcher.init(properties);
// initialize backup fetcher
String backupAdminUrl = properties.getProperty("doris.config.adminserver.backup.url");
if (backupAdminUrl != null) {
properties.put("doris.config.adminserver.url", backupAdminUrl);
}
backupAdminFetcher.init(properties);
}
public String requst(Map<String, String> paramMap) {
List<NameValuePair> paras = new ArrayList<NameValuePair>();
for (Map.Entry<String, String> entry : paramMap.entrySet()) {
NameValuePair para = new NameValuePair();
para.setName(entry.getKey());
para.setValue(entry.getValue());
paras.add(para);
}
String result = null;
NameValuePair[] parasArray = paras.toArray(new NameValuePair[] {});
try {
result = this.mainAdminFetcher.fetch(parasArray);
} catch (AdminConnectionException e) {
try {
result = this.backupAdminFetcher.fetch(parasArray);
} catch (Exception e1) {
// Swallow all exception
logger.error("Cannot acess both main admin server and back admin server.", e1);
}
}
return result;
}
public boolean isConnected() {
NameValuePair[] params = new NameValuePair[1];
params[0] = new NameValuePair("test", "test");
return this.mainAdminFetcher.checkConnection(params)
|| this.backupAdminFetcher.checkConnection(params);
}
private class ConfigFetcher {
public String accessUrl;
private final MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
private final HttpClient httpClient = new HttpClient(
connectionManager);
private String hostAddress;
private String hostName;
private int retry = 3;
public void init(Properties properties) {
if (logger.isInfoEnabled()) {
logger.info("admin connector initization starts.");
}
if (properties == null) {
throw new IllegalArgumentException("The connector properties could not be null");
}
// admin server access url
this.accessUrl = properties.getProperty("doris.config.adminserver.url");
if (StringUtils.isEmpty(accessUrl)) {
throw new IllegalArgumentException("confg 'doris.config.adminserver.url' is not valid.");
}
// fetch retry times.
String retryTimesConfig = properties.getProperty("doris.config.fetch.retrytimes", "3");
this.retry = Integer.parseInt(retryTimesConfig.trim());
// connection time out
String connectionTimeoutConfig = properties.getProperty("doris.config.connection.timeout");
if (StringUtils.isEmpty(connectionTimeoutConfig)) {
throw new IllegalArgumentException(
"confg 'doris.config.connection.timeout' is not valid.");
}
Integer connectionTimeout = Integer.parseInt(connectionTimeoutConfig.trim());
// socket time out
String soTimeoutConfig = properties.getProperty("doris.config.connection.socket.timeout");
if (StringUtils.isEmpty(soTimeoutConfig)) {
throw new IllegalArgumentException(
"confg 'doris.config.connection.socket.timeout' is not valid.");
}
Integer soTimeout = Integer.parseInt(soTimeoutConfig.trim());
// 设置连接超时时间
connectionManager.getParams().setConnectionTimeout(connectionTimeout);
// 设置读数据超时时间
connectionManager.getParams().setSoTimeout(soTimeout);
// 抓取客户端的主机信息
try {
InetAddress localhost = InetAddress.getLocalHost();
hostName = localhost.getHostName();
} catch (UnknownHostException e) {
if (logger.isWarnEnabled()) {
logger.warn("Fail to get host name:" + e.getMessage());
}
}
if (hostName == null) {
hostName = "unknown";
}
try {
hostAddress = IPAddressUtil.getIPAddress();
} catch (Exception e) {
if (logger.isWarnEnabled()) {
logger.warn("Error while getting host address:" + e.getMessage());
}
}
if (hostAddress == null) {
hostAddress = "unknown";
}
if (logger.isInfoEnabled()) {
logger.info("admin connector client hostName:" + hostName + ",hostAddress:" + hostAddress);
}
}
private String fetch(NameValuePair[] params) throws AdminConnectionException {
PostMethod method = new PostMethod(accessUrl);
String result = null;
try {
method.addParameters(params);
String errMsg = null;
int retried = retry;
while (retried > 0) {
try {
int statusCode = httpClient.executeMethod(method);
if (statusCode != HttpStatus.SC_OK) {
errMsg = "Fail to request from server: status code(" + statusCode
+ "), status line(" + method.getStatusLine() + ")";
logger.warn(errMsg);
}
result = method.getResponseBodyAsString();
retried = 0;
} catch (Exception e) {
retried--;
errMsg = "Fail to request from server: " + accessUrl;
logger.error(errMsg, e);
if (retried == 0) {
throw new AdminConnectionException("Cannot connect to Admin:"
+ accessUrl);
}
}
}
} finally {
method.releaseConnection();
}
return result;
}
private boolean checkConnection(NameValuePair[] params) {
HttpMethodBase method = new PostMethod(accessUrl);
boolean connected = false;
try {
method.setQueryString(params);
String errMsg = null;
int retried = retry;
while (retried > 0) {
if (connected == true) {
break;
}
boolean hasException = false;
try {
int statusCode = httpClient.executeMethod(method);
if (statusCode != HttpStatus.SC_OK) {
errMsg = "Fail to request from server: status code(" + statusCode
+ "), status line(" + method.getStatusLine() + ")";
logger.warn(errMsg);
}
retried = 0;
} catch (ConnectException e) {
retried--;
errMsg = "Fail to request from admin server: " + accessUrl;
logger.error(errMsg, e);
hasException = true;
} catch (Exception e) {
retried = 0;
errMsg = "Fail to request from server: " + accessUrl;
hasException = true;
logger.error(errMsg, e);
}
if (!hasException) {
connected = true;
}
}
} finally {
method.releaseConnection();
}
if (logger.isInfoEnabled()) {
logger.info("Admin Server \"" + accessUrl + "\" can be connected? " + connected);
}
return connected;
}
}
}