提交 | 用户 | 时间
|
e7c126
|
1 |
package com.xxl.job.admin.core.route.strategy; |
H |
2 |
|
|
3 |
import com.xxl.job.admin.core.route.ExecutorRouter; |
|
4 |
import com.xxl.job.core.biz.model.ReturnT; |
|
5 |
import com.xxl.job.core.biz.model.TriggerParam; |
|
6 |
|
|
7 |
import java.util.*; |
|
8 |
import java.util.concurrent.ConcurrentHashMap; |
|
9 |
import java.util.concurrent.ConcurrentMap; |
|
10 |
|
|
11 |
/** |
|
12 |
* 单个JOB对应的每个执行器,使用频率最低的优先被选举 |
|
13 |
* a(*)、LFU(Least Frequently Used):最不经常使用,频率/次数 |
|
14 |
* b、LRU(Least Recently Used):最近最久未使用,时间 |
|
15 |
* |
|
16 |
* Created by xuxueli on 17/3/10. |
|
17 |
*/ |
|
18 |
public class ExecutorRouteLFU extends ExecutorRouter { |
|
19 |
|
|
20 |
private static ConcurrentMap<Integer, HashMap<String, Integer>> jobLfuMap = new ConcurrentHashMap<Integer, HashMap<String, Integer>>(); |
|
21 |
private static long CACHE_VALID_TIME = 0; |
|
22 |
|
|
23 |
public String route(int jobId, List<String> addressList) { |
|
24 |
|
|
25 |
// cache clear |
|
26 |
if (System.currentTimeMillis() > CACHE_VALID_TIME) { |
|
27 |
jobLfuMap.clear(); |
|
28 |
CACHE_VALID_TIME = System.currentTimeMillis() + 1000*60*60*24; |
|
29 |
} |
|
30 |
|
|
31 |
// lfu item init |
|
32 |
HashMap<String, Integer> lfuItemMap = jobLfuMap.get(jobId); // Key排序可以用TreeMap+构造入参Compare;Value排序暂时只能通过ArrayList; |
|
33 |
if (lfuItemMap == null) { |
|
34 |
lfuItemMap = new HashMap<String, Integer>(); |
|
35 |
jobLfuMap.putIfAbsent(jobId, lfuItemMap); // 避免重复覆盖 |
|
36 |
} |
|
37 |
|
|
38 |
// put new |
|
39 |
for (String address: addressList) { |
|
40 |
if (!lfuItemMap.containsKey(address) || lfuItemMap.get(address) >1000000 ) { |
|
41 |
lfuItemMap.put(address, new Random().nextInt(addressList.size())); // 初始化时主动Random一次,缓解首次压力 |
|
42 |
} |
|
43 |
} |
|
44 |
// remove old |
|
45 |
List<String> delKeys = new ArrayList<>(); |
|
46 |
for (String existKey: lfuItemMap.keySet()) { |
|
47 |
if (!addressList.contains(existKey)) { |
|
48 |
delKeys.add(existKey); |
|
49 |
} |
|
50 |
} |
|
51 |
if (delKeys.size() > 0) { |
|
52 |
for (String delKey: delKeys) { |
|
53 |
lfuItemMap.remove(delKey); |
|
54 |
} |
|
55 |
} |
|
56 |
|
|
57 |
// load least userd count address |
|
58 |
List<Map.Entry<String, Integer>> lfuItemList = new ArrayList<Map.Entry<String, Integer>>(lfuItemMap.entrySet()); |
|
59 |
Collections.sort(lfuItemList, new Comparator<Map.Entry<String, Integer>>() { |
|
60 |
@Override |
|
61 |
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) { |
|
62 |
return o1.getValue().compareTo(o2.getValue()); |
|
63 |
} |
|
64 |
}); |
|
65 |
|
|
66 |
Map.Entry<String, Integer> addressItem = lfuItemList.get(0); |
|
67 |
String minAddress = addressItem.getKey(); |
|
68 |
addressItem.setValue(addressItem.getValue() + 1); |
|
69 |
|
|
70 |
return addressItem.getKey(); |
|
71 |
} |
|
72 |
|
|
73 |
@Override |
|
74 |
public ReturnT<String> route(TriggerParam triggerParam, List<String> addressList) { |
|
75 |
String address = route(triggerParam.getJobId(), addressList); |
|
76 |
return new ReturnT<String>(address); |
|
77 |
} |
|
78 |
|
|
79 |
} |