rocketmq实现限流

目录

问题背景

技术方向

方案确认

消息队列(√)

分布式锁(×)

方案实现

监控方向

业务方向


问题背景

公司邮件服务token有 分钟内超200封的熔断机制,当前token被熔断后,系统发邮件操作会被忽略,所以邮件服务也没有重试操作

人工发现token被熔断后,需要联系邮件群中值班人,将token恢复

分货业务依赖邮件来查看分货通知以及结果,并且分货层层依赖,如果不能及时收到邮件会影响业务的分货时效等,所以通过三个方面去解决这个问题

技术方向

系统内发邮件收口做限流

方案确认

方向:限流发邮件方法1分钟内最大200次

实现:改造系统发邮件底层方法,1分钟内最多发200个

消息队列(√)

面临问题:多出来的怎么处理?消息队列(需要持久化)

实现:新建一个topic,调用发邮件方法的请求全部扔到MQ中,自己消费,通过设置消费者的拉取间隔以及最大拉取数量限制,分钟内消费消息条数不超过200条

面临问题:多分区多消费者?

实现:默认拉取数量为32,目前MQ服务端设置,限制最大拉取数量为32

(可行)设置1个分区,一个消费者组,目前有2个实例(此时其中一个实例不会消费),设置拉取间隔为10s

(不可行,有自动加实例机制)设置2个分区,一个消费者组,目前有2个实例,设置拉取间隔为10s,最大拉取条数为16;系统在流量激增的情况下会增加实例来分摊流量

最终实现方式

topic设置1个分区,一个消费者组,使用默认负载均衡策略:平均分配

//平均分配负载均衡核心逻辑
int index = cidAll.indexOf(currentCID);
int mod = mqAll.size() % cidAll.size();
int averageSize = mqAll.size() <= cidAll.size() ? 1 : (mod > 0 && index < mod ? mqAll.size() / cidAll.size() + 1 : mqAll.size() / cidAll.size());
int startIndex = mod > 0 && index < mod ? index * averageSize : index * averageSize + mod;
int range = Math.min(averageSize, mqAll.size() - startIndex);

for(int i = 0; i < range; ++i) {
    result.add(mqAll.get((startIndex + i) % mqAll.size()));
}

return result;

解析两个实例负载均衡过程

//第一个实例起来,触发负载均衡
//index = 0
int index = cidAll.indexOf(currentCID);
//mod = 1%2 = 1
int mod = mqAll.size() % cidAll.size();
//averageSize = 1
int averageSize = mqAll.size() <= cidAll.size() ? 1 : (mod > 0 && index < mod ? mqAll.size() / cidAll.size() + 1 : mqAll.size() / cidAll.size());
//startIndex = 0 * 1 = 0
int startIndex = mod > 0 && index < mod ? index * averageSize : index * averageSize + mod;
//range = min(1, 1 - 0) = 1
int range = Math.min(averageSize, mqAll.size() - startIndex);

for(int i = 0; i < range; ++i) {
    //(0+0)%1 = 0,所以将第一个分区分给当前实例
    result.add(mqAll.get((startIndex + i) % mqAll.size()));
}

//第二个实例起来,触发负载均衡
//index = 1
int index = cidAll.indexOf(currentCID);
//mod = 1%2 = 1
int mod = mqAll.size() % cidAll.size();
//averageSize = 1
int averageSize = mqAll.size() <= cidAll.size() ? 1 : (mod > 0 && index < mod ? mqAll.size() / cidAll.size() + 1 : mqAll.size() / cidAll.size());
//startIndex = 1 * 1 + 1 = 2
int startIndex = mod > 0 && index < mod ? index * averageSize : index * averageSize + mod;
//range = min(1, 1 - 2) = -1
int range = Math.min(averageSize, mqAll.size() - startIndex);

//不会进入循环分配分区
for(int i = 0; i < range; ++i) {
    result.add(mqAll.get((startIndex + i) % mqAll.size()));
}

所以只会有一个实例去消费当前这个分区,在集群消费模式下,一个分区只会被消费组内的一个消费者消费,rmq默认拉取数量为32,设置拉取间隔为10s,所以每分钟内消费:32*6 = 192

分布式锁(×)

当前场景的点,在于需要将超出1分钟两百条的那些邮件持久化存储,等到下一个一分钟去发送,而分布式锁只能实现控制接口的流量,没法保证超出流量那部分的存储,所以没法解决当前问题

方案实现

最终采用消息队列,RocketMQ解决该问题

实现代码,使用Java SDK,设置拉取间隔为10s即可

