最近在和小伙伴们做充电与通信程序的架构迁移。迁移前的架构是,通信程序负责接收来自充电集控设备的数据实时数据,通过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左右。性能又有近一倍的提升。具体实现方案下次再分享。

最新文章

  1. 【NodeJs环境下bower】如何更改bower_components文件夹的位置
  2. Repeater的分页
  3. 使用JSP开发动态网站基础
  4. 序列化 Serializable
  5. Google 面试题和详解
  6. C#创建微信自定义菜单
  7. Javascript 访问网页弹出qq
  8. CCASS四种交收指令
  9. C++的常量折叠(二)
  10. BNUOJ 6038 - Reaux! Sham! Beaux!(模拟)
  11. Interactive pivot tables with R(转)
  12. 【打CF,学算法——三星级】Codeforces Round #313 (Div. 2) C. Gerald&amp;#39;s Hexagon
  13. Redis主从集群的Sentinel配置
  14. “蝉原则”与CSS3随机多背景随机圆角等效果
  15. android开发(3):列表listview的实现 | 下拉刷新
  16. Fragment onActivityResult提前响应,startActivityForResult执行后立即响应onActivityResult的解决方法
  17. 2:if 语句
  18. 了解linux的进程:rootfs与linuxrc
  19. npm出错的解决方案
  20. Gitlab不小心关闭了sign-in,无法登录web的坑。。。

热门文章

  1. Python学习第一周
  2. vConsole--针对手机网页的前端 console 调试面板。
  3. ⑥bootstrap表单使用基础案例
  4. 转:ef获取某个表中的部分字段值
  5. Java8一:Lambda表达式教程
  6. Golang源码探索(三) GC的实现原理
  7. jmockit学习总结
  8. JavaScript学习笔记(八)——变量的作用域与解构赋值
  9. windows下忘记mysql的root密码解决方法(图文)
  10. open_basedir restriction in effect.文件访问没有权限异常