最近在和小伙伴们做充电与通信程序的架构迁移。迁移前的架构是,通信程序负责接收来自充电集控设备的数据实时数据,通过Thrift调用后端的充电服务,充电服务收到响应后放到进程的Queue中,然后在管理线程的调度下,启动多线程进程数据处理。

随着业务规模的不断扩大和对系统可用性的逐步提高。现在这个架构存在很多的问题,比如:

1.充电服务重启,可能会丢数据。

2.充电服务重启会波及影响通信服务。

3.充电服务与通信服务面对的需求和变化是不一样,强依赖的架构带来很多的问题。

为了解决上述的这些问题,项目组决定借助Kafka对程序进行改造 。总体思路是,通信服务收到数据后,把数据存储到kafka,然后通过一个异步任务处理框架实时消费Kafka数据,并调用业务插件处理。

通过上面思路我们可以看到,系统整体架构仅是引入了一个MQ中间件,业务逻辑并没有发生本质的变化。但是在实际的压测中,却发现新架构下的程序性能比原来要慢很多。顺便说一下,压测场景是模拟10万充电终端离网上下线,短时间内会生成大约32万的消息量,遥信:10万,遥测:10万,电量10万,其他:2万。

通过ANTS分析相关进程,发现MonitorDataUploader.AddToLocalCache方法占用了78%左右的CPU。此方法不是业务方法,是为了监控程序的运行情况而加入的埋点监控。通过进一步分析看,在30多万消息量下,会产生约1000万甚至更高的监控消息。在如此高的并发下,这部分程序存在很严重的性能问题,导致系统的资源占用很高,系统运行变慢。

OK。既然问题已经清楚,那就开始优化吧。虽然可以把监控埋点屏蔽,临时解决程序的性能问题。但是,这对一个互联网应用来说是要不得的。没有监控,系统的运行健康状况就一无所知,这对一个SLA要求99.95%的系统来说,是不现实的。所以,必须全力优化监控程序在上报海量监控日志上的性能问题。

为了便于验证问题,写了一个模拟程序.通过模拟程序,很容易的再现了CPU占用很高的情况。

代码实现中,监控消息的存储是通过BlockingCollection存储的,并且设置了Collection大小为1000万。

var cache = new BlockingCollection<MonitorData>(boundedCapacity);

通过阅读BlockingCollection 的说明,可以看到空构造函数可以不设置Collection的上限。看到这个解释,怀疑是限制了上线的Collection存在性能问题。与是把代码中对BlockingCollection 的构造改成空构造,再次测试。测试结果大出意料,性能表现有了非常好的提升。

为了进一步验证问题,把对BlockingCollection 的构造改了限制大小,并设置上线为1个亿。测试时消息总量为5000万,验证一下是否是BlockingCollection 达到上限后,引起的严重性能问题。通过测试数据看,CPU消耗与不限制时基本一致。通过此可以确定,BlockingCollection 在设置了容量上限后,如果消息超过容量,性能将会非常差。

通过上面的调优,在发送5000万监控消息的情况下,程序的CPU在60% 左右持续30s左右。虽然性能有所改善,但是还不是很尽如人意。 有没有更好的解决方案呢?通过不算的思考和尝试,终于找到了一个更好的解决方案:基于双缓存+线程级多桶式Collection。此种模式下性能表现如下,CPU平均在30%左右,持续时间在15s左右。性能又有近一倍的提升。具体实现方案下次再分享。

