前言

2020年即将进入尾声,分享一下在现公司业务处理流程,一起讨论在分布式场景下,如何通过消息流的方式处理各种复杂的业务场景,这里涉及到一些常用组件,后面结合场景与代码来具体说明

场景说明

这里就拿我负责的短信应用来举例,它由3个核心模块组成

  1. 短信网关(接收客户提交短信,接收通道短信回执,转发回执给客户...)
  2. 计费服务(短信计费,购买套餐...)
  3. 短信通道(短信提交到通道...)

痛点

  • 批量提交营销类短信,如客户一次提交10w-20w条短信
  • 短信实时计费,延迟问题
  • 通道限流控制
  • 通知回执延时问题

组件

mysql

redis

阿里云日志

流程如下

痛点解决方案

  • 批量提交短信

批量提交这里主要以下几种情况

  1. 短信内容一致,手机号多个
  2. 短信内容不一致(例如内容携带用户信息等... 通常采用excel上传)
  3. 循环调用接口,提交短信

这里仅针对情况3来说明,首先将用户信息存入redis(先读缓存,再读库),减少在验证与鉴权时对数据库的查询压力,校验通过的消息开始写入收单队列,并记录日志(注意日志一定要异步写入),队列使用的redis队列,以目前的业务承载能力,是完全没有问题的,收单接口的qps可以通过分布式来提升,这个得益于k8s容器伸缩,平时我们一般是5个pod在运行(相当于负载5个应用),在节假日高峰期可以起10个pod,这里性能的瓶颈主要集中在redis队列,如果有更高要求可以尝试换成rabbitmq,kafka等

  • mysql批量持久化

这也一直是我比较迷的一个地方,数据库使用的阿里云mysql,单条循环插入速度在200/s左右,我这里采用的dapper,通过拼接values来批量插入,速度大概能达到3000/s,后面看看有没有更好的方案

  • 短信实时计费,延迟问题

在分布式情况下,实时计费又是一个比较大的性能瓶颈,直接读库,并修改用户条数显然是不行的,这样会出现脏读,导致最终数据不准确而出损(程序员就要背锅),而且效率低下,使用redis分布式锁等同于将分布式改成单应用,需要频繁更新缓存里的用户短信余量,速度大概在150/s - 180/s,消费速度过慢会导致队列里数据堆积,短信延迟过高,特别是通知类短信(如获取验证码)对延迟有较高的要求,这里使用redis的计数器来实现,通过计数器递减的方式,如果短信余量<0则用户短信余量不足,再单独起一个任务,每分钟同步一下用户短信余量,用户充值与短信失败回退,也是对计数器的操作

  • 通道限流控制

通道限流主要是供货商对通道进行流量限制,超频的短信会直接失败,一般出现在营销类短信,因为每条通道的价格(与地域,三网,到达率...有关)都不一样,每个用户都会分配通道,为了让短信尽量成功,程序需要进行限流,这里也是使用redis计数器实现,设置一个1分钟失效的缓存,超过频次后,会尝试其它通道,没有可用通道则再次写入队列

  • 通知回执延时问题

系统拿到回执后,需要将回执通知给客户配置的http地址,并得到客户的响应,未响应的回执会再次入列,直到客户响应,或者超过推送策略(推送3次或超过多长时间),有些客户配置的http地址响应非常慢,或者干脆是一些访问超时的地址,这样会导致通知延迟,通知类发卡密业务的短信对回执有较高要求,这里通过多线程来实现,通过创建多个线程从队列里获取回执并转发

  List<Task> tasks = new List<Task>();
for (int i = 0; i < 10; i++)
{
tasks.Add(Task.Run(async () =>{...}));
}
await Task.WhenAll(tasks);
  • 注意事项
  1. 因为操作redis的地方非常多,为了便于管理,所有redis的key建议统一写在常量类里,并写上注释,并制定对应的规范,方便维护
/// 项目名_类型_操作_参数    有效期
project_queue_action_params
  1. 业务日志,业务日志方便排查问题,建议不要偷懒,在业务的入口跟出口都写上对应的日志信息

