perf(es): 优化品牌聚合查询和网络连接配置
-增加 connectionRequestTimeout 配置,设置为 1000 毫秒 -调整 maxConnPerRoute 为 50,maxConnTotal为 200 -限制 terms 聚合 size,防止内存压力 - 优化品牌聚合查询逻辑,提高查询效率和准确性
This commit is contained in:
@@ -15,15 +15,6 @@
|
|||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
|
||||||
<groupId>com.qiniu</groupId>
|
|
||||||
<artifactId>qiniu-java-sdk</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.qiniu</groupId>
|
|
||||||
<artifactId>qiniu-java-sdk</artifactId>
|
|
||||||
<version>7.4.0</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-properties-migrator</artifactId>
|
<artifactId>spring-boot-properties-migrator</artifactId>
|
||||||
|
|||||||
@@ -66,14 +66,16 @@ public class ElasticsearchConfig extends AbstractElasticsearchConfiguration {
|
|||||||
.setRequestConfigCallback(requestConfigBuilder ->
|
.setRequestConfigCallback(requestConfigBuilder ->
|
||||||
requestConfigBuilder
|
requestConfigBuilder
|
||||||
.setConnectTimeout(1000)
|
.setConnectTimeout(1000)
|
||||||
.setSocketTimeout(12 * 1000));
|
.setSocketTimeout(12 * 1000)
|
||||||
|
.setConnectionRequestTimeout(1000));
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpAsyncClientBuilder configureHttpClientBuilder(HttpAsyncClientBuilder httpClientBuilder,
|
private HttpAsyncClientBuilder configureHttpClientBuilder(HttpAsyncClientBuilder httpClientBuilder,
|
||||||
CredentialsProvider credentialsProvider) {
|
CredentialsProvider credentialsProvider) {
|
||||||
httpClientBuilder
|
httpClientBuilder
|
||||||
.setKeepAliveStrategy(getConnectionKeepAliveStrategy())
|
.setKeepAliveStrategy(getConnectionKeepAliveStrategy())
|
||||||
.setMaxConnPerRoute(10)
|
.setMaxConnPerRoute(50)
|
||||||
|
.setMaxConnTotal(200)
|
||||||
.setDefaultIOReactorConfig(
|
.setDefaultIOReactorConfig(
|
||||||
IOReactorConfig
|
IOReactorConfig
|
||||||
.custom()
|
.custom()
|
||||||
|
|||||||
@@ -68,6 +68,8 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
|
|||||||
private static final String ATTR_BRAND_URL = "brandUrlAgg";
|
private static final String ATTR_BRAND_URL = "brandUrlAgg";
|
||||||
private static final String ATTR_NAME_KEY = "nameList";
|
private static final String ATTR_NAME_KEY = "nameList";
|
||||||
private static final String ATTR_VALUE_KEY = "valueList";
|
private static final String ATTR_VALUE_KEY = "valueList";
|
||||||
|
// 限制 terms 聚合 size,防止内存压力
|
||||||
|
private static final int MAX_AGG_SIZE = 200;
|
||||||
/**
|
/**
|
||||||
* ES
|
* ES
|
||||||
*/
|
*/
|
||||||
@@ -122,23 +124,24 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
|
|||||||
if (!restTemplate.indexOps(EsGoodsIndex.class).exists()) {
|
if (!restTemplate.indexOps(EsGoodsIndex.class).exists()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
NativeSearchQueryBuilder builder = createSearchQueryBuilder(goodsSearch, null);
|
NativeSearchQueryBuilder builder = createSearchQueryBuilder(goodsSearch, null);
|
||||||
//分类
|
//分类
|
||||||
AggregationBuilder categoryNameBuilder = AggregationBuilders.terms("categoryNameAgg").field("categoryNamePath.keyword");
|
AggregationBuilder categoryNameBuilder = AggregationBuilders.terms("categoryNameAgg").field("categoryNamePath.keyword").size(MAX_AGG_SIZE);
|
||||||
builder.addAggregation(AggregationBuilders.terms("categoryAgg").field("categoryPath").subAggregation(categoryNameBuilder));
|
builder.addAggregation(AggregationBuilders.terms("categoryAgg").field("categoryPath").size(MAX_AGG_SIZE).subAggregation(categoryNameBuilder));
|
||||||
|
|
||||||
//品牌
|
//品牌
|
||||||
AggregationBuilder brandNameBuilder = AggregationBuilders.terms(ATTR_BRAND_NAME).field("brandName.keyword");
|
AggregationBuilder brandNameBuilder = AggregationBuilders.terms(ATTR_BRAND_NAME).field("brandName.keyword").size(1);
|
||||||
builder.addAggregation(AggregationBuilders.terms("brandIdNameAgg").field(ATTR_BRAND_ID).size(Integer.MAX_VALUE).subAggregation(brandNameBuilder));
|
builder.addAggregation(AggregationBuilders.terms("brandIdNameAgg").field(ATTR_BRAND_ID).size(MAX_AGG_SIZE).subAggregation(brandNameBuilder));
|
||||||
|
|
||||||
AggregationBuilder brandUrlBuilder = AggregationBuilders.terms(ATTR_BRAND_URL).field("brandUrl.keyword");
|
AggregationBuilder brandUrlBuilder = AggregationBuilders.terms(ATTR_BRAND_URL).field("brandUrl.keyword").size(1);
|
||||||
builder.addAggregation(AggregationBuilders.terms("brandIdUrlAgg").field(ATTR_BRAND_ID).size(Integer.MAX_VALUE).subAggregation(brandUrlBuilder));
|
builder.addAggregation(AggregationBuilders.terms("brandIdUrlAgg").field(ATTR_BRAND_ID).size(MAX_AGG_SIZE).subAggregation(brandUrlBuilder));
|
||||||
//参数
|
//参数
|
||||||
AggregationBuilder valuesBuilder = AggregationBuilders.terms("valueAgg").field(ATTR_VALUE);
|
AggregationBuilder valuesBuilder = AggregationBuilders.terms("valueAgg").field(ATTR_VALUE).size(MAX_AGG_SIZE);
|
||||||
AggregationBuilder sortBuilder = AggregationBuilders.sum("sortAgg").field(ATTR_SORT);
|
AggregationBuilder sortBuilder = AggregationBuilders.sum("sortAgg").field(ATTR_SORT);
|
||||||
AggregationBuilder paramsNameBuilder = AggregationBuilders.terms("nameAgg").field(ATTR_NAME).subAggregation(sortBuilder).order(BucketOrder.aggregation("sortAgg", false)).subAggregation(valuesBuilder);
|
AggregationBuilder paramsNameBuilder = AggregationBuilders.terms("nameAgg").field(ATTR_NAME).size(MAX_AGG_SIZE)
|
||||||
|
.subAggregation(sortBuilder).order(BucketOrder.aggregation("sortAgg", false)).subAggregation(valuesBuilder);
|
||||||
builder.addAggregation(AggregationBuilders.nested("attrAgg", ATTR_PATH).subAggregation(paramsNameBuilder));
|
builder.addAggregation(AggregationBuilders.nested("attrAgg", ATTR_PATH).subAggregation(paramsNameBuilder));
|
||||||
|
|
||||||
NativeSearchQuery searchQuery = builder.build();
|
NativeSearchQuery searchQuery = builder.build();
|
||||||
searchQuery.setMaxResults(0);
|
searchQuery.setMaxResults(0);
|
||||||
SearchHits<EsGoodsIndex> search = restTemplate.search(searchQuery, EsGoodsIndex.class);
|
SearchHits<EsGoodsIndex> search = restTemplate.search(searchQuery, EsGoodsIndex.class);
|
||||||
@@ -227,35 +230,57 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
|
|||||||
*/
|
*/
|
||||||
private List<SelectorOptions> convertBrandOptions(EsGoodsSearchDTO goodsSearch, List<? extends Terms.Bucket> brandBuckets, List<? extends Terms.Bucket> brandUrlBuckets) {
|
private List<SelectorOptions> convertBrandOptions(EsGoodsSearchDTO goodsSearch, List<? extends Terms.Bucket> brandBuckets, List<? extends Terms.Bucket> brandUrlBuckets) {
|
||||||
List<SelectorOptions> brandOptions = new ArrayList<>();
|
List<SelectorOptions> brandOptions = new ArrayList<>();
|
||||||
for (int i = 0; i < brandBuckets.size(); i++) {
|
// 以 brandId 为 key 构建 URL 桶索引,避免按下标对齐产生越界/错位
|
||||||
String brandId = brandBuckets.get(i).getKey().toString();
|
Map<String, Terms.Bucket> brandUrlBucketMap = new HashMap<>();
|
||||||
//当商品品牌id为0时,代表商品没有选择品牌,所以过滤掉品牌选择器
|
if (brandUrlBuckets != null) {
|
||||||
//当品牌id为空并且
|
for (Terms.Bucket urlBucket : brandUrlBuckets) {
|
||||||
if (brandId.equals("0") ||
|
if (urlBucket != null && urlBucket.getKey() != null) {
|
||||||
(CharSequenceUtil.isNotEmpty(goodsSearch.getBrandId())
|
brandUrlBucketMap.put(urlBucket.getKey().toString(), urlBucket);
|
||||||
&& Arrays.asList(goodsSearch.getBrandId().split("@")).contains(brandId))) {
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<String> selectedBrandIds = new HashSet<>();
|
||||||
|
if (CharSequenceUtil.isNotEmpty(goodsSearch.getBrandId())) {
|
||||||
|
selectedBrandIds.addAll(Arrays.asList(goodsSearch.getBrandId().split("@")));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Terms.Bucket bucket : brandBuckets) {
|
||||||
|
if (bucket == null || bucket.getKey() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String brandId = bucket.getKey().toString();
|
||||||
|
// 排除无品牌或已选择品牌
|
||||||
|
if ("0".equals(brandId) || (!selectedBrandIds.isEmpty() && selectedBrandIds.contains(brandId))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 品牌名
|
||||||
String brandName = "";
|
String brandName = "";
|
||||||
if (brandBuckets.get(i).getAggregations() != null && brandBuckets.get(i).getAggregations().get(ATTR_BRAND_NAME) != null) {
|
Aggregations nameAggs = bucket.getAggregations();
|
||||||
ParsedStringTerms aggregation = brandBuckets.get(i).getAggregations().get(ATTR_BRAND_NAME);
|
if (nameAggs != null) {
|
||||||
brandName = this.getAggregationsBrandOptions(aggregation);
|
Aggregation nameAgg = nameAggs.get(ATTR_BRAND_NAME);
|
||||||
|
if (nameAgg instanceof ParsedStringTerms) {
|
||||||
|
brandName = this.getAggregationsBrandOptions((ParsedStringTerms) nameAgg);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (StringUtils.isEmpty(brandName)) {
|
if (StringUtils.isEmpty(brandName)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
// 品牌 URL
|
||||||
String brandUrl = "";
|
String brandUrl = "";
|
||||||
if (brandUrlBuckets != null && !brandUrlBuckets.isEmpty() &&
|
Terms.Bucket urlBucket = brandUrlBucketMap.get(brandId);
|
||||||
brandUrlBuckets.get(i).getAggregations() != null &&
|
if (urlBucket != null && urlBucket.getAggregations() != null) {
|
||||||
brandUrlBuckets.get(i).getAggregations().get(ATTR_BRAND_URL) != null) {
|
Aggregation urlAgg = urlBucket.getAggregations().get(ATTR_BRAND_URL);
|
||||||
ParsedStringTerms aggregation = brandUrlBuckets.get(i).getAggregations().get(ATTR_BRAND_URL);
|
if (urlAgg instanceof ParsedStringTerms) {
|
||||||
brandUrl = this.getAggregationsBrandOptions(aggregation);
|
brandUrl = this.getAggregationsBrandOptions((ParsedStringTerms) urlAgg);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (StringUtils.isEmpty(brandUrl)) {
|
if (StringUtils.isEmpty(brandUrl)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
SelectorOptions so = new SelectorOptions();
|
SelectorOptions so = new SelectorOptions();
|
||||||
so.setName(brandName);
|
so.setName(brandName);
|
||||||
so.setValue(brandId);
|
so.setValue(brandId);
|
||||||
@@ -475,7 +500,7 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
|
|||||||
//品牌判定
|
//品牌判定
|
||||||
if (CharSequenceUtil.isNotEmpty(searchDTO.getBrandId())) {
|
if (CharSequenceUtil.isNotEmpty(searchDTO.getBrandId())) {
|
||||||
String[] brands = searchDTO.getBrandId().split("@");
|
String[] brands = searchDTO.getBrandId().split("@");
|
||||||
filterBuilder.must(QueryBuilders.termsQuery(ATTR_BRAND_ID, brands));
|
filterBuilder.filter(QueryBuilders.termsQuery(ATTR_BRAND_ID, brands));
|
||||||
}
|
}
|
||||||
if (searchDTO.getRecommend() != null) {
|
if (searchDTO.getRecommend() != null) {
|
||||||
filterBuilder.filter(QueryBuilders.termQuery("recommend", searchDTO.getRecommend()));
|
filterBuilder.filter(QueryBuilders.termQuery("recommend", searchDTO.getRecommend()));
|
||||||
|
|||||||
Reference in New Issue
Block a user