diff --git a/system-setting/backend/src/main/java/io/metersphere/job/schedule/CleanSessionJob.java b/system-setting/backend/src/main/java/io/metersphere/job/schedule/CleanSessionJob.java new file mode 100644 index 0000000000..3c38b96911 --- /dev/null +++ b/system-setting/backend/src/main/java/io/metersphere/job/schedule/CleanSessionJob.java @@ -0,0 +1,68 @@ +package io.metersphere.job.schedule; + +import com.fit2cloud.quartz.anno.QuartzScheduled; +import io.metersphere.commons.utils.JSON; +import io.metersphere.commons.utils.LogUtil; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.reflect.MethodUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.Cursor; +import org.springframework.data.redis.core.ScanOptions; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.session.data.redis.RedisIndexedSessionRepository; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.time.Duration; +import java.util.HashMap; +import java.util.Map; + +@Component +public class CleanSessionJob { + @Resource + private StringRedisTemplate stringRedisTemplate; + @Resource + private RedisIndexedSessionRepository redisIndexedSessionRepository; + + @Value("${spring.session.timeout:43200s}") + private Duration timeout; + + /** + * 清理没有绑定user的session + * redisson 有时会把ttl设置成-1 https://github.com/redisson/redisson/issues/4200 + */ + @QuartzScheduled(cron = "0 2 0 * * ?") + public void cleanSession() { + Map userCount = new HashMap<>(); + ScanOptions options = ScanOptions.scanOptions().match("spring:session:sessions:*").count(1000).build(); + try ( + Cursor scan = stringRedisTemplate.scan(options) + ) { + while (scan.hasNext()) { + String key = scan.next(); + if (StringUtils.contains(key, "spring:session:sessions:expires:")) { + continue; + } + Boolean exists = stringRedisTemplate.opsForHash().hasKey(key, "sessionAttr:user"); + if (!exists) { + stringRedisTemplate.delete(key); + } else { + Object user = redisIndexedSessionRepository.getSessionRedisOperations().opsForHash().get(key, "sessionAttr:user"); + Long expire = redisIndexedSessionRepository.getSessionRedisOperations().getExpire(key); + String userId = (String) MethodUtils.invokeMethod(user, "getId"); + Long count = userCount.getOrDefault(userId, 0L); + count++; + userCount.put(userId, count); + LogUtil.info(key + " : " + userId + " 过期时间: " + expire); + if (expire != null && expire.intValue() == -1) { + redisIndexedSessionRepository.getSessionRedisOperations().expire(key, timeout); + } + } + } + + LogUtil.info(JSON.toJSONString(userCount)); + } catch (Exception e) { + LogUtil.error(e); + } + } +}