参考链接: https://github.com/spring-projects/spring-session/issues/1198

日志如下:

2022-10-18 15:20:02.161 - [] - [redisMessageListenerContainer-13446] WARN  o.s.s.data.redis.RedisOperationsSessionRepository.onMessage(557)- Unable to publish SessionDestroyedEvent for session af4bc17f-181f-4fcb-9310-36ec768150b4
2022-10-18 15:20:03.763 - [] - [redisMessageListenerContainer-13454] WARN  o.s.s.data.redis.RedisOperationsSessionRepository.onMessage(557)- Unable to publish SessionDestroyedEvent for session 71184fca-8955-477d-ac6c-77a69d974413
2022-10-18 15:20:03.763 - [] - [redisMessageListenerContainer-13451] WARN  o.s.s.data.redis.RedisOperationsSessionRepository.onMessage(557)- Unable to publish SessionDestroyedEvent for session 8332fc27-da05-443d-8849-bcfa71ffd3f9
2022-10-18 15:20:05.365 - [] - [redisMessageListenerContainer-13461] WARN  o.s.s.data.redis.RedisOperationsSessionRepository.onMessage(557)- Unable to publish SessionDestroyedEvent for session 1eb4071d-4d3b-487c-b6f4-5a4f44d92e14
2022-10-18 15:20:05.365 - [] - [redisMessageListenerContainer-13460] WARN  o.s.s.data.redis.RedisOperationsSessionRepository.onMessage(557)- Unable to publish SessionDestroyedEvent for session efa55628-1c50-4097-a838-47aa73b999f3
2022-10-18 15:20:08.572 - [] - [redisMessageListenerContainer-13471] WARN  o.s.s.data.redis.RedisOperationsSessionRepository.onMessage(557)- Unable to publish SessionDestroyedEvent for session 1a589ea8-5236-499d-9bcd-30abfb3d4604
2022-10-18 15:20:11.778 - [] - [redisMessageListenerContainer-13484] WARN  o.s.s.data.redis.RedisOperationsSessionRepository.onMessage(557)- Unable to publish SessionDestroyedEvent for session 68a2c608-4d1f-4269-95b8-56cfb5f89a7f
2022-10-18 15:20:13.382 - [] - [redisMessageListenerContainer-13491] WARN  o.s.s.data.redis.RedisOperationsSessionRepository.onMessage(557)- Unable to publish SessionDestroyedEvent for session f3a1b72f-08fe-4ce9-827d-d8acd1c20c13

        主要是由于不同应用使用了同一个redis产生的,我们应用这里使用的spring-session如下

        <dependency>
			<groupId>org.springframework.session</groupId>
			<artifactId>spring-session-data-redis</artifactId>
			<version>2.0.10.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.session</groupId>
			<artifactId>spring-session-core</artifactId>
			<version>2.0.10.RELEASE</version>
		</dependency>

        从日志中去阅读原码,在RedisMessageListenerContainer中调用的onMessage()方法是MessageListener的实现类RedisOperationsSessionRepository中的,可以看到日志输出的Unable to publish SessionDestroyedEvent for session来自这里。

public void onMessage(Message message, byte[] pattern) {
        byte[] messageChannel = message.getChannel();
        byte[] messageBody = message.getBody();
        String channel = new String(messageChannel);
        if (channel.startsWith(this.sessionCreatedChannelPrefix)) {
            Map<Object, Object> loaded = (Map)this.defaultSerializer.deserialize(message.getBody());
            this.handleCreated(loaded, channel);
        } else {
            String body = new String(messageBody);
            if (body.startsWith(this.getExpiredKeyPrefix())) {
                boolean isDeleted = channel.equals(this.sessionDeletedChannel);
                if (isDeleted || channel.equals(this.sessionExpiredChannel)) {
                    int beginIndex = body.lastIndexOf(":") + 1;
                    int endIndex = body.length();
                    String sessionId = body.substring(beginIndex, endIndex);
                    RedisOperationsSessionRepository.RedisSession session = this.getSession(sessionId, true);
                    if (session == null) {
                        logger.warn("Unable to publish SessionDestroyedEvent for session " + sessionId);
                        return;
                    }

                    if (logger.isDebugEnabled()) {
                        logger.debug("Publishing SessionDestroyedEvent for session " + sessionId);
                    }

                    this.cleanupPrincipalIndex(session);
                    if (isDeleted) {
                        this.handleDeleted(session);
                    } else {
                        this.handleExpired(session);
                    }
                }

            }
        }
    }

        目前分析出是在spring session过期时会在所有会话中触发销毁事件,但获得的sessionId未必是当前应用的,因此见上述原码,getSession(sessionId,true)方法获得的session为null,从而日志输出Unable to publish SessionDestroyedEvent for session。

        目前不影响业务的使用,只是会在日志中不停的输出,若更多的应用同时使用同一个redis,日志将会被“污染”。

        请教大家有没有解决方法。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