SpringBoot集成多个Elasticsearch7.6.2
如果是集成一个或者Elasticsearch集群,可以用springboot的自动装配。以下是集成多个毫无关系的elasticsearch客户端
- pom.xml导入依赖
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.6.2</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.6.2</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>4.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.8.0</version>
</dependency>
- 配置config工厂类
import lombok.Data;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import java.time.Duration;;
/**
* ES配置
*/
@Data
@Configuration
@Component
@ConfigurationProperties(prefix = "elasticsearch")
public class EsConfig {
public static final String ES_CLIENT_1 = "es_client_1";
public static final String ES_CLIENT_2 = "es_client_2";
private Connect connect1;
private Connect connect2;
/**
* 客户端1
*/
@Bean(name = ES_CLIENT_1, destroyMethod = "close")
public GenericObjectPool<RestHighLevelClient> genericObjectPool1() {
return esPool(factoryClient(connect1), config());
}
/**
* 客户端2
*/
@Bean(name = ES_CLIENT_2, destroyMethod = "close")
public GenericObjectPool<RestHighLevelClient> genericObjectPool2() {
return esPool(factoryClient(connect2), config());
}
private GenericObjectPool<RestHighLevelClient> esPool(PooledObjectFactory<RestHighLevelClient> factory, GenericObjectPoolConfig config) {
return new GenericObjectPool<>(factory, config);
}
private GenericObjectPoolConfig config() {
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
poolConfig.setMinIdle(5);
poolConfig.setMaxIdle(20);
poolConfig.setMaxTotal(500);
poolConfig.setMaxWaitMillis(3000L);
poolConfig.setJmxEnabled(false);
return poolConfig;
}
private PooledObjectFactory<RestHighLevelClient> factoryClient(Connect connect) {
return new BasePooledObjectFactory<RestHighLevelClient>() {
@Override
public void destroyObject(PooledObject<RestHighLevelClient> pooledObject) throws Exception {
RestHighLevelClient highLevelClient = pooledObject.getObject();
highLevelClient.close();
}
@Override
public RestHighLevelClient create() throws Exception {
return getRestHighLevelClient(connect);
}
@Override
public PooledObject<RestHighLevelClient> wrap(RestHighLevelClient restHighLevelClient) {
return new DefaultPooledObject<>(restHighLevelClient);
}
};
}
private RestHighLevelClient getRestHighLevelClient(Connect connect) {
HttpHost host = HttpHost.create(connect.hosts);
RestClientBuilder builder = RestClient.builder(host);
// 异步连接延时配置
builder.setRequestConfigCallback(requestConfigBuilder -> {
requestConfigBuilder.setConnectTimeout(connect.connectTimeout);
requestConfigBuilder.setSocketTimeout(connect.socketTimeout);
requestConfigBuilder.setConnectionRequestTimeout(connect.connectionRequestTimeout);
return requestConfigBuilder;
});
// 异步连接数配置
builder.setHttpClientConfigCallback(httpClientBuilder -> {
httpClientBuilder.setMaxConnTotal(connect.maxConnectNum);
httpClientBuilder.setMaxConnPerRoute(connect.maxConnectPerRoute);
httpClientBuilder.setKeepAliveStrategy(((response, context) -> Duration.ofMinutes(3).toMillis()));
return httpClientBuilder;
});
return new RestHighLevelClient(builder);
}
@Data
public static class Connect {
private String hosts;
/**
* 连接超时时间
*/
private int connectTimeout;
/**
* Socket 连接超时时间
*/
private int socketTimeout;
/**
* 获取连接的超时时间
*/
private int connectionRequestTimeout;
/**
* 最大连接数
*/
private int maxConnectNum;
/**
* 最大路由连接数
*/
private int maxConnectPerRoute;
}
}
ES连接池:
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
public class EsClientPool {
@Autowired
@Qualifier(ElasticsearchConfig.ES_CLIENT_1)
private GenericObjectPool<RestHighLevelClient> genericObjectPool1;
@Autowired
@Qualifier(ElasticsearchConfig.ES_CLIENT_2)
private GenericObjectPool<RestHighLevelClient> genericObjectPool2;
/**
* 获得对象
*
* @return
* @throws Exception
*/
public RestHighLevelClient getClient(Integer a) throws Exception {
// 从池中取一个对象
if(a==1){
return genericObjectPool1.borrowObject();
}else {
return genericObjectPool2.borrowObject();
}
}
/**
* 归还对象
*
* @param client
*/
public void returnClient(RestHighLevelClient client, Integer a) {
// 使用完毕之后,归还对象
if (a== 1) {
genericObjectPool1.returnObject(client);
} else {
genericObjectPool2.returnObject(client);
}
}
}
- 在yml中加入以下配置
elasticsearch:
connect1:
hosts: http://127.0.0.1:9200
connectTimeout: 10000
socketTimeout: 10000
connectionRequestTimeout: 1000
maxConnectNum: 500
maxConnectPerRoute: 200
connect2:
hosts: http://127.0.0.1:9200
connectTimeout: 10000
socketTimeout: 10000
connectionRequestTimeout: 1000
maxConnectNum: 500
maxConnectPerRoute: 200
- 需在springboot中的启动类中关闭ES的自动装配(在@SpringBootApplication注解加上exclude = {RestClientAutoConfiguration.class, ElasticsearchDataAutoConfiguration.class})跟用上@EnableConfigurationProperties(EsConfig.class)
@EnableConfigurationProperties(EsConfig.class)
@SpringBootApplication(exclude = {RestClientAutoConfiguration.class, ElasticsearchDataAutoConfiguration.class})
public class XXXXApplication {}
5.在impl中写(索引如果是通配符*方式请注意如果索引太多个可能会查询超时):
@Service
@Slf4j
public class EsImpl {
@Autowired
private EsClientPool esClientPool;
public void getEs(DTO dto) {
BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
// 创建搜索请求对象
SearchRequest request = new SearchRequest();
//索引名称,通配符*方式请注意如果索引太多个可能超时
request.indices("XXX_2022-10*");
// 构建查询的请求体
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//多条件设置
boolBuilder.must(QueryBuilders.termQuery("xxx", dto.getXXX()));
sourceBuilder.sort("createDate", SortOrder.DESC);
sourceBuilder.from(dto.getPageIndex()-1);
sourceBuilder.size(dto.getPageSize());
sourceBuilder.query(boolBuilder);
request.source(sourceBuilder);
RestHighLevelClient client = null;
SearchResponse response = null;
try {
// 1跟2分别代表不同的客户端
client = esClientPool.getClient(1);
response = esClientPool.getClient(1).search(request, RequestOptions.DEFAULT);
} catch (Exception e) {
log.error("ES search fail=", e);
} finally {
if (client != null) {
esClientPool.returnClient(client, 1);
}
}
SearchHits hits = response.getHits();
}
}