.net core 消息流处理流程
前言
2020年即将进入尾声,分享一下在现公司业务处理流程,一起讨论在分布式场景下,如何通过消息流的方式处理各种复杂的业务场景,这里涉及到一些常用组件,后面结合场景与代码来具体说明
场景说明
这里就拿我负责的短信应用来举例,它由3个核心模块组成
- 短信网关(接收客户提交短信,接收通道短信回执,转发回执给客户...)
- 计费服务(短信计费,购买套餐...)
- 短信通道(短信提交到通道...)
痛点
- 批量提交营销类短信,如客户一次提交10w-20w条短信
- 短信实时计费,延迟问题
- 通道限流控制
- 通知回执延时问题
组件
mysql
redis
阿里云日志
流程如下

痛点解决方案
- 批量提交短信
批量提交这里主要以下几种情况
- 短信内容一致,手机号多个
- 短信内容不一致(例如内容携带用户信息等... 通常采用excel上传)
- 循环调用接口,提交短信
这里仅针对情况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);
- 注意事项
- 因为操作redis的地方非常多,为了便于管理,所有redis的key建议统一写在常量类里,并写上注释,并制定对应的规范,方便维护
/// 项目名_类型_操作_参数 有效期
project_queue_action_params
- 业务日志,业务日志方便排查问题,建议不要偷懒,在业务的入口跟出口都写上对应的日志信息
- 推荐我自己写的一个Redis消息队列中间件InitQ,操作简单可以下载的玩玩 
 https://github.com/wmowm/initq
.net core 消息流处理流程的更多相关文章
- 简述C#中IO的应用  RabbitMQ安装笔记  一次线上问题引发的对于C#中相等判断的思考  ef和mysql使用(一)  ASP.NET/MVC/Core的HTTP请求流程
		简述C#中IO的应用 在.NET Framework 中. System.IO 命名空间主要包含基于文件(和基于内存)的输入输出(I/O)服务的相关基础类库.和其他命名空间一样. System.I ... 
- BTARN 接收消息流以3A7为例
		 1.RNIFReceive.aspx 页接收来自发起方的传入消息. (如果发起方是BizTalk则类似于:http://localhost/BTARNApp/RNIFSend.aspx?TPUrl ... 
- Kafka(分布式发布-订阅消息系统)工作流程说明
		Kafka系统架构Apache Kafka是分布式发布-订阅消息系统.它最初由LinkedIn公司开发,之后成为Apache项目的一部分.Kafka是一种快速.可扩展的.设计内在就是分布式的,分区的和 ... 
- MQTT协议笔记之消息流
		前言 前面的笔记已把所有消息类型都过了一遍,这里从消息流的角度尝试解读一下. 网络故障 在任何网络环境下,都会出现一方连接失败,比如离开公司大门那一刻没有了WIFI信号.但持续连接的另一端-服务器可能 ... 
- 源码分析Kafka 消息拉取流程
		目录 1.KafkaConsumer poll 详解 2.Fetcher 类详解 本节重点讨论 Kafka 的消息拉起流程. @(本节目录) 1.KafkaConsumer poll 详解 消息拉起主 ... 
- [蓝牙] 6、基于nRF51822的蓝牙心率计工程消息流Log分析(详细)
		开机初始化Log Log编号 函数名 所在文件名 000001: main ..\main.c 000002: timers_init ..\main.c 000003: gpiote_init ... 
- 审核流(2)流程设计-SNF.WorkFlow功能使用说明--SNF快速开发平台3.1
		流程设计 图形化的流程设计,更方便.直观 1.打开“流程设计“程序,如上.点击”新建“如下: 2.红色部分为必填项,审批对象是选择要审批的程序菜单,单据名称是在审核流流转时用于提示的单据名称,还要选择 ... 
- Android中ListView嵌套GridView的简单消息流UI(解决宽高问题)
		最近搞一个项目,需要用到类似于新浪微博的消息流,即每一项有文字.有九宫格图片,因此这就涉及到ListView或者ScrollView嵌套GridView的问题.其中GridView的高度问题在网上都很 ... 
- 基于log4j的消息流的实现之二消息传递
		在“基于log4j的消息流的实现之一消息获取”中获取日志消息的部分,修改如下: import org.apache.commons.collections.map.HashedMap; import ... 
随机推荐
- web中的HTML CSS
			HTML 超文本标记语言 页面的结构 首行声明文档类型>根标记>头部标记/主体标记 标记 div 布局 切割 分割 划分区域 spa ... 
- day30 Pyhton 复习模块
			一.模块 什么是模块. 模块就是我们把装有特定功能的代码进行归类的结果. 从代码编写的单位来看我们的程序, 从小到大的顺序: 一条代码 < 语句句块 < 代码块(函数, 类) < 模 ... 
- JS中实现Trim(),TrimStart(),TrimEnd() 的方法
			//去除字符串头尾空格或指定字符 String.prototype.Trim = function (c) { if (c == null || c == "") { var st ... 
- docker设置http访问
			1 编辑配置文件 vim /etc/docker/daemon.json { "registry-mirrors": ["https://a4fyjv0u.mirr ... 
- 转 RabbitMQ 入门教程(PHP版) 使用rabbitmq-delayed-message-exchange插件实现延迟功能
			延迟任务应用场景 场景一:物联网系统经常会遇到向终端下发命令,如果命令一段时间没有应答,就需要设置成超时. 场景二:订单下单之后30分钟后,如果用户没有付钱,则系统自动取消订单. 场景三:过1分钟给新 ... 
- centos8平台使用journalctl管理systemd-journald日志
			一,systemd-journald的作用 1,什么是systemd-journald? systemd-journald 是 systemd 自带的日志系统,是一个收集并存储各类日志数据的系统服务. ... 
- 跟我一起学Redis之看完这篇比常人多会三种类型实战(又搞了几个小时)
			前言 对于Redis而言,很多小伙伴只关注其关键的五大基础类型:string.hash.list.set.sorted set(有序集合),其实还有三种特殊类型在很多应用场景也比较适合使用,分别是:b ... 
- 建议你吃透python这68个内置函数!
			内置函数就是Python给你提供的, 拿来直接用的函数,比如print,input等. 截止到python版本3.6.2 ,一共提供了68个内置函数,具体如下 abs() dict() help() ... 
- Spring Shiro配置第三方SSO客户端登录
			经过实践的Shiro配置,利用 sSOInterceptor 进行sso登录拦截 配置 @Configuration public class ShiroConfiguration extends B ... 
- python基础三:函数
			def name(参数1,参数2,参数3,...) 可以自定义一些自己需要的函数来简化自己的工作. 如:自定义一个计算函数 def mycount(a,b,c): y=a+b-c return y ... 
