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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章