|
@@ -2,8 +2,6 @@ package com.tzld.piaoquan.recommend.server.framework.recaller;
|
|
|
|
|
|
|
|
|
|
import com.google.common.base.Function;
|
|
import com.google.common.base.Function;
|
|
-import com.google.common.base.Optional;
|
|
|
|
-import com.google.common.base.Predicate;
|
|
|
|
import com.google.common.collect.FluentIterable;
|
|
import com.google.common.collect.FluentIterable;
|
|
import com.google.common.collect.Lists;
|
|
import com.google.common.collect.Lists;
|
|
import com.google.common.collect.Maps;
|
|
import com.google.common.collect.Maps;
|
|
@@ -12,7 +10,6 @@ import com.google.common.collect.Maps;
|
|
import com.tzld.piaoquan.recommend.server.common.base.RankItem;
|
|
import com.tzld.piaoquan.recommend.server.common.base.RankItem;
|
|
import com.tzld.piaoquan.recommend.server.framework.candidiate.*;
|
|
import com.tzld.piaoquan.recommend.server.framework.candidiate.*;
|
|
import com.tzld.piaoquan.recommend.server.framework.common.User;
|
|
import com.tzld.piaoquan.recommend.server.framework.common.User;
|
|
-import com.tzld.piaoquan.recommend.server.framework.recaller.provider.ItemProvider;
|
|
|
|
import com.tzld.piaoquan.recommend.server.framework.recaller.provider.QueueProvider;
|
|
import com.tzld.piaoquan.recommend.server.framework.recaller.provider.QueueProvider;
|
|
import com.tzld.piaoquan.recommend.server.gen.recommend.RecommendRequest;
|
|
import com.tzld.piaoquan.recommend.server.gen.recommend.RecommendRequest;
|
|
import org.apache.commons.collections4.CollectionUtils;
|
|
import org.apache.commons.collections4.CollectionUtils;
|
|
@@ -21,7 +18,6 @@ import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.ArrayList;
|
|
-import java.util.Arrays;
|
|
|
|
import java.util.HashMap;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
@@ -40,21 +36,16 @@ public class BaseRecaller<InMemoryItem> {
|
|
private static final long DEFAULT_PARALLEL_FILTER_TIMEOUT = 200; // ms
|
|
private static final long DEFAULT_PARALLEL_FILTER_TIMEOUT = 200; // ms
|
|
private static final ExecutorService filterExecutorService = Executors.newFixedThreadPool(128);
|
|
private static final ExecutorService filterExecutorService = Executors.newFixedThreadPool(128);
|
|
private static final ExecutorService fetchQueueExecutorService = Executors.newFixedThreadPool(128);
|
|
private static final ExecutorService fetchQueueExecutorService = Executors.newFixedThreadPool(128);
|
|
-
|
|
|
|
- protected final ItemProvider<InMemoryItem> itemProvider;
|
|
|
|
private final QueueProvider<InMemoryItem> queueProvider;
|
|
private final QueueProvider<InMemoryItem> queueProvider;
|
|
- private final FilterConfig filterConfig ;
|
|
|
|
private final long QUEUE_LOAD_TIMEOUT;
|
|
private final long QUEUE_LOAD_TIMEOUT;
|
|
|
|
|
|
- public BaseRecaller(ItemProvider<InMemoryItem> itemProvider, QueueProvider<InMemoryItem> queueProvider, FilterConfig filterConfig) {
|
|
|
|
- this(itemProvider, queueProvider, filterConfig, DEFAULT_QUEUE_LOAD_TIMEOUT);
|
|
|
|
|
|
+ public BaseRecaller(QueueProvider<InMemoryItem> queueProvider) {
|
|
|
|
+ this(queueProvider, DEFAULT_QUEUE_LOAD_TIMEOUT);
|
|
}
|
|
}
|
|
|
|
|
|
- public BaseRecaller(ItemProvider<InMemoryItem> itemProvider, QueueProvider<InMemoryItem> queueProvider,
|
|
|
|
- FilterConfig filterConfig, long queueLoadTimeout) {
|
|
|
|
- this.itemProvider = itemProvider;
|
|
|
|
|
|
+ public BaseRecaller(QueueProvider<InMemoryItem> queueProvider,
|
|
|
|
+ long queueLoadTimeout) {
|
|
this.queueProvider = queueProvider;
|
|
this.queueProvider = queueProvider;
|
|
- this.filterConfig = filterConfig;
|
|
|
|
this.QUEUE_LOAD_TIMEOUT = queueLoadTimeout;
|
|
this.QUEUE_LOAD_TIMEOUT = queueLoadTimeout;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -63,10 +54,8 @@ public class BaseRecaller<InMemoryItem> {
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-
|
|
|
|
- public boolean isValidItem(InMemoryItem item){
|
|
|
|
- return item!= null;
|
|
|
|
-
|
|
|
|
|
|
+ public boolean isValidItem(InMemoryItem item) {
|
|
|
|
+ return item != null;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -74,10 +63,9 @@ public class BaseRecaller<InMemoryItem> {
|
|
*
|
|
*
|
|
* @param entries
|
|
* @param entries
|
|
* @param candidate
|
|
* @param candidate
|
|
- * @param user
|
|
|
|
* @return
|
|
* @return
|
|
*/
|
|
*/
|
|
- private List<RankItem> toHits(final Iterable<Entry<InMemoryItem>> entries, final Candidate candidate, final User user) {
|
|
|
|
|
|
+ private List<RankItem> toHits(final Iterable<Entry<InMemoryItem>> entries, final Candidate candidate) {
|
|
|
|
|
|
List<RankItem> result = new ArrayList<RankItem>();
|
|
List<RankItem> result = new ArrayList<RankItem>();
|
|
for (Entry entry : entries) {
|
|
for (Entry entry : entries) {
|
|
@@ -98,9 +86,7 @@ public class BaseRecaller<InMemoryItem> {
|
|
|
|
|
|
// 读取redis中的数据放入queue中
|
|
// 读取redis中的数据放入queue中
|
|
public Map<Candidate, Queue<InMemoryItem>> loadQueues(List<Candidate> candidates) {
|
|
public Map<Candidate, Queue<InMemoryItem>> loadQueues(List<Candidate> candidates) {
|
|
-
|
|
|
|
// update queueName
|
|
// update queueName
|
|
- // final Map<String, Long> cacheRules = getCacheRulesConfig();
|
|
|
|
Iterable<Candidate> updateCandidates = FluentIterable.from(candidates).transform(new Function<Candidate, Candidate>() {
|
|
Iterable<Candidate> updateCandidates = FluentIterable.from(candidates).transform(new Function<Candidate, Candidate>() {
|
|
@Override
|
|
@Override
|
|
public Candidate apply(Candidate candidate) {
|
|
public Candidate apply(Candidate candidate) {
|
|
@@ -146,9 +132,6 @@ public class BaseRecaller<InMemoryItem> {
|
|
|
|
|
|
/**
|
|
/**
|
|
* recall
|
|
* recall
|
|
- * 1. construct recall filter
|
|
|
|
- * 2. Redis并行召回
|
|
|
|
- * 3. do filter
|
|
|
|
*
|
|
*
|
|
* @param requestData
|
|
* @param requestData
|
|
* @param user
|
|
* @param user
|
|
@@ -159,7 +142,6 @@ public class BaseRecaller<InMemoryItem> {
|
|
public List<RankItem> recalling(final RecommendRequest requestData, final User user, int requestIndex, List<Candidate> recallCandidates) {
|
|
public List<RankItem> recalling(final RecommendRequest requestData, final User user, int requestIndex, List<Candidate> recallCandidates) {
|
|
|
|
|
|
long startTime = System.currentTimeMillis();
|
|
long startTime = System.currentTimeMillis();
|
|
- final RecallFilterPipeline<InMemoryItem> recallFilter = new RecallFilterPipeline<InMemoryItem>(this.filterConfig, requestData, user, requestIndex);
|
|
|
|
|
|
|
|
// load queue
|
|
// load queue
|
|
long queueLoadStartTime = System.currentTimeMillis();
|
|
long queueLoadStartTime = System.currentTimeMillis();
|
|
@@ -204,11 +186,15 @@ public class BaseRecaller<InMemoryItem> {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- // do filter
|
|
|
|
- // 执行 recall filter配置文件中的方法
|
|
|
|
- long filterStartTime = System.currentTimeMillis();
|
|
|
|
|
|
|
|
- List<Map.Entry<Candidate, Queue<InMemoryItem>>> batch = new ArrayList<Map.Entry<Candidate, Queue<InMemoryItem>>>();
|
|
|
|
|
|
+ List<RankItem> result = convertToRankItem(candidateQueueMap);
|
|
|
|
+
|
|
|
|
+ return result;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ private List<RankItem> convertToRankItem(Map<Candidate, Queue<InMemoryItem>> candidateQueueMap) {
|
|
|
|
+
|
|
final List<Callable<List<RankItem>>> callables = new ArrayList<Callable<List<RankItem>>>();
|
|
final List<Callable<List<RankItem>>> callables = new ArrayList<Callable<List<RankItem>>>();
|
|
int expectedRecallSum = 0;
|
|
int expectedRecallSum = 0;
|
|
for (final Map.Entry<Candidate, Queue<InMemoryItem>> entry : candidateQueueMap.entrySet()) {
|
|
for (final Map.Entry<Candidate, Queue<InMemoryItem>> entry : candidateQueueMap.entrySet()) {
|
|
@@ -219,16 +205,10 @@ public class BaseRecaller<InMemoryItem> {
|
|
final Candidate candidate = entry.getKey();
|
|
final Candidate candidate = entry.getKey();
|
|
try {
|
|
try {
|
|
// 1. filter
|
|
// 1. filter
|
|
- Iterable<Entry<InMemoryItem>> entries = FluentIterable.from(entry.getValue()).filter(new Predicate<Entry<InMemoryItem>>() {
|
|
|
|
- @Override
|
|
|
|
- public boolean apply(Entry<InMemoryItem> entry) {
|
|
|
|
- return isValidItem(entry.item) &&
|
|
|
|
- recallFilter.predicate(candidate, entry.item);
|
|
|
|
- }
|
|
|
|
- }).limit(candidate.getCandidateNum());
|
|
|
|
|
|
+ Iterable<Entry<InMemoryItem>> entries = FluentIterable.from(entry.getValue()).limit(candidate.getCandidateNum());
|
|
|
|
|
|
// 2. toHits
|
|
// 2. toHits
|
|
- candidateHits.addAll(toHits(entries, candidate, user));
|
|
|
|
|
|
+ candidateHits.addAll(toHits(entries, candidate));
|
|
|
|
|
|
// debug log for tracing
|
|
// debug log for tracing
|
|
LOGGER.debug("recalled candidate [{}], queue length [{}], expected [{}], hit [{}]",
|
|
LOGGER.debug("recalled candidate [{}], queue length [{}], expected [{}], hit [{}]",
|
|
@@ -236,7 +216,6 @@ public class BaseRecaller<InMemoryItem> {
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
LOGGER.error("recall filter queue occur error, queue [{}], error: [{}]", candidate.toString(), ExceptionUtils.getFullStackTrace(e));
|
|
LOGGER.error("recall filter queue occur error, queue [{}], error: [{}]", candidate.toString(), ExceptionUtils.getFullStackTrace(e));
|
|
}
|
|
}
|
|
-
|
|
|
|
return candidateHits;
|
|
return candidateHits;
|
|
}
|
|
}
|
|
});
|
|
});
|
|
@@ -245,7 +224,6 @@ public class BaseRecaller<InMemoryItem> {
|
|
Map<String, RankItem> hits = new HashMap<String, RankItem>();
|
|
Map<String, RankItem> hits = new HashMap<String, RankItem>();
|
|
try {
|
|
try {
|
|
List<Future<List<RankItem>>> futures = filterExecutorService.invokeAll(callables, DEFAULT_PARALLEL_FILTER_TIMEOUT, TimeUnit.MILLISECONDS);
|
|
List<Future<List<RankItem>>> futures = filterExecutorService.invokeAll(callables, DEFAULT_PARALLEL_FILTER_TIMEOUT, TimeUnit.MILLISECONDS);
|
|
-
|
|
|
|
for (Future<List<RankItem>> future : futures) {
|
|
for (Future<List<RankItem>> future : futures) {
|
|
try {
|
|
try {
|
|
if (future.isDone() && !future.isCancelled() && future.get() != null) {
|
|
if (future.isDone() && !future.isCancelled() && future.get() != null) {
|
|
@@ -259,34 +237,28 @@ public class BaseRecaller<InMemoryItem> {
|
|
hits.put(item.getId(), item);
|
|
hits.put(item.getId(), item);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ LOGGER.debug("collect items from filter task, userid: [{}], item size [{}]", "", part.size());
|
|
} else {
|
|
} else {
|
|
- LOGGER.error("parallel recall filter Canceled {} ", requestData.getRequestId());
|
|
|
|
|
|
+ LOGGER.error("parallel recall filter Canceled {} ", "");
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
LOGGER.error("parallel recall filter occur error, uid: [{}], Exception [{}]",
|
|
LOGGER.error("parallel recall filter occur error, uid: [{}], Exception [{}]",
|
|
- requestData.getRequestId(), ExceptionUtils.getFullStackTrace(e));
|
|
|
|
|
|
+ "", ExceptionUtils.getFullStackTrace(e));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
LOGGER.error("parallel recall filter occur error, uid: [{}], Exception [{}]",
|
|
LOGGER.error("parallel recall filter occur error, uid: [{}], Exception [{}]",
|
|
- requestData.getRequestId(), ExceptionUtils.getFullStackTrace(e));
|
|
|
|
|
|
+ "", ExceptionUtils.getFullStackTrace(e));
|
|
}
|
|
}
|
|
|
|
|
|
List<RankItem> result = new ArrayList<RankItem>(hits.values());
|
|
List<RankItem> result = new ArrayList<RankItem>(hits.values());
|
|
|
|
+
|
|
return result;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
|
|
- private Map<Candidate, Queue<InMemoryItem>> obtainQueue(List<Candidate> refactorCandidates, RecommendRequest requestData, User user, boolean isFromRedis) {
|
|
|
|
- if (isFromRedis) {
|
|
|
|
- return loadQueues(refactorCandidates);
|
|
|
|
- } else {
|
|
|
|
- return fetchQueues(refactorCandidates, requestData, user);
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
+ private Map<Candidate, Queue<InMemoryItem>> obtainQueue(List<Candidate> refactorCandidates, RecommendRequest requestData, User user, boolean isFromRedis) {
|
|
|
|
+ return loadQueues(refactorCandidates);
|
|
}
|
|
}
|
|
|
|
|
|
- protected Map<Candidate, Queue<InMemoryItem>> fetchQueues(List<Candidate> candidates, RecommendRequest requestData, User user) {
|
|
|
|
-
|
|
|
|
- return null;
|
|
|
|
- }
|
|
|
|
}
|
|
}
|