dotnet core使用IO合并技巧轻松实现千万级消息推送
之前讲述过多路复用实现单服百万级别RPS吞吐,但在文中有一点是没有说的就是消息IO合并,如果缺少了消息IO合并即使怎样多路复用也很难达到百万级别的请求响毕竟所有应用层面的网络IO读写都是非常损耗性能的(需要硬件配置很高的服务器)。这一章主要讲述的是IO合并的应用,并通过这个特性实现普通单服务千万级别的消息推送测试。
什么是消息IO合并
所谓的消息IO合并即是由原来一个消息对应一个网络读写设计成多个消息共享一个网络读写。那这样的设计到底会带来多大的性能提升,最简单的对比场就是每次执行1条SQL执行1万次和直接批执行1万条SQL的差别,相信做过的朋友一定非常清楚其性能提升的幅度。那在网络通讯中如何设计才能让多个消息进行IO合并呢?作者在实际实践中的方式有两种:1)通过定时器把队列中的所有消息定期合并发送,2)通过一个状态机归递消息队列,一旦队列存在消息一次过合并发送。定时器这种比较损耗性能,在连接量大的情况存在延时间相互影响;对于后者则比较好控制很多也不存在延时性,原理发送消息进队列后和网络发送完成再回到状态机检测消息队列状态即可。
消息推送相对于请求响应来说相还是简单很多的,毕竟消息推送是单向并不需要有高效的响应机制。不过对于普通服务器间实现千万级的消息推送还是需要做些规划,毕竟是需要在有限的IO读写量的情况来达到这么大规模的消息处理。还有这么大量的消息序列化和反序列化也是一非常损耗性能的事情,所以这次实践并没有使用Protobuf,而是采用自定义序列化。测试的通讯组件选择Beetlex因为它具备了自动消息合并能力,并配合高效的多复路用机制在服务之间进行千万级别的消息推变得简单。
测试简述
这一次测试主要是向服务端推着一个简单的订单信息,由客户每次生成不同的订单信息推送给服务端,服务器接收订单消息后进行统计,并计算每秒接收的订单数量。
消息结构
public class Order
{
public long ID;
public string Product;
public int Quantity;
public double Price;
public double Total;
}
创建订单
private static long mId;
private static string[] mProducts = new string[] { "Apple", "Orange", "Banana", "Citrus", "Mango" };
private static int[] mQuantity = new int[] { , , , , , , };
private static double[] mPrice = new double[] { 2.3, 1.6, 3.2, 4.6, , };
public static Order CreateOrder()
{
Order order = new Order();
order.ID = System.Threading.Interlocked.Increment(ref mId);
order.Product = mProducts[order.ID % mPrice.Length];
order.Quantity = mQuantity[order.ID % mQuantity.Length];
order.Price = mPrice[order.ID % mPrice.Length];
order.Total = order.Quantity * order.Price;
return order;
}
基于测试资源有限,这次的测试并没像之前跑PRS那样采用Protobuf,因为这量的对象处理量实在太大,测试的硬件环境不变所以采了自定义的序列化方式,具体可以参考源代码。
接收端代码
public override void SessionPacketDecodeCompleted(IServer server, PacketDecodeCompletedEventArgs e)
{
PushMessages.Order order = (PushMessages.Order)e.Message;
if (order.ID > MaxOrerID)
MaxOrerID = order.ID;
System.Threading.Interlocked.Increment(ref Count);
}
由于是接收推送的消息,服务端接收消息后统计相关数量即可完成,对于之前的RPS测试所需处理的东西就少很多了。
推送端压测代码
public void Run()
{
foreach (var item in mClients)
System.Threading.ThreadPool.QueueUserWorkItem(OnRun, item);
}
private void OnRun(object state)
{
AsyncTcpClient item = (AsyncTcpClient)state;
while (true)
{
Order order = OrderFactory.CreateOrder();
item.Send(order);
if (order.ID > MaxOrerID)
MaxOrerID = order.ID;
System.Threading.Interlocked.Increment(ref Count);
if (item.Count > )
System.Threading.Thread.Sleep();
}
}
为了防止压爆连接内部的消息队列,压测端当连接队列超过2000个消息的时候停止一下。由于采用了消息合并机制所以并不需要太多连接,在整个测试过程中开启了三个压测实例,每个实例使用5个连接,换句话说BeetleX通过15个连接,实现千万级消息的推送能力。
测试服务器资源
这次测试使用了两家云服务器,第一家名字就不说了,开启了V16核的虚拟服务器,内部带宽6G和100万pps,结果实际压测2G带宽就压不上去了,刚开始以为是linux系统要配置问题,换了windows系统试一下还是不行……,最终还是换回了阿里云测,在v12核的虚拟服务器上顺利完成了这一次测试。
服务端: v12核,24G内存,操作系统ubuntu16.04 一台,内网最大带宽4Gb.
压测端: v12核,24G内存,操作系统ubuntu16.04,内网最大带宽4Gb, 两台(主要测试方式有些暴力一台无法达到压测目标)
测试结果
二台压测机共开启了3个实例,每个实例5个连接,每个连接应用层处理的buffer 32k;整个测结果消息推送量达到了1000万个/秒。服务端记录接收IO每秒15000次,平均每次receive得到的消息大概在600个左右。以下是测试情况的截图:
服务程序统计情况
服务端CPU情况
网络使用情况
下功测试代码
dotnet core使用IO合并技巧轻松实现千万级消息推送的更多相关文章
- Socket.io+Notification实现浏览器消息推送
前言 socket.io: 包含对websocket的封装,可实现服务端和客户端之前的通信.详情见官网(虽然是英文文档,但还是通俗易懂).Notification: Html5新特性,用于浏览器的桌面 ...
- ZH奶酪:基于ionic.io平台的ionic消息推送功能实现
Hybrid App越来越火,Ionic的框架也逐渐被更多的人熟知. 在mobile app中,消息推送是很必要的一个功能. 国内很多ionic应用的推送都是用的极光推送,最近研究了一下Ionic自己 ...
- 基于socket.io的实时消息推送
用户访问Web站点的过程是基于HTTP协议的,而HTTP协议的工作模式是:请求-响应,客户端发出访问请求,服务器端以资源数据响应请求. 也就是说,服务器端始终是被动的,即使服务器端的资源数据发生变化, ...
- HMS Core地理围栏能力助你实现指定范围人群的精准消息推送
精准推送是移动端产品留存阶段的主要运营手段,精准推送常常会与用户画像紧密结合,针对用户的喜好.画像,采用不同策略,但基于用户所属区域推送消息却很难实现.目前市面上大多数第三方消息推送服务商,在系统未深 ...
- socket.io简单入门(一.实现简单的图表推送)
引子:随着nodejs蓬勃发展,虽然主要业务系统因为架构健壮性不会选择nodejs座位应用服务器.但是大量的内部系统却可以使用nodejs试水,大量的前端开发人员转入全堆开发也是一个因素. 研究本例主 ...
- node.js中使用socket.io + express进行实时消息推送
socket.io是一个websocket库,包含客户端的js和服务端的node.js,可以在不同浏览器和移动设备上构建实时应用. 一.安装 socket.io npm install socket. ...
- RabbitMQ消息队列(七)-通过fanout模式将消息推送到多个Queue中(.Net Core版)
前面第六章我们使用的是direct直连模式来进行消息投递和分发.本章将介绍如何使用fanout模式将消息推送到多个队列. 有时我们会遇到这样的情况,多个功能模块都希望得到完整的消息数据.例如一个log ...
- DingTalk钉钉消息推送(.net core 3 WebApi尝鲜记)
我发了个朋友圈,Swagger真他妈的牛B,解放了开发API的码农,麻麻再也不用担心我们写API文档耽误回家吃饭了. /// <summary> /// 发送钉钉消息 /// </s ...
- .NET Core 企业微信消息推送
接口定义 应用支持推送文本.图片.视频.文件.图文等类型.请求方式:POST(HTTPS)请求地址: https://qyapi.weixin.qq.com/cgi-bin/message/send? ...
随机推荐
- JIRA
https://www.jianshu.com/p/8c14b52ce692 JIRA这个工具接触有好几年了,在多个海外项目上都用过这个工具.去年又在项目上深度使用后就有点爱不释手了,回国后也在找机会 ...
- entOS7查看开放端口命令
CentOS7的开放关闭查看端口都是用防火墙来控制的,具体命令如下: 查看已经开放的端口: firewall-cmd --list-ports 开启端口 firewall-cmd --zone=/tc ...
- Java工作原理:JVM,内存回收及其他
JAVA虚拟机系列文章 http://developer.51cto.com/art/201001/176550.htm Java语言引入了Java虚拟机,具有跨平台运行的功能,能够很好地适应各种We ...
- 面试题5-[剑指offer] 二维数组中的查找
题目 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. ...
- csv 数据
csv数据:逗号分隔值,其文件以纯文本的形式存储表格数据(数据和文本).csv模块是python的内置模块,需要引用后再使用 csv.reader(csv_file) #使用with结构 with o ...
- Java后期拓展(一)之Redis
1.NoSQL数据库简介 2.Redis的介绍及安装启动 3.Redis的五大数据类型 4.Redis的相关配置 5.Redis的Java客户端Jedis 6.Redis的事务 7.Redis的持久化 ...
- unix的发展
转载http://blog.51cto.com/1193432/1671058
- ubuntu tensorflow install(Ubuntu16.04+CUDA9.0+cuDNN7.5+Python3.6+TensorFlow1.5)
在网上找了很多案例,踩了许多坑,感觉比较全面的是下面介绍的 http://www.cnblogs.com/xuliangxing/p/7575586.html 先说说我的步骤: 首先安装了Anacod ...
- Three.js学习笔记04--纹理
1 纹理由图片组成 3D世界的纹理由图片组成. 将纹理以一定的规则映射到几何体上,一般是三角形上,那么这个几何体就有纹理皮肤了. 首先应该有一个纹理类,其次是有一个加载图片的方法,将这张图片和这个纹 ...
- 分享13道上海尚学堂拿回来的Java面试真题,这些都是Java核心常见问题,想拿OFFER必看!
上海尚学堂Java培训学员参加面试带回来的真题,分享出来与大家,希望大家能认真地看看做一遍.后面有详细题解答案,对照下,看看自己做得怎么样,把这些面试遇到的真题全部掌握,做好面试笔试前的准备. 一.1 ...