scheduler竞争锁
注意参数类型和返回值
@Autowired
private StringRedisTemplate redisTemplate;
@Autowired
private XfuzzConfig xfuzzConfig;
private volatile boolean scheduler = false;
@Scheduled(fixedDelay = 5 * 1000, initialDelay = 10 * 1000)
public void acquireLock() {
String id = IpUtils.matchIp(xfuzzConfig.getEthName());
String key = "lock:scheduler";
int seconds = 60;
if (!scheduler) {
scheduler = redisTemplate.opsForValue().setIfAbsent(key, id, seconds, TimeUnit.SECONDS);
return;
}
String lua = "if redis.call('get',KEYS[1]) == ARGV[1] then\n" +
" redis.call('expire', KEYS[1], ARGV[2])\n" +
" return true\n" +
"else\n" +
"end";
DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>();
redisScript.setResultType(Boolean.class);
redisScript.setScriptText(lua);
List<String> keyList = new ArrayList<>();
keyList.add(key);
scheduler = redisTemplate.execute(redisScript, keyList, id, seconds + "");
}
获取 ip(常见网卡匹配)
public static String matchIp(String ifName) {
if (ifName.contains(",")) {
for (String reg : ifName.split(",")) {
String ip = getIp(reg);
if (StringUtils.isNotBlank(ip)) {
return ip;
}
}
throw new RuntimeException("未获取到网卡" + ifName + " ip");
} else {
String ip = getIp(ifName);
if (StringUtils.isNotBlank(ip)) {
return ip;
}
throw new RuntimeException("未获取到网卡" + ifName + " ip");
}
}
public static String getIp(String ifName) {
ifName = ifName.trim();
try {
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
while (networkInterfaces.hasMoreElements()) {
NetworkInterface networkInterface = (NetworkInterface) networkInterfaces.nextElement();
if (networkInterface.isLoopback() || !networkInterface.isUp()) {
continue;
}
String name = networkInterface.getName();
boolean match = StringUtils.isNotBlank(name) && name.matches(ifName);
name = networkInterface.getDisplayName();
match = match || (StringUtils.isNotBlank(name) && name.matches(ifName));
if (!match) {
continue;
}
Enumeration<InetAddress> addresses = networkInterface.getInetAddresses();
while (addresses.hasMoreElements()) {
InetAddress inetAddress = addresses.nextElement();
if (inetAddress.isSiteLocalAddress()) {
return inetAddress.getHostAddress();
}
}
}
} catch (Exception e) {
log.error("获取网卡 {} ip失败", ifName, e);
}
return null;
}