.net core 消息流处理流程的更多相关文章

  1. 简述C#中IO的应用 RabbitMQ安装笔记 一次线上问题引发的对于C#中相等判断的思考 ef和mysql使用(一) ASP.NET/MVC/Core的HTTP请求流程

    简述C#中IO的应用   在.NET Framework 中. System.IO 命名空间主要包含基于文件(和基于内存)的输入输出(I/O)服务的相关基础类库.和其他命名空间一样. System.I ...

  2. BTARN 接收消息流以3A7为例

     1.RNIFReceive.aspx 页接收来自发起方的传入消息. (如果发起方是BizTalk则类似于:http://localhost/BTARNApp/RNIFSend.aspx?TPUrl ...

  3. Kafka(分布式发布-订阅消息系统)工作流程说明

    Kafka系统架构Apache Kafka是分布式发布-订阅消息系统.它最初由LinkedIn公司开发,之后成为Apache项目的一部分.Kafka是一种快速.可扩展的.设计内在就是分布式的,分区的和 ...

  4. MQTT协议笔记之消息流

    前言 前面的笔记已把所有消息类型都过了一遍,这里从消息流的角度尝试解读一下. 网络故障 在任何网络环境下,都会出现一方连接失败,比如离开公司大门那一刻没有了WIFI信号.但持续连接的另一端-服务器可能 ...

  5. 源码分析Kafka 消息拉取流程

    目录 1.KafkaConsumer poll 详解 2.Fetcher 类详解 本节重点讨论 Kafka 的消息拉起流程. @(本节目录) 1.KafkaConsumer poll 详解 消息拉起主 ...

  6. [蓝牙] 6、基于nRF51822的蓝牙心率计工程消息流Log分析(详细)

    开机初始化Log Log编号 函数名   所在文件名 000001: main ..\main.c 000002: timers_init ..\main.c 000003: gpiote_init ...

  7. 审核流(2)流程设计-SNF.WorkFlow功能使用说明--SNF快速开发平台3.1

    流程设计 图形化的流程设计,更方便.直观 1.打开“流程设计“程序,如上.点击”新建“如下: 2.红色部分为必填项,审批对象是选择要审批的程序菜单,单据名称是在审核流流转时用于提示的单据名称,还要选择 ...

  8. Android中ListView嵌套GridView的简单消息流UI(解决宽高问题)

    最近搞一个项目,需要用到类似于新浪微博的消息流,即每一项有文字.有九宫格图片,因此这就涉及到ListView或者ScrollView嵌套GridView的问题.其中GridView的高度问题在网上都很 ...

  9. 基于log4j的消息流的实现之二消息传递

    在“基于log4j的消息流的实现之一消息获取”中获取日志消息的部分,修改如下: import org.apache.commons.collections.map.HashedMap; import ...

随机推荐

  1. 如何从0到1的构建一款Java数据生成器-第二章

    前提 在上一章我们提到了并且解决了几只拦路虎,承上启下,下面我们一起来实现一款数据生成器. 对外API /** * @description: 本地数据生成API * @author: peter * ...

  2. 身为电气人,为什么也要学习C语言编程?人生苦短,我学编程!

    说起编程大家可能都听过,但编程究竟是怎么一回事你弄懂了吗? 编程=对计算机程序进行编写,这些程序可以是现在手里拿着的手机.办公的电脑.你点击的页面.浏览的网页,都是有程序让它执行你要它做的事情. PL ...

  3. 【C语言/C++编程学习笔记】:通俗易懂讲解 - 链表!学不会?不存在的!

    C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构.C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现 ...

  4. rabbitmq 交换机模式一 广播模式 fanout

    <?php require_once "./vendor/autoload.php"; use PhpAmqpLib\Connection\AMQPStreamConnect ...

  5. LUMEN框架多数据库连接配置方法

    LUMEN作为一款API导向很浓的框架,配置极简化,默认只支持一路DB配置 然而随着业务复杂度的提高,引入多个数据库连接似乎无法避免,下面介绍一下LUMEN连接多个数据库的配置方法: 修改.env文件 ...

  6. js鼠标、键盘事件实例代码

    1. 鼠标的哪个按键被点击? <html> <head> <script type="text/javascript"> function wh ...

  7. Jquery中$("").事件()和$("").on("事件","指定的元素",function(){});的区别(jQuery动态绑定事件)

    这个是在学习时不懂的问题,记录下来方便查看 转至https://www.cnblogs.com/mr-wuxiansheng/p/7136864.html //绑定 下一页 的点击事件 $(" ...

  8. Python爬虫训练:爬取酷燃网视频数据

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理 项目目标 爬取酷燃网视频数据 https://krcom.cn/ 环境 Py ...

  9. javaweb学习笔记整理补课

    javaweb学习笔记整理补课 * JavaWeb: * 使用Java语言开发基于互联网的项目 * 软件架构: 1. C/S: Client/Server 客户端/服务器端 * 在用户本地有一个客户端 ...

  10. 读高性能Mysql摘要

    类型相关 INT(1)和INT(20)对于存储和计算来说,意义是相同的,他不会限制值的合法范围,只是一些交互工具会用来显示字符的个数 默认是有符号的,可以指定为无符号,增加数据存储范围,如0-255, ...