前言

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. 【7】进大厂必须掌握的面试题-Java面试-Jsp

    1. jsp的生命周期方法是什么? 方法 描述 公共无效的jspInit() 与servlet的init方法相同,仅被调用一次. 公共无效_jspService(ServletRequest requ ...

  2. day27 Pyhton 面向对象02 类和对象的命名空间

    一.内容回顾 类:具有相同属性和方法的一类事务 # 描述一类事务轮廓的一个机制 #商品/用户/店铺 对象/实例: 对象(实例)就是类的实例化 # 对象就是类的一个具体的表现 #某一件特定的商品/某个人 ...

  3. python知识点整理一

    1.数组元素之和 解法一 from functools import reduce list=[1,3,5,7,9,34] print(reduce(lambda x,y:x+y,list)) 解法二 ...

  4. swoole为什么不建议使用static和global

    $http = new swoole_http_server("0.0.0.0", 9501); $http->on("request", functio ...

  5. centos8平台redis cluster集群搭建(redis5.0.7)

    一,规划 redis cluster 1,cluster采用六台redis,3主3从 redis1    : ip: 172.17.0.2 redis2    : ip: 172.17.0.3 red ...

  6. Flink on Yarn三部曲之一:准备工作

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  7. Business Partner - 供应商与客户的集成 - S/4HANA(1)

    本文基于S/4HANA 1511版本,同时大部分内容适用于S/4HANA i.e1610/1709/1809. 本文旨在为全新实施的BP配置,或从ECC到S/4HANA的供应商客户主数据迁移提供信息支 ...

  8. java中true不是关键字?

    java中true ,false , null在java中不是关键字,也不是保留字,它们只是显式常量值,但是你在程序中不能使用它们作为标识符. 其中const和goto是java的保留字.java中所 ...

  9. better-scroll 与 Vue 结合

    什么是 better-scroll better-scroll 是一个移动端滚动的解决方案,它是基于 iscroll 的重写,它和 iscroll 的主要区别在这里.better-scroll 也很强 ...

  10. Redis---07主从复制(哨兵模式)

    一.什么是哨兵模式 基于主从复制的一般模式(一主二从)下,当发生主机发生宕机时,会通过流言协议判断主机是不是宕机,是的话则会通过投票协议自动把某一个从机转换成主机. 二.设置哨兵模式的配置文件 通过r ...