正如初始化中所解释的,RestClientBuilder
支持提供RequestConfigCallback
和HttpClientConfigCallback
,它们容许Apache Async Http Client公开的任何自定义。这些回调能够修改客户端的某些特定行为,而不会覆盖RestClient
初始化的全部其余默认配置,本节介绍一些须要为低级别Java REST Client进行其余配置的常见方案。html
配置请求超时能够经过在经过其构建器构建RestClient
时提供RequestConfigCallback
实例来完成,该接口有一个方法接收org.apache.http.client.config.RequestConfig.Builder的实例做为参数并具备相同的返回类型,能够修改请求配置构建器,而后返回。在如下示例中,咱们将增长链接超时(默认为1秒)和socket超时(默认为30秒),咱们也相应地调整最大重试超时(默认为30秒)。java
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()
的返回),线程数能够修改以下:node
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
客户端构建器,而后返回。在如下示例中,咱们设置了须要基自己份验证的默认凭据提供程序。apache
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
禁用它:segmentfault
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();
— 禁用抢占式身份验证。api
也能够经过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/。oracle
若是你的应用程序在安全管理器下运行,则可能会受到JVM默认策略的限制,即无限期缓存正主机名解析和负主机名解析10秒,若是你链接客户端的主机的已解析地址随时间变化,那么你可能但愿修改默认的JVM行为,能够经过将 networkaddress.cache.ttl=<timeout>和 networkaddress.cache.negative.ttl=<timeout>添加到 Java安全策略来修改这些。
客户端以循环方式将每一个请求发送到其中一个配置的节点,能够选择经过初始化客户端时须要提供的节点选择器来过滤节点,这在启用嗅探时颇有用,以防只有HTTP请求才能触发专用主节点。对于每一个请求,客户端将运行最终配置的节点选择器以过滤候选节点,而后从剩余的节点中选择列表中的下一个节点。socket
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中没有任何节点可用时强制恢复本地节点。
不一致地选择相同节点集的节点选择器将使循环行为变得不可预测而且可能不公平,上面的偏好示例很好,由于它能够解释已经影响轮询调度可预测性的节点的可用性,节点选择不该该依赖于其余外部因素,不然轮询调度将没法正常工做。