记 ==> 首次使用rabbitMQ优化项目

news2024/7/6 17:34:59

昨天刚学习完了rabbitMQ,刚好我的项目有个模块挺符合使用rabbitMQ进行异步处理的。

这个模块大概功能是:用户发送的所有帖子都会添加到他的发件箱,当有个新用户关注了他,他发件箱内所有的博客都会被添加到关注他的用户的收件箱里

比如:A关注B,A的收件箱内添加B的所有帖子

后续B再发帖子,直接推送到A的收件箱

有点类似抖音,当我们关注了一个up主,我们可以在关注列表里刷到这个up主的视频,并且是按新发布时间降序排序的

接下来看看我的代码,(ps:本人小白勿喷)

当用户关注一个博主后,利用redis的Zset集合完成feed流TimeLine模式的读扩散(拉模式),从博主的收件箱内拉取所有帖子到用户收件箱。当博主后续再新发帖子,才用写扩散(推模式)推送到收件箱

当用户取关后,从用户收件箱内移除掉被取关博主的帖子

我的理解是,这个接口的功能就是单纯的实现用户关注和取关,并不关注帖子的拉取和删除,并不该把这两个功能冗杂在一个方法里。

于是我便打算用rabbitMQ的directExchange模式进行消息发送,关注或者取关后把消息发布出去,不关注对帖子的拉取的行为,让监听者去慢慢的拉。

修改代码~~

把当前用户和被关注取关的用户ID一起当做消息发送出去

引入AMQP依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

yml内添加rabbitmq配置

更改序列化规则,后续消息使用map发送

写一个config,配置一下交互机,队列,并完成绑定

然后写两个方法分别接听拉取帖子和取消帖子这两个queue

拉取队列

取关队列

我把源码贴出来,献丑啦

package com.brrbaii.mqListener;

import com.brrbaii.dto.Result;
import com.brrbaii.dto.UserDTO;
import com.brrbaii.utils.UserHolder;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Set;

import static com.brrbaii.common.MQConstants.*;
import static com.brrbaii.common.RedisConstants.*;
import static com.brrbaii.utils.SystemConstants.ALREADY_FOLLOW;

@Component
public class FollowListener {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    /**
     * 用户关注后,把被关注用户发件箱内的所有BLOG添加到当前用户的收件箱
     * @param map:被关注的用户ID和当前用户ID
     */
    @RabbitListener(queues = PULL_BLOG_QUEUE)
    public void pullBlog2UserBox(Map<String,String> map){
        if( map == null){
            return;
        }
        String followerId = map.get("followedUserId");
        String userId = map.get("userId");
        //被关注的用户key
        String followBox = FEED_USER_KEY + followerId;

        //功能:关注后,把该用户的发件箱内数据拷贝到粉丝收件箱
        //获取被关注用户所有博客--从0到当前时间就是获取全部,并按照降序排序
        Set<ZSetOperations.TypedTuple<String>> typedTuples = stringRedisTemplate.opsForZSet()
                .reverseRangeByScoreWithScores(followBox, 0, System.currentTimeMillis());

        //用户没有博客,不用获取
        if (typedTuples==null || typedTuples.isEmpty()){
            return;
        }
        //获取当前用户的key
        String userBOx = FEED_PUSH_KEY + userId;

        //把被关注用户的blog添加到“我”的收件箱
        for(ZSetOperations.TypedTuple<String> tuple:typedTuples){
            stringRedisTemplate.opsForZSet().add(
                    userBOx,
                    tuple.getValue(),
                    tuple.getScore()
            );
        }
    }

    /**
     * 用户取关后,从用户的收件箱内清除被取关用户的BLOG
     * @param map:被关注的用户ID和当前用户ID
     */
    @RabbitListener(queues = PUSH_BLOG_QUEUE)
    public void pushBlogFromUserBox(Map<String,String> map){
        if( map == null){
            return;
        }
        String followerId = map.get("followedUserId");
        String userId = map.get("userId");

        String cancelFollower = FEED_USER_KEY + followerId;
        //获取被取关用户的所有blog,这里无需关注score
        Set<String> cancelFollowerBox = stringRedisTemplate.opsForZSet().range(cancelFollower, 0, -1);

        //没有BLOG,直接结束
        if(cancelFollowerBox == null || cancelFollowerBox.isEmpty()){
            return;
        }

        //获取当前用户收件箱
        String userBox = FEED_PUSH_KEY + userId;

        //从当前用户的收件箱里,把被取关用户的博客删除
        for(String blogId : cancelFollowerBox){
            stringRedisTemplate.opsForZSet().remove(userBox,blogId);
        }
    }

}
package com.brrbaii.config;

