1.实现代码
/**
* @author: rzx
* @date: 2023-07-21 16:30
* @desc:
*/
@Component
public class ConsoleAddressTask implements InitializingBean {
private static Logger LOGGER = LoggerFactory.getLogger(ConsoleAddressTask.class);
public final static long OV_TIME = 20 * 1000;
private String podIps = null;
private String luaScript = null;
private String url = null;
private RedisScript<String> redisScript = null;
private List<String> keys = Arrays.asList(CONSOLE_ADDRESS);
@Value("${server.port}")
private String port;
@Value("${ip.refreshInterval}")
private Integer refreshInterval;
@Resource(name = "redisAopTemplate")
private RedisTemplate redisTemplate;
/**
* 定时检查ip是否存活更新ip注册时间
*/
@Scheduled(fixedDelay = OV_TIME)
public void updateConsoleAddressTask() {
try {
//执行lua脚本
redisTemplate.execute(redisScript, keys, url, String.valueOf(refreshInterval));
//获取所有成员
Set range = redisTemplate.opsForZSet().range(keys.get(0), 0, -1);
range.stream().forEach(v -> LOGGER.info("console k8s address:{}", v));
} catch (Exception e) {
LOGGER.error("Lua script Execute exception! url:" + url);
throw new RuntimeException("Lua script Execute exception!");
}
}
@Override
public void afterPropertiesSet() {
initConfiguration();
}
/**
* 初始化配置
*/
private void initConfiguration() {
if (null == podIps) {
//从k8s配置中读取ip,例如118.14.24.24,[21312312312adaqe-1231231-2343dda]
String myPodIps = System.getenv("MY_POD_IPS");
if (StringUtils.isBlank(myPodIps)) {
try {
//k8s读取不到,获取ip4地址
myPodIps = "," + Inet4Address.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
if (StringUtils.isNotBlank(myPodIps)) {
//截取最后一个,之后所有内容
podIps = StringUtils.substringAfterLast(myPodIps, ",");
} else {
throw new RuntimeException("my_pod_ips Cannot be empty!");
}
}
//lua脚本(使用lua时间避免多台机器时间不一致) 根据当前时间戳记录ip的注册时间,后续根据过期时间及当前时间戳判断是否刷新当前ip的注册时间
//如果当前ip已下架则过时清理
luaScript = "redis.replicate_commands()\n" +
"local currentTime = redis.call('time')[1]\n" +
"local consoleAddrsKey = KEYS[1]\n" +
"local consoleUrl = ARGV[1]\n" +
"local refreshInterval = tonumber(ARGV[2])\n" +
"redis.call('ZADD', consoleAddrsKey, currentTime, consoleUrl)\n" +
"local timestamp = redis.call('ZSCORE', consoleAddrsKey, consoleUrl)\n" +
"if timestamp ~= nil and currentTime - timestamp > refreshInterval then\n" +
" -- Refresh the value\n" +
"end" +
" redis.call('ZREMRANGEBYSCORE', consoleAddrsKey, 0, currentTime - refreshInterval)\n";
redisScript = new DefaultRedisScript<>(luaScript, String.class);
url = podIps + ":" + port;
}
}