为了账号安全,请及时绑定邮箱和手机立即绑定

JavaWeb项目架构之Redis分布式日志队列

标签:
JQuery

架构、分布式、日志队列,标题自己都看着唬人,其实就是一个日志收集的功能,只不过中间加了一个Redis做消息队列罢了。


前言

为什么需要消息队列?

当系统中出现“生产“和“消费“的速度或稳定性等因素不一致的时候,就需要消息队列,作为抽象层,弥合双方的差异。

比如我们系统中常见的邮件、短信发送,把这些不需要及时响应的功能写入队列,异步处理请求,减少响应时间。

如何实现?

成熟的JMS消息队列中间件产品市面上有很多,但是基于目前项目的架构以及部署情况,我们采用Redis做消息队列。

为什么用Redis?

Redis中list数据结构,具有“双端队列”的特性,同时redis具有持久数据的能力,因此redis实现分布式队列是非常安全可靠的。

它类似于JMS中的“Queue”,只不过功能和可靠性(事务性)并没有JMS严格。Redis本身的高性能和"便捷的"分布式设计(replicas,sharding),可以为实现"分布式队列"提供了良好的基础。

提供者端

项目采用第三方redis插件spring-data-redis,不清楚如何使用的请自行谷歌或者百度。

redis.properties:

#redis 配置中心 redis.host=192.168.1.180redis.port=6379redis.password=123456redis.maxIdle=100 redis.maxActive=300 redis.maxWait=1000 redis.testOnBorrow=true redis.timeout=100000

redis配置:

    <!-- redis 配置 -->    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig" />    <bean id="jedisConnectionFactory"        class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">        <property name="hostName" value="${redis.host}" />        <property name="port" value="${redis.port}" />        <property name="password" value="${redis.password}" />        <property name="timeout" value="${redis.timeout}" />        <property name="poolConfig" ref="jedisPoolConfig" />        <property name="usePool" value="true" />    </bean>    <bean id="redisTemplate"  class="org.springframework.data.redis.core.StringRedisTemplate">        <property name="connectionFactory" ref="jedisConnectionFactory" />    </bean>

切面日志配置(伪代码):

/** * 系统日志,切面处理类 * 创建者 小柒2012 * 创建时间 2018年1月15日 */@Component@Scope@Aspectpublic class SysLogAspect {    @Autowired    private RedisTemplate<String, String> redisTemplate;    //注解是基于swagger的API,也可以自行定义    @Pointcut("@annotation(io.swagger.annotations.ApiOperation)")    public void logPointCut() {     }    @Around("logPointCut()")    public Object around(ProceedingJoinPoint point) throws Throwable {        Object result = point.proceed();        //把日志消息写入itstyle_log频道        redisTemplate.convertAndSend("itstyle_log","日志数据,自行处理");        return result;    }}

消费者端

Redis配置:

    <!-- redis 配置 -->    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig" />    <bean id="jedisConnectionFactory"        class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">        <property name="hostName" value="${redis.host}" />        <property name="port" value="${redis.port}" />        <property name="password" value="${redis.password}" />        <property name="timeout" value="${redis.timeout}" />        <property name="poolConfig" ref="jedisPoolConfig" />        <property name="usePool" value="true" />    </bean>    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"                      p:connection-factory-ref="jedisConnectionFactory">          <property name="keySerializer">              <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />          </property>          <property name="hashKeySerializer">              <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />          </property>      </bean>    <!-- 监听实现类 -->    <bean id="listener" class="com.itstyle.market.common.listener.MessageDelegateListenerImpl"/>    <bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer" />    <redis:listener-container connection-factory="jedisConnectionFactory">        <!-- topic代表监听的频道,是一个正规匹配  其实就是你要订阅的频道-->        <redis:listener ref="listener" serializer="stringRedisSerializer" method="handleLog" topic="itstyle_log"/>    </redis:listener-container>

监听接口:

public interface MessageDelegateListener {    public void handleLog(Serializable message);}

监听实现:

public class MessageDelegateListenerImpl implements MessageDelegateListener {        @Override        public void handleLog(Serializable message) {            if(message == null){                System.out.println("null");            }else {                //处理日志数据            }        }}

Q&A

  • 【问题一】为什么使用Redis?
    上面其实已经有做说明,尽管市面上有许多很稳定的产品,比如可能大家会想到的Kafka、RabbitMQ以及RocketMQ。但是由于项目本身使用了Redis做分布式缓存,基于省事可行的原则就选定了Redis。

  • 【问题二】日志数据如何存储?
    原则上是不建议存储到关系数据库的,比如MySql,毕竟产生的日志数量是巨大的,建议存储到Elasticsearch等非关系型数据库。

  • 【问题三】切面日志收集是如何实现的?
    切面日志需要引入spring-aspects相关Jar包,并且配置使Spring采用CGLIB代理 <aop:aspectj-autoproxy proxy-target-class="true" />。


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消