序
本文主要研究一下 nacos 的 RaftProxy
RaftProxy
nacos-1.1.3/naming/src/main/java/com/alibaba/nacos/naming/consistency/persistent/raft/RaftProxy.java
@Component
public class RaftProxy {public void proxyGET(String server, String api, Map<String, String> params) throws Exception {
// do proxy
if (!server.contains(UtilsAndCommons.IP_PORT_SPLITER)) {server = server + UtilsAndCommons.IP_PORT_SPLITER + RunningConfig.getServerPort();
}
String url = "http://" + server + RunningConfig.getContextPath() + api;
HttpClient.HttpResult result = HttpClient.httpGet(url, null, params);
if (result.code != HttpURLConnection.HTTP_OK) {throw new IllegalStateException("leader failed, caused by:" + result.content);
}
}
public void proxy(String server, String api, Map<String, String> params, HttpMethod method) throws Exception {
// do proxy
if (!server.contains(UtilsAndCommons.IP_PORT_SPLITER)) {server = server + UtilsAndCommons.IP_PORT_SPLITER + RunningConfig.getServerPort();
}
String url = "http://" + server + RunningConfig.getContextPath() + api;
HttpClient.HttpResult result;
switch (method) {
case GET:
result = HttpClient.httpGet(url, null, params);
break;
case POST:
result = HttpClient.httpPost(url, null, params);
break;
case DELETE:
result = HttpClient.httpDelete(url, null, params);
break;
default:
throw new RuntimeException("unsupported method:" + method);
}
if (result.code != HttpURLConnection.HTTP_OK) {throw new IllegalStateException("leader failed, caused by:" + result.content);
}
}
public void proxyPostLarge(String server, String api, String content, Map<String, String> headers) throws Exception {
// do proxy
if (!server.contains(UtilsAndCommons.IP_PORT_SPLITER)) {server = server + UtilsAndCommons.IP_PORT_SPLITER + RunningConfig.getServerPort();
}
String url = "http://" + server + RunningConfig.getContextPath() + api;
HttpClient.HttpResult result = HttpClient.httpPostLarge(url, headers, content);
if (result.code != HttpURLConnection.HTTP_OK) {throw new IllegalStateException("leader failed, caused by:" + result.content);
}
}
}
- RaftProxy 提供了 proxyGET、proxy、proxyPostLarge 三个方法,其中 proxy 接收了 HttpMethod,可以处理 GET、POST、DELETE
HttpClient
nacos-1.1.3/naming/src/main/java/com/alibaba/nacos/naming/misc/HttpClient.java
public class HttpClient {
private static final int TIME_OUT_MILLIS = 10000;
private static final int CON_TIME_OUT_MILLIS = 5000;
private static AsyncHttpClient asyncHttpClient;
private static CloseableHttpClient postClient;
static {AsyncHttpClientConfig.Builder builder = new AsyncHttpClientConfig.Builder();
builder.setMaximumConnectionsTotal(-1);
builder.setMaximumConnectionsPerHost(128);
builder.setAllowPoolingConnection(true);
builder.setFollowRedirects(false);
builder.setIdleConnectionTimeoutInMs(TIME_OUT_MILLIS);
builder.setConnectionTimeoutInMs(CON_TIME_OUT_MILLIS);
builder.setCompressionEnabled(true);
builder.setIOThreadMultiplier(1);
builder.setMaxRequestRetry(0);
builder.setUserAgent(UtilsAndCommons.SERVER_VERSION);
asyncHttpClient = new AsyncHttpClient(builder.build());
HttpClientBuilder builder2 = HttpClients.custom();
builder2.setUserAgent(UtilsAndCommons.SERVER_VERSION);
builder2.setConnectionTimeToLive(CON_TIME_OUT_MILLIS, TimeUnit.MILLISECONDS);
builder2.setMaxConnPerRoute(-1);
builder2.setMaxConnTotal(-1);
builder2.disableAutomaticRetries();
postClient = builder2.build();}
//......
public static HttpResult httpPost(String url, List<String> headers, Map<String, String> paramValues) {return httpPost(url, headers, paramValues, "UTF-8");
}
public static HttpResult httpPost(String url, List<String> headers, Map<String, String> paramValues, String encoding) {
try {HttpPost httpost = new HttpPost(url);
RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(5000).setConnectTimeout(5000).setSocketTimeout(5000).setRedirectsEnabled(true).setMaxRedirects(5).build();
httpost.setConfig(requestConfig);
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
for (Map.Entry<String, String> entry : paramValues.entrySet()) {nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
httpost.setEntity(new UrlEncodedFormEntity(nvps, encoding));
HttpResponse response = postClient.execute(httpost);
HttpEntity entity = response.getEntity();
String charset = encoding;
if (entity.getContentType() != null) {HeaderElement[] headerElements = entity.getContentType().getElements();
if (headerElements != null && headerElements.length > 0 && headerElements[0] != null &&
headerElements[0].getParameterByName("charset") != null) {charset = headerElements[0].getParameterByName("charset").getValue();}
}
return new HttpResult(response.getStatusLine().getStatusCode(), IOUtils.toString(entity.getContent(), charset), Collections.<String, String>emptyMap());
} catch (Throwable e) {return new HttpResult(500, e.toString(), Collections.<String, String>emptyMap());
}
}
public static HttpResult httpPostLarge(String url, Map<String, String> headers, String content) {
try {HttpClientBuilder builder = HttpClients.custom();
builder.setUserAgent(UtilsAndCommons.SERVER_VERSION);
builder.setConnectionTimeToLive(500, TimeUnit.MILLISECONDS);
CloseableHttpClient httpClient = builder.build();
HttpPost httpost = new HttpPost(url);
for (Map.Entry<String, String> entry : headers.entrySet()) {httpost.setHeader(entry.getKey(), entry.getValue());
}
httpost.setEntity(new StringEntity(content, ContentType.create("application/json", "UTF-8")));
HttpResponse response = httpClient.execute(httpost);
HttpEntity entity = response.getEntity();
HeaderElement[] headerElements = entity.getContentType().getElements();
String charset = headerElements[0].getParameterByName("charset").getValue();
return new HttpResult(response.getStatusLine().getStatusCode(),
IOUtils.toString(entity.getContent(), charset), Collections.<String, String>emptyMap());
} catch (Exception e) {return new HttpResult(500, e.toString(), Collections.<String, String>emptyMap());
}
}
//......
}
- httpPost 的 connectionRequestTimeout 为 5 秒,connectTimeout 为 5 秒,socketTimeout 为 5 秒;httpPostLarge 设置了 500 毫秒的 connectionTimeToLive
小结
RaftProxy 提供了 proxyGET、proxy、proxyPostLarge 三个方法,其中 proxy 接收了 HttpMethod,可以处理 GET、POST、DELETE
doc
- RaftProxy