All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.icodegarden.nutrient.elasticsearch.latest.ElasticsearchClientBuilder Maven / Gradle / Ivy

The newest version!
package io.github.icodegarden.nutrient.elasticsearch.latest;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.impl.nio.reactor.IOReactorConfig;
import org.apache.http.protocol.HttpContext;
import org.elasticsearch.client.Node;
import org.elasticsearch.client.NodeSelector;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestClientBuilder.HttpClientConfigCallback;
import org.springframework.util.StringUtils;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import io.github.icodegarden.nutrient.elasticsearch.ElasticsearchClientConfig;

/**
 * 
 * @author Fangfang.Xu
 *
 */
public class ElasticsearchClientBuilder {

	public static ElasticsearchClient buildElasticsearchClient(ElasticsearchClientConfig esProperties) {
		if (esProperties.getHttpHosts() == null) {
			throw new IllegalArgumentException("es httpHosts must be not empty");
		}

		try {
			String[] urls = esProperties.getHttpHosts().split(",");
			Node[] nodes = new Node[urls.length];
			for (int i = 0; i < urls.length; i++) {
				URI uri = new URI(urls[i]);
				nodes[i] = new Node(new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme()));
			}

			RestClientBuilder builder = RestClient.builder(nodes);
			/**
			 * 在使用云ES时,提供的是一个域名负载均衡地址(就像一个单节点地址),似乎应该把云ES的地址认为是一直可用
			 */
//			builder.setFailureListener(new RestClient.FailureListener() {
//			    @Override
//			    public void onFailure(Node node) {
//			        log.error("node:{} was failed", node);
//			    }
//			});
			builder.setNodeSelector(NodeSelector.ANY); // default
			builder.setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {
				@Override
				public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder requestConfigBuilder) {
					return requestConfigBuilder.setConnectionRequestTimeout(esProperties.getConnectionRequestTimeout())
							.setConnectTimeout(esProperties.getConnectTimeout())
							.setSocketTimeout(esProperties.getSocketTimeout());
				}
			});
			builder.setHttpClientConfigCallback(new HttpClientConfigCallback() {
				@Override
				public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
					if (StringUtils.hasText(esProperties.getPassword())) {
						CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
						credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(
								esProperties.getUsername(), esProperties.getPassword()));
						httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
					}
					if(esProperties.isKeepAlive()) {
						httpClientBuilder.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy() {
							@Override
							public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
								long keepAliveDuration = super.getKeepAliveDuration(response, context);
								if (keepAliveDuration < 0) {// < 0 无限,会跟服务端不一致报SocketTimeout
									return esProperties.getKeepAliveSeconds();
								}
								return keepAliveDuration;
							}
						});
					}
					
//					httpClientBuilder.setConnectionManager(connManager)
//					httpClientBuilder.setConnectionReuseStrategy(reuseStrategy)
					httpClientBuilder.setMaxConnPerRoute(esProperties.getMaxConnPerRoute());
					httpClientBuilder.setMaxConnTotal(esProperties.getMaxConnTotal());
//					httpClientBuilder.setDefaultIOReactorConfig(IOReactorConfig.custom().setIoThreadCount(1).build());
					return httpClientBuilder.setDefaultIOReactorConfig(IOReactorConfig.custom()
							.setIoThreadCount(Runtime.getRuntime().availableProcessors()/* default */).build());
				}
			});

			// Create the low-level client
			RestClient restClient = builder.build();

			// Create the transport with a Jackson mapper
			ElasticsearchTransport transport = new RestClientTransport(restClient,
					new JacksonJsonpMapper(newObjectMapper()));
			// And create the API client
			ElasticsearchClient client = new ElasticsearchClient(transport);

			return client;
		} catch (URISyntaxException e) {
			throw new IllegalArgumentException(e);
		}
	}

	private static ObjectMapper newObjectMapper() {
		final DateTimeFormatter STANDARD_DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		ObjectMapper om = new ObjectMapper();
		om = new ObjectMapper();
		om.setSerializationInclusion(Include.NON_NULL);
		om.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
		om.configure(SerializationFeature.FLUSH_AFTER_WRITE_VALUE, true);
		om.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

		JavaTimeModule timeModule = new JavaTimeModule();
		timeModule.addSerializer(LocalDateTime.class, new JsonSerializer() {
			@Override
			public void serialize(LocalDateTime localDateTime, JsonGenerator jsonGenerator,
					SerializerProvider serializerProvider) throws IOException {
				jsonGenerator.writeString(STANDARD_DATETIME_FORMATTER.format(localDateTime));
			}
		});
		timeModule.addDeserializer(LocalDateTime.class, new JsonDeserializer() {
			@Override
			public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
					throws IOException, JsonProcessingException {
				String valueAsString = jsonParser.getValueAsString();
				return LocalDateTime.parse(valueAsString, STANDARD_DATETIME_FORMATTER);
			}
		});
		om.registerModule(timeModule);

		return om;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy