009 使用Redis处理消息

原文

https://spring.io/guides/gs/messaging-redis/

直译

启动Redis服务器

在构建消息传递应用程序之前,需要设置将处理接收和发送消息的服务器。

Redis是一个开源的,BSD许可的键值数据存储,它还附带了一个消息传递系统。该服务器可在http://redis.io/download免费获得。您可以手动下载,或者如果您使用带自制程序的Mac:

brew install redis

解压缩Redis后,可以使用默认设置启动它。

redis-server

你应该看到这样的消息:

[35142] 01 May 14:36:28.939 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
[35142] 01 May 14:36:28.940 * Max number of open files set to 10032
                _._
              _.-``__ ''-._
        _.-``    `.  `_.  ''-._           Redis 2.6.12 (00000000/0) 64 bit
    .-`` .-```.  ```\/    _.,_ ''-._
  (    '      ,       .-`  | `,    )     Running in stand alone mode
  |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
  |    `-._   `._    /     _.-'    |     PID: 35142
    `-._    `-._  `-./  _.-'    _.-'
  |`-._`-._    `-.__.-'    _.-'_.-'|
  |    `-._`-._        _.-'_.-'    |           http://redis.io
    `-._    `-._`-.__.-'_.-'    _.-'
  |`-._`-._    `-.__.-'    _.-'_.-'|
  |    `-._`-._        _.-'_.-'    |
    `-._    `-._`-.__.-'_.-'    _.-'
        `-._    `-.__.-'    _.-'
            `-._        _.-'
                `-.__.-'

[35142] 01 May 14:36:28.941 # Server started, Redis version 2.6.12
[35142] 01 May 14:36:28.941 * The server is now ready to accept connections on port 6379

创建Redis消息接收器

在任何基于消息传递的应用程序中,都有消息发布者和消息接收者。要创建消息接收器,请使用响应消息的方法实现接收器:

src/main/java/hello/Receiver.java

package hello;

import java.util.concurrent.CountDownLatch;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

public class Receiver {
    private static final Logger LOGGER = LoggerFactory.getLogger(Receiver.class);

    private CountDownLatch latch;

    @Autowired
    public Receiver(CountDownLatch latch) {
        this.latch = latch;
    }

    public void receiveMessage(String message) {
        LOGGER.info("Received <" + message + ">");
        latch.countDown();
    }
}

这Receiver是一个简单的POJO,它定义了一种接收消息的方法。正如您在注册Receiver消息监听器时所看到的那样,您可以根据需要为消息处理方法命名。

出于演示目的,它由构造函数自动装配,具有倒计时锁存器。这样,它可以在收到消息时发出信号。
注册监听器并发送消息
Spring Data Redis提供了使用Redis发送和接收消息所需的所有组件。具体来说,您需要配置:

  • 连接工厂

  • 消息侦听器容器

  • Redis模板

您将使用Redis模板发送消息,您将Receiver使用消息侦听器容器注册它以便它将接收消息。连接工厂驱动模板和消息侦听器容器,使它们能够连接到Redis服务器。

此示例使用Spring Boot的默认设置RedisConnectionFactory,其实例JedisConnectionFactory基于Jedis Redis库。连接工厂将注入消息侦听器容器和Redis模板。

src/main/java/hello/Application.java

package hello;

import java.util.concurrent.CountDownLatch;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;

@SpringBootApplication
public class Application {

	private static final Logger LOGGER = LoggerFactory.getLogger(Application.class);

	@Bean
	RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
			MessageListenerAdapter listenerAdapter) {

		RedisMessageListenerContainer container = new RedisMessageListenerContainer();
		container.setConnectionFactory(connectionFactory);
		container.addMessageListener(listenerAdapter, new PatternTopic("chat"));

		return container;
	}

	@Bean
	MessageListenerAdapter listenerAdapter(Receiver receiver) {
		return new MessageListenerAdapter(receiver, "receiveMessage");
	}

	@Bean
	Receiver receiver(CountDownLatch latch) {
		return new Receiver(latch);
	}

	@Bean
	CountDownLatch latch() {
		return new CountDownLatch(1);
	}

	@Bean
	StringRedisTemplate template(RedisConnectionFactory connectionFactory) {
		return new StringRedisTemplate(connectionFactory);
	}

	public static void main(String[] args) throws InterruptedException {

		ApplicationContext ctx = SpringApplication.run(Application.class, args);

		StringRedisTemplate template = ctx.getBean(StringRedisTemplate.class);
		CountDownLatch latch = ctx.getBean(CountDownLatch.class);

		LOGGER.info("Sending message...");
		template.convertAndSend("chat", "Hello from Redis!");

		latch.await();

		System.exit(0);
	}
}

listenerAdapter方法中定义的bean在定义的消息侦听器容器中注册为消息侦听器container,并将侦听“chat”主题上的消息。因为Receiver该类是POJO,所以它需要包装在实现所需MessageListener接口的消息侦听器适配器中addMessageListener()。消息侦听器适配器还配置为在消息到达时调用receiveMessage()方法Receiver。

连接工厂和消息监听器容器bean是监听消息所需的全部内容。要发送消息,您还需要Redis模板。这里,它是一个配置为a的bean StringRedisTemplate,其实现RedisTemplate主要集中在Redis的常用用法,其中键和值都是Strings。

该main()方法通过创建Spring应用程序上下文来解决所有问题。然后,应用程序上下文启动消息侦听器容器,并且消息侦听器容器bean开始侦听消息。main()然后,该方法StringRedisTemplate从应用程序上下文中检索bean,并使用它发送“Hello from Redis!” “聊天”主题上的消息。最后,它关闭Spring应用程序上下文,应用程序结束。

构建可执行的JAR

您可以使用Gradle或Maven从命令行运行该应用程序。或者,您可以构建一个包含所有必需依赖项,类和资源的可执行JAR文件,并运行该文件。这使得在整个开发生命周期中,跨不同环境等将服务作为应用程序发布,版本和部署变得容易。

如果您使用的是Gradle,则可以使用./gradlew bootRun。或者您可以使用构建JAR文件./gradlew build。然后你可以运行JAR文件:

java -jar build / libs / gs-messaging-redis-0.1.0.jar

如果您使用的是Maven,则可以使用该应用程序运行该应用程序./mvnw spring-boot:run。或者您可以使用构建JAR文件./mvnw clean package。然后你可以运行JAR文件:

java -jar target / gs-messaging-redis-0.1.0.jar

上面的过程将创建一个可运行的JAR。您也可以选择构建经典WAR文件。
您应该看到以下输出:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.5.RELEASE)

2014-04-18 08:03:34.032  INFO 47002 --- [           main] hello.Application                        : Starting Application on retina with PID 47002 (/Users/gturnquist/src/spring-guides/gs-messaging-redis/complete/target/classes started by gturnquist)
2014-04-18 08:03:34.062  INFO 47002 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@7a53c84a: startup date [Fri Apr 18 08:03:34 CDT 2014]; root of context hierarchy
2014-04-18 08:03:34.326  INFO 47002 --- [           main] o.s.c.support.DefaultLifecycleProcessor  : Starting beans in phase 2147483647
2014-04-18 08:03:34.357  INFO 47002 --- [           main] hello.Application                        : Started Application in 0.605 seconds (JVM running for 0.899)
2014-04-18 08:03:34.357  INFO 47002 --- [           main] hello.Application                        : Sending message...
2014-04-18 08:03:34.370  INFO 47002 --- [    container-2] hello.Receiver                           : Received <Hello from Redis!>
2014-04-18 08:03:34.379  INFO 47002 --- [       Thread-1] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@7a53c84a: startup date [Fri Apr 18 08:03:34 CDT 2014]; root of context hierarchy
2014-04-18 08:03:34.380  INFO 47002 --- [       Thread-1] o.s.c.support.DefaultLifecycleProcessor  : Stopping beans in phase 2147483647

摘要

恭喜!您刚刚使用Spring和Redis开发了一个简单的发布 - 订阅应用程序。

Redis支持可用。

扩展知识

实际测试中遇到的异常场景:

本示例在实际测试中,可能出现生产者生产了消息,但是消费者却未消费到消息的情况

在debug模式下,生产者生产消息后,打断点,然后单步调试到消费者消费时,却可以正常消费到消息

由此提出以下猜测:
生产者生产消息时,消费者尚未就绪,导致消息丢失。

挖个坑,后续来填:TODO 进一步排查出现上述场景的原因,如何避免,如何解决

查看运行时某个java对象占用JVM大小及通过idea查看java的内存占用情况

https://blog.csdn.net/qq_2300688967/article/details/84951123

IntelliJ IDEA 学习笔记 - 显示内存和内存回收

https://blog.csdn.net/cgl125167016/article/details/79005861

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值