通用配置
正如初始化中所解释的,RestClientBuilder
支持提供RequestConfigCallback
和HttpClientConfigCallback
,它们允许Apache Async Http Client公开的任何自定义。这些回调可以修改客户端的某些特定行为,而不会覆盖RestClient
初始化的所有其他默认配置,本节介绍一些需要为低级别Java REST Client进行其他配置的常见方案。
超时
配置请求超时可以通过在通过其构建器构建RestClient
时提供RequestConfigCallback
实例来完成,该接口有一个方法接收org.apache.http.client.config.RequestConfig.Builder的实例作为参数并具有相同的返回类型,可以修改请求配置构建器,然后返回。在以下示例中,我们将增加连接超时(默认为1秒)和socket超时(默认为30秒),我们也相应地调整最大重试超时(默认为30秒)。
RestClientBuilder builder = RestClient.builder(
new HttpHost("localhost", 9200))
.setRequestConfigCallback(
new RestClientBuilder.RequestConfigCallback() {
@Override
public RequestConfig.Builder customizeRequestConfig(
RequestConfig.Builder requestConfigBuilder) {
return requestConfigBuilder
.setConnectTimeout(5000)
.setSocketTimeout(60000);
}
})
.setMaxRetryTimeoutMillis(60000);
线程数
Apache Http Async Client默认启动一个调度线程,以及连接管理器使用的许多工作线程,与本地检测到的处理器数量一样多(取决于Runtime.getRuntime().availableProcessors()
的返回),线程数可以修改如下:
RestClientBuilder builder = RestClient.builder(
new HttpHost("localhost", 9200))
.setHttpClientConfigCallback(new HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(
HttpAsyncClientBuilder httpClientBuilder) {
return httpClientBuilder.setDefaultIOReactorConfig(
IOReactorConfig.custom()
.setIoThreadCount(1)
.build());
}
});
基本认证
配置基本身份验证可以通过在通过其构建器构建RestClient
时提供HttpClientConfigCallback
来完成,该接口有一个方法接收org.apache.http.impl.nio.client.HttpAsyncClientBuilder的实例作为参数并具有相同的返回类型,可以修改http
客户端构建器,然后返回。在以下示例中,我们设置了需要基本身份验证的默认凭据提供程序。
final CredentialsProvider credentialsProvider =
new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials("user", "password"));
RestClientBuilder builder = RestClient.builder(
new HttpHost("localhost", 9200))
.setHttpClientConfigCallback(new HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(
HttpAsyncClientBuilder httpClientBuilder) {
return httpClientBuilder
.setDefaultCredentialsProvider(credentialsProvider);
}
});
可以禁用抢占式身份验证,这意味着每个请求都将在没有授权标头的情况下发送,以查看是否接受该请求,并且在接收到HTTP401
响应后,将重新发送与基本身份验证标头完全相同的请求,如果你希望这样做,那么你可以通过HttpAsyncClientBuilder
禁用它:
final CredentialsProvider credentialsProvider =
new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials("user", "password"));
RestClientBuilder builder = RestClient.builder(
new HttpHost("localhost", 9200))
.setHttpClientConfigCallback(new HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(
HttpAsyncClientBuilder httpClientBuilder) {
httpClientBuilder.disableAuthCaching();
return httpClientBuilder
.setDefaultCredentialsProvider(credentialsProvider);
}
});
httpClientBuilder.disableAuthCaching();
— 禁用抢占式身份验证。
加密通信
也可以通过HttpClientConfigCallback
配置加密通信,作为参数接收的org.apache.http.impl.nio.client.HttpAsyncClientBuilder公开了多种方法来配置加密通信:setSSLContext
、setSSLSessionStrategy
和setConnectionManager
,按照最不重要的优先顺序排列,以下是一个例子:
KeyStore truststore = KeyStore.getInstance("jks");
try (InputStream is = Files.newInputStream(keyStorePath)) {
truststore.load(is, keyStorePass.toCharArray());
}
SSLContextBuilder sslBuilder = SSLContexts.custom()
.loadTrustMaterial(truststore, null);
final SSLContext sslContext = sslBuilder.build();
RestClientBuilder builder = RestClient.builder(
new HttpHost("localhost", 9200, "https"))
.setHttpClientConfigCallback(new HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(
HttpAsyncClientBuilder httpClientBuilder) {
return httpClientBuilder.setSSLContext(sslContext);
}
});
如果未提供显式配置,则将使用系统默认配置。
其他
对于所需的任何其他必需配置,应参考Apache HttpAsyncClient文档:https://hc.apache.org/httpcomponents-asyncclient-4.1.x/。
如果你的应用程序在安全管理器下运行,则可能会受到JVM默认策略的限制,即无限期缓存正主机名解析和负主机名解析10秒,如果你连接客户端的主机的已解析地址随时间变化,那么你可能希望修改默认的JVM行为,可以通过将networkaddress.cache.ttl=<timeout>和networkaddress.cache.negative.ttl=<timeout>添加到Java安全策略来修改这些。
节点选择器
客户端以循环方式将每个请求发送到其中一个配置的节点,可以选择通过初始化客户端时需要提供的节点选择器来过滤节点,这在启用嗅探时很有用,以防只有HTTP请求才能触发专用主节点。对于每个请求,客户端将运行最终配置的节点选择器以过滤候选节点,然后从剩余的节点中选择列表中的下一个节点。
RestClientBuilder builder = RestClient.builder(
new HttpHost("localhost", 9200, "http"));
builder.setNodeSelector(new NodeSelector() {
@Override
public void select(Iterable<Node> nodes) {
/*
* Prefer any node that belongs to rack_one. If none is around
* we will go to another rack till it's time to try and revive
* some of the nodes that belong to rack_one.
*/
boolean foundOne = false;
for (Node node : nodes) {
String rackId = node.getAttributes().get("rack_id").get(0);
if ("rack_one".equals(rackId)) {
foundOne = true;
break;
}
}
if (foundOne) {
Iterator<Node> nodesIt = nodes.iterator();
while (nodesIt.hasNext()) {
Node node = nodesIt.next();
String rackId = node.getAttributes().get("rack_id").get(0);
if ("rack_one".equals(rackId) == false) {
nodesIt.remove();
}
}
}
}
});
设置分配感知节点选择器,允许选择本地rack中的节点(如果有),否则转到任何rack中的任何其他节点。它充当偏好而不是严格的要求,如果没有任何本地节点可用,它将进入另一个rack,而不是在这种情况下不返回任何节点,这将使客户端在首选rack中没有任何节点可用时强制恢复本地节点。
不一致地选择相同节点集的节点选择器将使循环行为变得不可预测并且可能不公平,上面的偏好示例很好,因为它可以解释已经影响轮询调度可预测性的节点的可用性,节点选择不应该依赖于其他外部因素,否则轮询调度将无法正常工作。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。