欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 宝鼎售后问题提交 | 后台管理


新闻资讯

MENU

软件开发知识

ActiveMQ中的Pub与Sub Redis中的发布 图纸加密 订阅其实在真正的企业开发中并不是很常用

点击: 次  来源:宝鼎软件 时间:2017-09-29

原文出处: 徐靖峰

上一篇文章《浅析Spring中的事件驱念头制》简朴先容了Spring对事件的支持。Event的整个生命周期,从publisher发出,颠末applicationContext容器通知到EventListener,都是产生在单个Spring容器中,而在漫衍式场景下,有些时候一个事件的发生,大概需要被多个实例响应,本文主要先容漫衍式场景下的事件驱念头制,由于利用了Redis,ActiveMQ,也可以换一个名词来领略:漫衍式下的宣布订阅模式。

JMS类型

在日常项目开拓中,我们或多或少的发明一些包一些类位于java或javax中,他们主要提供抽象类,接口,提供了一种类型,如JPA,JSR,JNDI,JTA,JMS,他们是由java指定的尺度类型,一流企业做尺度、二流企业做品牌、三流企业做产物,固然有点挖苦的意味,但也可以见得它的重要意义。而JMS就是java在动静处事上指定的尺度

The Java Message Service (JMS) API is a messaging standard that allows application components based on the Java Platform Enterprise Edition (Java EE) to create, send, receive, and read messages. It enables distributed communication that is loosely coupled, reliable, and asynchronous.

JMS(JAVA Message Service,java动静处事)API是一个动静处事的尺度可能说是类型,答允应用措施组件基于JavaEE平台建设、发送、吸收和读打动静。它使漫衍式通信耦合度更低,动静处事越发靠得住以及异步性。

动静中间件有很是多的实现,如ActiveMQ,RabbitMQ,RocketMQ,而他们同一遵循的接口类型,即是JMS。在下文中即将呈现的ConnectionFactory,Destination,Connection,Session,MessageListener,Topic,Queue等等名词,都是JMS焦点的接口,由于本文的初志并不是讲授MQ&JMS,所以这些机制暂且跳过。

界说漫衍式事件需求

在上一个项目中,我们对接了外网的http接口,而安详性的保障则是交给OAutp来完成,作为OAutp的客户端,我们需要获取处事端返回的token,而token接口的获取次数每个月是有限制的,于是我们选择利用Redis来生存,按时刷新。由于每次提倡请求时都要携带token,为了更高的机能淘汰一次redis io,我们在TokenService中利用了当地变量缓存token。于是形成如下的token获取机制:

 ActiveMQ中的Pub与Sub Redis中的宣布 图纸加密 订阅其实在真正的企业开拓中并不是很常用

这个图并不巨大,只是为了利便描写需求:首先去当地变量中加载token,若token==null,则去Redis加载,若Redis未掷中(token逾期了),则最终挪用外部的http接口获取及时的token,同时存入redis中和当地变量中。

这个需求设计到这样一个问题:大大都环境下是单个实例中发明redis中的token为空,而它需要同时获取最新token,并通知其他的实例也去加载最新的token,这个时候事件广播就可以派上用场了。

由于token缓存在了Redis中,我们首先先容Redis的宣布订阅机制。

Redis中的Pub与Sub

redis不只仅具备缓存的成果,它还拥有一个channel机制,我们可以利用Redis来举办宣布订阅。上述的token流程我们简化一下,省略生存到redis的那一环,直接先容如何通知其他应用刷新token。

引入依赖和设置

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
spring:
  redis:
    database: 0
    host: localhost
    port: 6379

界说TokenService

@Service
public class TokenService {
    @Autowired
    StringRedisTemplate redisTemplate;
    public void getToken(String username) { // <1>
        String token = UUID.randomUUID().toString();
        //模仿http接口利用用户名和暗码获取token
        System.out.println(username + " 乐成获取token ..." + token);
        //发送token刷新广播
        System.out.println("广播token刷新事件 ...");
        redisTemplate.convertAndSend(RedisPubSubConfig.tokenChannel, token);
    }
    public void refreshTokenListener(String token) { // <2>
        System.out.println("接到token刷新事件,刷新 token : " + token);
    }
}

<1> 模仿获取token的要领,获取token的同时发送广播。
<2> 用于吸收其他应用发送过来的广播动静。

设置RedisMessageListenerContainer

在Spring应用中Event是由Spring容器打点的,而在Redis的动静机制中,Event是由RedisMessageListenerContainer打点的。我们为token设置一个channel,用于刷新token:

@Configuration
public class RedisPubSubConfig {
    public final static String tokenChannel = "tokenChannel";
    @Bean
    RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory redisConnectionFactory) {
        RedisMessageListenerContainer redisMessageListenerContainer = new RedisMessageListenerContainer();// <1>
        redisMessageListenerContainer.setConnectionFactory(redisConnectionFactory);
        redisMessageListenerContainer.addMessageListener(tokenRefreshListener(), new ChannelTopic(tokenChannel)); // <2>
        return redisMessageListenerContainer;
    }
    @Autowired
    TokenService tokenService;
    MessageListener tokenRefreshListener() {
        return new MessageListener() {
            @Override
            public void onMessage(Message message, byte[] pattern) {
                byte[] bytes = message.getBody(); // <3>
                tokenService.refreshTokenListener(new String(bytes));
            }
        };
    }
}