import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static com.brrbaii.common.MQConstants.*;

@Configuration
public class MQConfig {
    //拉取blog队列
    @Bean
    public Queue pullBlogQueue(){
        System.out.println("为什么没给我创建队列?");
        return new Queue(PULL_BLOG_QUEUE);
    }

    //移出blog队列
    @Bean
    public Queue pushBlogQueue(){
        return new Queue(PUSH_BLOG_QUEUE);
    }

    //声明交换机
    @Bean
    public DirectExchange blogDirectExchange(){
        return new DirectExchange(DIRECT_EXCHANGE_BLOG);
    }

    @Bean
    public Binding pullBlogBinding(Queue pullBlogQueue, DirectExchange blogDirectExchange){
        return BindingBuilder
                .bind(pullBlogQueue)
                .to(blogDirectExchange)
                .with(PULL_BLOG_ROUTING_KEY);
    }
    @Bean
    public Binding pushBlogBinding(Queue pushBlogQueue, DirectExchange blogDirectExchange){
        return BindingBuilder
                .bind(pushBlogQueue)
                .to(blogDirectExchange)
                .with(PUSH_BLOG_ROUTING_KEY);
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/426317.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

binkw32dll缺失怎么办?如何解决binkw32dll修复问题

binkw32dll缺失怎么办&#xff1f;在使用某些计算机游戏或应用程序时&#xff0c;您可能遇到过binkw32dll缺失的问题。这意味着您的计算机无法找到该DLL文件&#xff0c;从而无法正常运行程序。在本文中&#xff0c;我们将探讨binkw32.dll缺失的可能原因并提供解决方案。 一.什…

python flask 接口平台开发

文章目录descFlaskFlask-SQLAlchemyflasggerdesc 考虑到开发的便捷性、生态的丰富程度&#xff0c;用Flask、Flask-SQLAlchemy、flasgger等编写一套简单易用的接口平台 这里记录以下这几个组件的使用方式 Flask 轻量、灵活&#xff0c;相比Django不用遵循太多的开发规范 F…

SSM整合的基本思路梳理

SSM整合的简单思路流程 基本思路 我在整合的时候一般习惯从MyBatis开始向上构建&#xff0c;也就是在开始一个项目的时候先将DAO层搭建起来&#xff0c;再向上整合Spring以及SpringMVC。按照这个流程&#xff0c;可以做出一个比较简单的大致流程作为参考&#xff0c;帮助我们…

企业为什么要做网站?这篇文章告诉你

在如今数字化的时代&#xff0c;企业为什么要做网站&#xff1f;这个问题一直都是企业主和市场营销人员必须要考虑的问题。本文将以一个真实的案例为例&#xff0c;解析为什么企业要做网站以及如何通过网站提升业务和品牌的影响力。 案例背景 以一家小型私人医疗诊所为例&…

【神经网络】tensorflow实验4--Matplotlib数据可视化

1. 实验目的 ①掌握Matplotlib绘图基础 ②运用Matplotlib&#xff0c;实现数据集的可视化 ③运用Pandas访问数据集 2. 实验内容 ①绘制散点图、直方图和折线图&#xff0c;对数据进行可视化 ②下载波士顿数房价据集&#xff0c;并绘制数据集中各个属性与房价之间的散点图&#…

人人可用的敏捷指标工具!Kyligence Zen 正式发布 GA 版

4 月 11 日&#xff0c;Kyligence 指标平台产品发布会成功召开。发布会上&#xff0c;一站式指标平台 Kyligence Zen 正式推出 GA 版&#xff0c;接下来这款人人可用的敏捷指标工具将以更加完善、成熟、稳定的产品性能与功能解决企业面临的指标管理、分析和应用痛点 &#xff0…

【信息论】一、信息与信息论

“The fundamental problem of communication is that of reproducing at one point either exactly or approximately a message selected at another point.” —— Claude Elwood Shannon 1.1 信息的定义 什么是信息&#xff1f;它与消息、信号之间有什么区别和联系&#…

指纹识别q

1、指纹传感器 FTIR(Frustrated Total Internal Reflection)&#xff0c;受抑全内反射。在屏幕的夹层中加入LED光线&#xff0c;当用户按下屏幕时&#xff0c;使夹层的光线造成不同的反射效果&#xff0c;感应器接收光线变化而捕捉用户的施力点。 明显的缺点&#xff1a;体积太…

弹塑性力学--应变硬化

在单轴拉伸试验中&#xff0c;当应力超过屈服强度后&#xff0c;需要施加更大的载荷产生更大的应力&#xff0c;才会使材料发生更多的塑性变形。随着塑性应变的增加&#xff0c;材料变得更强、更难以变形了&#xff0c;因此这个阶段称为“应变硬化”&#xff08;Strain Hardeni…

数据库----------唯一约束、默认约束、零填充约束

目录 1.唯一约束&#xff08;Unique&#xff09; 1.概念 2.语法 3.添加唯一约束 4.删除唯一约束 2.默认约束(default) 1.概念 2.语法 3.添加默认约束 4.删除默认约束 3.零填充约束&#xff08;zerofill&#xff09;了解即可 1.概念 2.操作 3.删除 1.唯一约束&…

如来十三掌(与佛论禅、Rot13编码)

下载附件打开是一串... 佛经 666 这个编码方式还真是第一次遇见----与佛论禅 对文本进行与佛论禅密码解密 得到 MzkuM3gvMUAwnzuvn3cgozMlMTuvqzAenJchMUAeqzWenzEmLJW9 根据题目提示&#xff0c;如来十三掌&#xff0c;猜测是rot13加密&#xff0c;进行rot13解码 得到 Z…

Cloud computing

Cloud computing 可以看到右侧的容器虚拟化架构中&#xff0c;不需要运行额外的OS&#xff0c;这样启动的服务性能会相比于通过虚拟化软件实现的架构更优秀。但是虚拟机同样也有它的优点&#xff0c;比如它的安全、隔离性&#xff0c;可以运行不同的操作系统等等。 Virtualiz…

EasyCVR平台基于GB28181协议的语音对讲配置操作教程

EasyCVR基于云边端协同&#xff0c;具有强大的数据接入、处理及分发能力&#xff0c;平台可支持海量视频的轻量化接入与汇聚管理&#xff0c;可提供视频监控直播、视频轮播、视频录像、云存储、回放与检索、智能告警、服务器集群、语音对讲、云台控制、电子地图、平台级联等功能…

企业网站架构LAMP部署与优化(apache、mysql、php)

目录LAMP概述与简介编译安装Apache http服务1、关闭防火墙&#xff0c;将安装Apache所需软件包传到/opt/apache目录下2、在opt/apache目录下安装http所需软件包3、解压以下文件4、将解压的两个文件移到相应目录5、安装环境依赖包6、配置软件模块7、编译安装8、优化配置文件路径…

【linux】:linux下文件的使用以及文件描述符

文章目录 前言一、linux系统中的文件操作以及文件接口二、文件描述符 1.文件描述符的分配规则2.重定向总结前言 理解文件原理和操作&#xff1a; 我们先快速回忆下一C语言的文件操作&#xff1a; 首先看一下fopen函数的使用&#xff0c;然后我们写一段简单的C语言打开文件的代…

使用conda来管理虚拟环境

百度miniconda 下载windows版&#xff0c;安装的时候添加环境变量Conda -info -e 可以看到只有一个虚拟环境​ ​​​​​​3.Conda命令 &#xff08;1&#x…

高效学习方法分享和学习工具推荐

方法不对&#xff0c;努力白费&#xff1b;方法对了&#xff0c;事半功倍&#xff01; 口号喊起来&#xff0c;气氛拉满&#xff01; 我现在是吉林大学计算机科学与技术大四在读&#xff08;2023春季学期&#xff09;&#xff0c;刚好趁这个活动回顾一下我的大学生活。上过大学…

Android: 在wsl中使用libevent实现http服务器,并编写Android app 实现文件下载

在wsl中使用libevent实现http服务器&#xff0c;并编写Android app 实现文件下载 PC端&#xff1a; 在WSL中编译libevent-2.1.8-stable sample中的http-server.c&#xff0c;实现http测试用服务器 Makefile如下&#xff1a; #指定源文件为*.c src $(wildcard *.c) #通过src…

houjie-cpp面向对象

houjie 面向对象 面向对象&#xff08;上&#xff09; const 在一个函数后面放const&#xff0c;这个只能修饰成员函数&#xff0c;告诉编译器这个成员函数不会改数据 const还是属于函数签名的一部分。 引用计数&#xff1a;涉及到共享的东东&#xff0c;然后当某个修改的时候&…

Java的时代依然还在,合格的Java工程师成为紧缺人才

Java的时代依然还在&#xff0c;合格的Java工程师成为紧缺人才编程语言的世界变化莫测&#xff0c;在其中浮浮沉沉28年的Java&#xff0c;也经历见证了很多语言的兴起和衰败。在最新的编程语言排行榜中&#xff0c;Java依旧位居前三&#xff0c;可见Java的发展后劲有多强&#…