1

org.springframework.data.redis.listener.RedisMessageListenerContainer を使用して redis pubsub チャネルをリッスンしようとしています。

私の MessageListener クラスは次のようになります

@Component
public class RedisMessageListener {

    @Autowired
    private ProcessAdapterImpl processAdapter;

    private static Logger logger = LoggerFactory.getLogger(RedisMessageListener.class);

    public void handleMessage(Serializable message, String channel) {
        logger.debug("handleMessage >>>>> Message received: " + message.toString() + " channel:" + channel);
        processAdapter.onEventReceived(message.toString());
    }
}

およびアプリケーションコンテキストで

<bean id="tbProperties"
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location">
        <value>classpath:conf/notifier-local.properties
        </value>
    </property>
</bean>
<bean id="jedisConnectionFactory"
    class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
    <property name="hostName" value="${redis.server}" />
    <property name="port" value="${redis.port}" />
    <property name="usePool" value="true" />
</bean>

<!-- redis template definition -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate"
    p:connection-factory-ref="jedisConnectionFactory" />

<bean id="redisPublisher"
    class="com.vgroup.apps.notifier.event.publisher.RedisPublisherImpl" />

<bean id="messageListener"
    class="org.springframework.data.redis.listener.adapter.MessageListenerAdapter">
    <constructor-arg>
        <bean class="com.vgroup.apps.notifier.event.listener.RedisMessageListener" />
    </constructor-arg>
</bean>

<bean id="redisContainer"
    class="org.springframework.data.redis.listener.RedisMessageListenerContainer">
    <property name="connectionFactory" ref="jedisConnectionFactory" />
    <property name="messageListeners">
        <map>
            <entry key-ref="messageListener">
                <bean class="org.springframework.data.redis.listener.ChannelTopic">
                    <constructor-arg value="${redis.queue}" />
                </bean>
            </entry>
        </map>
    </property>
</bean>

redis パブリッシャーは以下のようになります

@Component
public class RedisPublisherImpl implements IRedisPublisher {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private ObjectMapper mapper;

    private static Logger logger = LoggerFactory.getLogger(RedisPublisherImpl.class);

    public void afterPropertiesSet() throws Exception {
    }

    @Override
    public void publish(Object event) {
        logger.info("Start executing publish object");
        try {
            String jsonString = mapper.writeValueAsString(event);
            redisTemplate.convertAndSend("notifications", jsonString);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }

        logger.info("End executing publish object");
    }
}

この構成では、発行元から 1 回だけ送信された場合でも、いくつかの奇妙な理由でメッセージを 2 回 (場合によっては 3 ~ 4 回) 受け取ります。

私のログでは、メッセージが 2 つの異なる rediscontainer スレッドによってリッスンされていることがわかります

2015-12-03 09:13:12.152 [redisContainer-2] DEBUG c.v.a.n.e.l.RedisMessageListener - handleMessage >>>>> Message received: abc channel:notifications
2015-12-03 09:13:12.152 [redisContainer-2] DEBUG c.v.a.n.e.l.RedisMessageListener - handleMessage >>>>> Message received: def channel:notifications
2015-12-03 09:13:12.156 [redisContainer-3] DEBUG c.v.a.n.e.l.RedisMessageListener - handleMessage >>>>> Message received: abc channel:notifications
2015-12-03 09:13:12.157 [redisContainer-3] DEBUG c.v.a.n.e.l.RedisMessageListener - handleMessage >>>>> Message received: def channel:notifications
4

1 に答える 1

4

Bean が 2 回作成されているかどうかを確認します (つまり、サブスクリプションが 2 回発生しています)。web.xmlでも同様の問題がありました。contextListener と DispatchServlet の両方があり、2 回サブスクライブして Bean を 2 回初期化しています。

于 2015-12-07T20:21:23.860 に答える