今日指数项目项目集成RabbitMQ与CaffienCatch

今日指数项目项目集成RabbitMQ与CaffienCatch

一. 为什么要集成RabbitMQ

首先CaffeineCatch 是作为一个本地缓存工具 使用CaffeineCatch 能够大大较少I/O开销

股票项目 主要分为两大工程 --> job工程(负责数据采集) , backend(负责业务处理)

由于股票的实时性也就是说 , 对于股票来说像大盘数据 , 个股数据等都是每分钟进行更新的

而使用传统的采集以及业务处理方式 , 也就是说 数据采集后将数据保存到数据库中 , 然后客户从数据库中反复获取数据

当用户数量增多 , 数据库的I/O开销也会随之增大 , 会导致时效性的降低

所以这里我采用MQ加CaffeineCatch , 在job工程中采集数据后 写入数据库 , 同时通过MQ发送消息给backend工程 重新加载缓存

将数据库中的数据读取到CaffeineCatch 中

二. job工程代码实现

1. 导入mq依赖

复制代码
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

2. 定义配置文件

复制代码
spring:
  rabbitmq:
    host: 114.116.244.165 # rabbitMQ的ip地址
    port: 5672 # 端口
    username: jixu
    password: 123321
    virtual-host: /

3. 编写服务端代码

复制代码
package com.jixu.stock.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MqConfig {
    // 定义大盘消息序列化方式
    @Bean
    public MessageConverter messageConverter(){
        return new Jackson2JsonMessageConverter();
    }

    // 定义主题交换机
    @Bean
    public TopicExchange topicExchange(){
        return new TopicExchange("stockExchange",true,false);
    }

    // 定义大盘队列
    @Bean
    public Queue stockMarketQueue(){
        return new Queue("marketQueue",true);
    }
    @Bean
    // 绑定大盘信息
    public Binding bindingStockeMarket(){
        // with( Routingkey 参数 --> 匹配的队列名称 )
        return BindingBuilder.bind(stockMarketQueue()).to(topicExchange()).with("inner.market");
    }
}

4. 定义客户端

复制代码
package com.jixu.stock.config;

import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Date;

@Configuration
@Slf4j
public class MqConfig {
    // 定义大盘消息序列化方式
    @Bean
    public MessageConverter messageConverter(){
        return new Jackson2JsonMessageConverter();
    }

    // 客户端接受信息
    @RabbitListener(queues = "marketQueue")
    public void stockMarketListener(Date date){
        long diffTime= DateTime.now().getMillis()-new DateTime(date).getMillis();
        //超过一分钟告警
        if (diffTime>60000) {
            log.error("采集国内大盘时间点:{},同步超时:{}ms",new DateTime(date).toString("yyyy-MM-dd HH:mm:ss"),diffTime);
        }
    }
}

3. 修改业务层代码

在数据插入成功后发送消息给MQ

复制代码
log.info("当前时间点{} , 数据插入成功", DateTime.now().toString("yyyy-MM-dd HH-mm-ss"));
rabbitTemplate.convertAndSend("stockExchange","inner.market",new Date());

三. backend工程代码实现

首先在实现业务逻辑之前需要导入相关依赖 , 以及配置MQ和CaffineCache

1. 配置MQ配置类

复制代码
package com.jixu.stock.config;

import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Date;

@Configuration
@Slf4j
public class MqConfig {
    // 定义大盘消息序列化方式
    @Bean
    public MessageConverter messageConverter(){
        return new Jackson2JsonMessageConverter();
    }


}

2. 配置CaffineCache配置类

复制代码
 	/**
     * 配置CaffienCatch
     */
    @Bean
    public Cache<String,Object> caffeineCache(){
        Cache<String, Object> cache = Caffeine
                .newBuilder()
                .maximumSize(200)//设置缓存数量上限
//                .expireAfterAccess(1, TimeUnit.SECONDS)//访问1秒后删除
//                .expireAfterWrite(1,TimeUnit.SECONDS)//写入1秒后删除
                .initialCapacity(100)// 初始的缓存空间大小
                .recordStats()//开启统计
                .build();
        return cache;
    }

3. 创建客户端类接收信息

复制代码
package com.jixu.stock.mq;

import com.jixu.stock.service.StockService;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.github.benmanes.caffeine.cache.Cache;
import java.util.Date;

/**
 * @program: stock_parent
 * @description:
 * @author: jixu
 * @create: 2024-10-01 12:45
 **/
@Component
@Slf4j
public class StockMarketMQ {

    @Autowired
    private Cache caffeineCache;

    @Autowired
    private StockService service;

    // 客户端接受信息
    @RabbitListener(queues = "marketQueue")
    public void stockMarketListener(Date date){
        long diffTime= DateTime.now().getMillis()-new DateTime(date).getMillis();
        //超过一分钟告警
        if (diffTime>60000) {
            log.error("采集国内大盘时间点:{},同步超时:{}ms",new DateTime(date).toString("yyyy-MM-dd HH:mm:ss"),diffTime);
        }


    }
}

在信息接受之后需要对业务层代码进行修改 --> 实现CaffineCache缓存

这里我们使用CaffineCache.get的方法 , 其中会传入两个参数 , 分别是要从CaffineCache中查询的数据的key ,以及如果key不存在使用的补救方法(从数据库中查询)

4. 完善业务代码

复制代码
/**
     * 实现股票大盘数据查询
     * @return
     */
    @Override
    public R<ArrayList<InnerMarketDomain>> getInnerMarketDomain() {

        R<ArrayList<InnerMarketDomain>> msg = (R<ArrayList<InnerMarketDomain>>) caffeineCache.get("stockMarketMsg" , key -> {
            // 1. 获取最新时间数据
            Date curTime = DateTimeUtil.getLastDate4Stock(DateTime.now()).toDate();
            // 创建mock数据
            curTime = DateTime.parse("2022-01-02 09:32:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();

            // 2. 获取股票代码
            ArrayList<String> marketInfo = stockInfoConfig.getInner();

            // 3. dao层查询数据
            ArrayList<InnerMarketDomain> data = stockMarketIndexInfoMapper.getMarketInfo(curTime , marketInfo);

            return R.ok(data);
        });
        return msg;


    }

5. 完善StockMarketMQ类刷新数据

复制代码
// 清除caffeineCache中的缓存
caffeineCache.invalidate("stockMarketMsg");
// 调用service重新获取
service.getInnerMarketDomain();
相关推荐
坐吃山猪4 小时前
SpringBoot01-配置文件
java·开发语言
我叫汪枫4 小时前
《Java餐厅的待客之道:BIO, NIO, AIO三种服务模式的进化》
java·开发语言·nio
yaoxtao5 小时前
java.nio.file.InvalidPathException异常
java·linux·ubuntu
Swift社区6 小时前
从 JDK 1.8 切换到 JDK 21 时遇到 NoProviderFoundException 该如何解决?
java·开发语言
DKPT7 小时前
JVM中如何调优新生代和老生代?
java·jvm·笔记·学习·spring
phltxy7 小时前
JVM——Java虚拟机学习
java·jvm·学习
seabirdssss8 小时前
使用Spring Boot DevTools快速重启功能
java·spring boot·后端
喂完待续9 小时前
【序列晋升】29 Spring Cloud Task 微服务架构下的轻量级任务调度框架
java·spring·spring cloud·云原生·架构·big data·序列晋升
benben0449 小时前
ReAct模式解读
java·ai