记一次高并发场景下.net监控程序数据上报的性能调优的更多相关文章

  1. Qunar机票技术部就有一个全年很关键的一个指标:搜索缓存命中率,当时已经做到了>99.7%。再往后,每提高0.1%,优化难度成指数级增长了。哪怕是千分之一,也直接影响用户体验,影响每天上万张机票的销售额。 在高并发场景下,提供了保证线程安全的对象、方法。比如经典的ConcurrentHashMap,它比起HashMap,有更小粒度的锁,并发读写性能更好。线程安全的StringBuilder取代S

    Qunar机票技术部就有一个全年很关键的一个指标:搜索缓存命中率,当时已经做到了>99.7%.再往后,每提高0.1%,优化难度成指数级增长了.哪怕是千分之一,也直接影响用户体验,影响每天上万张机 ...

  2. 【转】记录PHP、MySQL在高并发场景下产生的一次事故

    看了一篇网友日志,感觉工作中值得借鉴,原文如下: 事故描述 在一次项目中,上线了一新功能之后,陆陆续续的有客服向我们反应,有用户的个别道具数量高达42亿,但是当时一直没有到证据表示这是,确实存在,并且 ...

  3. 高并发场景下System.currentTimeMillis()的性能问题的优化 以及SnowFlakeIdWorker高性能ID生成器

    package xxx; import java.sql.Timestamp; import java.util.concurrent.*; import java.util.concurrent.a ...

  4. HttpClient在高并发场景下的优化实战

    在项目中使用HttpClient可能是很普遍,尤其在当下微服务大火形势下,如果服务之间是http调用就少不了跟http客户端找交道.由于项目用户规模不同以及应用场景不同,很多时候可能不需要特别处理也. ...

  5. 高并发场景下System.currentTimeMillis()的性能问题的优化

    高并发场景下System.currentTimeMillis()的性能问题的优化 package cn.ucaner.alpaca.common.util.key; import java.sql.T ...

  6. C++高并发场景下读多写少的解决方案

    C++高并发场景下读多写少的解决方案 概述 一谈到高并发的解决方案,往往能想到模块水平拆分.数据库读写分离.分库分表,加缓存.加mq等,这些都是从系统架构上解决.单模块作为系统的组成单元,其性能好坏也 ...

  7. C++高并发场景下读多写少的优化方案

    概述 一谈到高并发的优化方案,往往能想到模块水平拆分.数据库读写分离.分库分表,加缓存.加mq等,这些都是从系统架构上解决.单模块作为系统的组成单元,其性能好坏也能很大的影响整体性能,本文从单模块下读 ...

  8. MySQL在大数据、高并发场景下的SQL语句优化和"最佳实践"

    本文主要针对中小型应用或网站,重点探讨日常程序开发中SQL语句的优化问题,所谓“大数据”.“高并发”仅针对中小型应用而言,专业的数据库运维大神请无视.以下实践为个人在实际开发工作中,针对相对“大数据” ...

  9. 高并发场景下System.currentTimeMillis()的性能优化

    一.前言 System.currentTimeMillis()的调用比new一个普通对象要耗时的多(具体耗时高出多少我也不知道,不过听说在100倍左右),然而该方法又是一个常用方法, 有时不得不使用, ...

随机推荐

  1. git使用教程之git分支

    1 分支简介 让我们来看一个简单的分支新建与分支合并的例子,实际工作中你可能会用到类似的工作流. 你将经历如下步骤: 开发某个网站. 为实现某个新的需求,创建一个分支. 在这个分支上开展工作. 正在此 ...

  2. SSH三大框架整合步骤

    Struts2:需要整合的第一个框架: 1.创建一个动态web项目 2.导入struts2必须的jar 放到 lib目录下 ,再 build path 添加web工程中 3.配置struts2的核心配 ...

  3. win10提示管理员已阻止你运行此应用,如何强制运行

      方法/步骤     这里以自己遇到的一个软件为例,下图就是禁止的图画:   在开始菜单中输入"cmd",然后以管理员身份运行:   按住"shift"键,同 ...

  4. HTML中动态生成内容的事件绑定问题【转载】

    转自 http://www.hitoy.org/event-binding-problem-of-dynamically-generated-content.html 由于实际的需要,有时需要往网页中 ...

  5. 原生addClass 方法 添加类函数

    function addClass(id,new_class){       var i,n=0;       new_class=new_class.split(",");   ...

  6. 通用的contain函数

    用来检测节点所属关系:document.documentElement.contains(document.body) function contains(refNode, otherNode) {i ...

  7. Easy UI下拉列表默认选中(多行)与为文本框赋值

    1.为单行文本框赋值 var data2 = $('#LoadArea').combobox("getData"); if (data2) { $('#id).combobox(' ...

  8. 有关ActiveXObject的兼容性问题(浏览器的特有属性)

    这个问题还得从一开始时候学习有关javascript中有关对文件的一些操作. 对于每个前端的人应该都清楚有关File对象,其中包括多种方法,就不一一描述了,比如说她是通过FileSystemObjec ...

  9. get和post与服务端的交互方式

    在网上看了不少关于get和post的文章,看到博主这个,现在手录下来. 原博客地址:http://www.cnblogs.com/warrior4236/p/5675756.html 一:B/S结构, ...

  10. insert时报Cannot add or update a child row: a foreign key constraint fails (`yanchangzichan`.`productstatusrecord`, CONSTRAINT `p_cu` FOREIGN KEY (`cid`) REFERENCES `customer` (`cid`))错误

    mybatis在insert时报Cannot add or update a child row: a foreign key constraint fails (`yanchangzichan`.` ...