创建名称为 'enableRedisKeyspaceNotificationsInitializer' 的 bean 时出错

Error creating bean with name 'enableRedisKeyspaceNotificationsInitializer'

我可以使用以下 Spring 会话配置连接到 Azure Redis 缓存:

<bean id="redisPassword" class="org.springframework.data.redis.connection.RedisPassword">
    <constructor-arg index="0" value="xxxxxxxxxxxxxxxx"/>
</bean>

<bean id="redisStandaloneConfiguration" class="org.springframework.data.redis.connection.RedisStandaloneConfiguration">
    <property name="hostName" value="acmedev.redis.cache.windows.net"/>
    <property name="port" value="6380"/>
    <property name="password" ref="redisPassword"/>
</bean>

<context:annotation-config/>
<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"/>

<bean class="org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory">
    <constructor-arg index="0" ref="redisStandaloneConfiguration"/>
</bean>

我的应用成功连接:

[lettuce-nioEventLoop-4-1] DEBUG io.lettuce.core.RedisClient - Connecting to Redis at acmedev.redis.cache.windows.net:6380: Success

然后应用程序挂了一会儿,我最终得到了这个错误

11:22:54.712 [lettuce-nioEventLoop-4-1] DEBUG io.lettuce.core.protocol.CommandHandler - [channel=0xcf902cd8, /10.1.200.58:53533 -> acmedev.redis.cache.windows.net/52.240.141.200:6380, chid=0x1] Storing exception in connectionError
2020-02-19 11:22:54,713  WARN (org.springframework.context.support.AbstractApplicationContext:558) || - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'enableRedisKeyspaceNotificationsInitializer' defined in class path resource [org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfiguration.class]: Invocation of init method failed; nested exception is org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to acmedev.redis.cache.windows.net:6380
11:22:54.719 [RMI TCP Connection(3)-127.0.0.1] DEBUG io.lettuce.core.RedisClient - Initiate shutdown (100, 100, MILLISECONDS)


[lettuce-nioEventLoop-4-1] DEBUG io.lettuce.core.protocol.CommandHandler - [channel=0xcf902cd8, /10.1.200.58:53533 -> acmedev.redis.cache.windows.net/52.240.141.200:6380, chid=0x1] Unexpected exception during request: java.io.IOException: An existing connection was forcibly closed by the remote host
java.io.IOException: An existing connection was forcibly closed by the remote host
    at sun.nio.ch.SocketDispatcher.read0(Native Method)
    at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43)
    at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
    at sun.nio.ch.IOUtil.read(IOUtil.java:192)
    at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380)
    at io.netty.buffer.PooledByteBuf.setBytes(PooledByteBuf.java:253)
    at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1133)
    at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:350)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:148)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:714)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:650)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:576)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
    at io.netty.util.concurrent.SingleThreadEventExecutor.run(SingleThreadEventExecutor.java:989)
    at io.netty.util.internal.ThreadExecutorMap.run(ThreadExecutorMap.java:74)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.lang.Thread.run(Thread.java:745)

当我在 localhost 上使用 redis 运行 时,这些相同的 beans 工作得很好。

我做错了什么?

首先 RedisHttpSessionConfiguration 尝试(默认)enable 键空间通知。但这仅适用于不安全的实例。

文档表单 class ConfigureNotifyKeyspaceEventsAction 解释为什么它只适用于本地主机:

This strategy will not work if the Redis instance has been properly secured. Instead, the Redis instance should be configured externally and a Bean of type ConfigureRedisAction#NO_OP should be exposed.

并说明应如何配置它以使用安全的 Redis 实例。

简单使用方法:RedisHttpSessionConfiguration#setConfigureRedisAction 设置 ConfigureRedisAction#NO_OP 然后例如在您的 redis 实例调用中:config set notify-keyspace-events Egx

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
                           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
     http://www.springframework.org/schema/util  http://www.springframework.org/schema/util/spring-util-3.1.xsd">
 .
 .
 .
    <util:constant id="configureRedisAction"
                   static-field="org.springframework.session.data.redis.config.ConfigureRedisAction.NO_OP"/>
<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration" p:configureRedisAction-ref="configureRedisAction"/>