public void run(String... args) throws Exception {
    Properties properties = new Properties();
    properties.setProperty(ConfigKey.CONSUMER_GROUP, emailNotifyMqProperties.getConsumerGroup());
    properties.setProperty(ConfigKey.ACCESS_KEY, rocketMqProperties.getAccessKey());
    properties.setProperty(ConfigKey.SECRET_KEY, rocketMqProperties.getSecretKey());
    properties.setProperty(ConfigKey.NAME_SERVER_ADDR, rocketMqProperties.getServer());
    properties.setProperty(ConfigKey.ENABLE_MSG_TRACE, "true");
    //消费限流:解决发邮件分钟内超过200封会被熔断的问题
    properties.setProperty(ConfigKey.PULL_INTERVAL, "10000");

    NormalConsumer consumer = ClientFactory.createNormalConsumer(properties, this::consumeMessage);

    consumer.subscribe(emailNotifyMqProperties.getTopic(), null);
    consumer.start();
}

监控方向

1. 系统日志报警,配置邮件发送失败报警

2. 关注token熔断消息通知

业务方向

梳理当前系统中邮件通知的场景,分析报警内容,从以下方向减少邮件次数发送

1. 用户是否需要关注(用户长时间使用下来,部分通知发现自己并不关注的,比如节点报错可重试成功的

2. 是否可以批量发送(多条通知集合到一条邮件发送:多用户,多单据等)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用F1C200S从零制作掌机之构建debian文件系统

前情&#xff1a;使用buildrootfs构建的文件系统调试了很久NES模拟器&#xff0c;执行InfoNES模拟器的时候一直黑屏&#xff0c;无内容显示&#xff0c;调不通了&#xff0c;所以改用debian系统试试。 一、环境配置 首先下载两个工具&#xff1a;qemu-arm-static和debootstra…

如何在 Microsoft Edge 上使用开发人员工具

Microsoft Edge 提供了一套强大的开发人员工具&#xff0c;可帮助 Web 开发人员检查、调试和优化他们的网站或 Web 应用程序。 无论您是经验丰富的 Web 开发人员还是刚刚起步&#xff0c;了解如何有效地使用这些工具都可以对开发过程产生重大影响。 在本文中&#xff0c;我们…

vb.netcad二开自学笔记8:界面之任务窗格

使用net可以创建一个类似属性面板的自定义的任务窗格&#xff0c;从而实现应用程序更丰富的人机交互。 1、添加一个自定义控件 2、在前面创建的代码框架内增加一个命令函数ShowMyPalette Imports System.Windows.Media.Imaging Imports Autodesk.AutoCAD.ApplicationServices …

电机控制杂谈——位置环到底该用什么调节器?

1.为什么位置环用P调节器尽可以实现无静差调节&#xff1f; 当时在学《运动控制》这门课程时&#xff0c;用的是陈伯时老师的教材。在介绍调节器的时候&#xff0c;教材中说到&#xff0c;P&#xff08;比例&#xff09;调节器会存在稳态误差&#xff0c;所以在转速环和电流环…

html——VSCode的使用

快捷键 快速生成标签&#xff1a;标签名tab 保存文件&#xff1a;CtrlS 设置自动保存【文件】→【自动保存】 快速查看网页效果&#xff1a;右击→Open in Default Browser 快捷键&#xff1a;altb 注意&#xff1a;必须安装了open in brows…

显示渲染-OSG框架解析

1.背景介绍 1.1 OSG介绍 OSG的全称&#xff1a;OpenSceneGraph&#xff0c;它是一个开放源码&#xff0c;跨平台的图形开发包&#xff0c;它为诸如飞行器仿真&#xff0c;游戏&#xff0c;虚拟现实&#xff0c;科学计算可视化这样的高性能图形应用程序开发而设计。 它基于场…

生成图质量评价

1. RichHF-18K 论文地址 解决问题&#xff1a; 如何对生成图质量进行算法评价&#xff0c;以优化图片质量&#xff0c;提升模型生成能力 解决思路&#xff1a; 参考多模态模型&#xff0c;构建评价模型&#xff0c;从7个维度分三个分支对生成图进行测评&#xff1a; Tips&…

简单仿写MVC

代码地址&#xff08;需要自取&#xff09;&#xff1a;mvc_Imitation: 简单仿写实现MVC (gitee.com) 项目目录 先把架子搭好 Controller注解 Documented Retention(RetentionPolicy.RUNTIME) Target(ElementType.TYPE) public interface Controller { }RequestMapping Do…

java设计模式(十一)组合模式(Composite Pattern)

1、模式介绍&#xff1a; 组合模式是一种结构型设计模式&#xff0c;它允许你将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。 2、应用场景&#xff1a; 表示树形结构&#xff1a;当你需要表示对象的部分-整体…

2024年06月CCF-GESP编程能力等级认证Python编程四级真题解析

本文收录于专栏《Python等级认证CCF-GESP真题解析》&#xff0c;专栏总目录&#xff1a;点这里&#xff0c;订阅后可阅读专栏内所有文章。 一、单选题&#xff08;每题 2 分&#xff0c;共 30 分&#xff09; 第 1 题 小杨父母带他到某培训机构给他报名参加CCF组织的GESP认证…

前端视角下的Spring-Boot语法学习:打印 hello-world

今日话题 基于 Spring Boot 打印输出 hello world 作者&#xff1a;云层上的光 时间&#xff1a;2024年6月20日 14时25分14秒 主线任务 一、打印 hello world 1、点击 “新建项目”用来演示 打印输出 “hello world” 2、填写项目配置&#xff1a;&#xff08;详细版见&a…

Python基础知识——(002)

文章目录 P8——7. input函数的使用 基本的输入函数input P9——8. Python中的注释 P10——9. Python中的缩进与本章总结 本章总结 P11——10. 章节习题 P8——7. input函数的使用 基本的输入函数input 语法结构&#xff1a; x input(提示文字) 注意事项&#xff1a;无论输…

【matlab】【python】爬虫实战

目录 引言 具体步骤 1.设置请求选项 2.发送请求并获取响应 3.设置正则表达式 4.执行正则表达式匹配 matlab完整代码 python代码示例 引言 在当今这个信息爆炸的时代&#xff0c;数据已成为推动社会进步和企业发展的核心动力之一。随着互联网的普及和技术的飞速发展&am…

前端视角下的Spring-Boot语法学习:demo-crud 实现增删改查

今日话题 基于 Spring Boot 实现增删改查&#xff0c;仅仅只是提供接口不涉及数据库增删改查 作者&#xff1a;云层上的光 时间&#xff1a;2024年6月21日 15时19分14秒 主线任务 一、项目创建 1、基于 idea 创建项目 2、选择项目依赖 Spring Web 二、实现增删改查 1、新…

Pix4Dmapper:无人机测绘的革命性工具

在现代测绘和地理信息系统&#xff08;GIS&#xff09;领域&#xff0c;Pix4Dmapper无疑是一款革命性的工具。作为一名长期使用这款软件的用户&#xff0c;我深深感受到它在工作中的重要性和便利性。Pix4Dmapper不仅仅是一款软件&#xff0c;更是测绘工作者的得力助手&#xff…

Selenium 的基本操作你知道哪些?

1. 前言 今天的推文&#xff0c;我们就来说说看&#xff0c;怎么实现模拟真人去打开微信读书网站。 2.需求分析和准备 整体的需求大致可以分为以下步骤&#xff1a; 打开chrome浏览器 打开百度网页 搜索“微信读书” 点击进入“微信读书”官网 搜索关键词“长安的荔枝” 点…

2023.2版IDEA复制配置修改端口增加一个当前运行服务的操作流程

文章目录 前言操作流程截图 前言 在微服务技术学习中很多学习场景会使用到运行多个服务节点进行调试&#xff0c;想要去模拟集群部署&#xff0c;就需要去复制配置&#xff0c;本文讲解一下如何复制&#xff0c;以及修改端口号。 操作流程截图

现代化木工装备建设新颖校园木工创客室

校园木工创客室是一个集木工制作、创意设计、科技融合与教育实践于一体的多功能空间。它为学生提供了一个动手实践、创新创造的平台&#xff0c;旨在培养学生的动手能力、创新思维、解决问题的能力以及团队协作能力。 木工创客室的设备选择应综合考虑需求、预算、品牌、质量、安…

Git常用技能速成

文章目录 一.版本控制二.提交并推送代码三.提交推送代码 一.版本控制 接下来&#xff0c;我们就需要对我们的功能进行优化&#xff0c;但是需要说明的是&#xff0c;我们不仅仅要对上述提到的缓存进行优化&#xff0c;还需要对我们程序的各个方面进行优化。我们本章节主要是针…

vue3在defineProps中使用多语言t,打包报错

报错原因 代码如下 打包后就会报错 defineProps() in script setup cannot reference locally declared variables because it will be hoisted outside of the setup() function. If your component options require initialization in the module scope, use a separate no…