开发记录

监控server重构记录

2019-04-03  本文已影响0人  叮咣铛

监控server总出问题,卡死或CPU超级高,代码翻了几遍后,遗留问题如下:

遗留项目的问题和优化方向:

1,Tcp server 原始的bind accept ,然后每连接新建Thread方式,改为Netty
2,传统jar导入方式,需要改成Maven依赖
3,DB Connection 和Statement竟然只建立一个然后全局共享....
4,DB connection pool替换为HikariCP(结合上一点,原本pool没起作用)
5,内部类线程逻辑抽取出来单独类(超长的方法和类难以维护)
6,定时任务从Thread.sleep方式改为ScheduledExecutorService,结果他吞异常,又换成Timer
7,删除没用还在定时跑的线程,db cache

生产消费场景 共享数据用的Collections.synchronizedList ,变成单线程了 ,终端3k多上传(有错时上传,并发不到那么多)
改为ConcurrentLinkedQueue,
(经典的生产消费模型,用Queue啊)

动手依据:

按照《java-concurrencyInPractice》说法

Chapter 6

Task Execution

Explicitly creating threads for tasks

thread-per-task

优点:

1,把和client socket交流操作从主线程中分离出来

主线程可以及时的响应下一个连接

2,多个连接请求可以并行,提高效率,特别是多处理器情况

3,线程安全更易于达成

这种方式提高了吞吐Throughout 和响应responsiveness

缺点:

1, 线程的创建销毁 not free

2, 资源消耗 ,尤其是内存 线程数量多于处理器时,会有空闲Thread

3,可以创建多少Thread 有限制,超出这个限制就来OOM了

《Netty In Action》

imageNetty.png

创建大量线程 ,根据OS不同,每个线程占用的内存from 64 KB to 1 MB

context-switching 带来的消耗在连接数到达10000时可能会凸显

并发连接较少时可能还无法感知

但当连接来到

100,000 时候呢?

NIO是一种选择,但开发太繁琐

imageN2.png

Netty

异步 ,事件驱动

imageN3.png

重构后整体结构:

image4.png

重构过程:

先大致浏览了一下Netty In Action

大致了解各个基本组件都是干啥的,还是有点混乱

脑海里的java socket 知识停留在

ServerSocket bind port

accept

new Thread(client socket) IO Stream

之前也做过NIO的socket,年头稍久远忘没了,只记得当时公司里到处请教如何只用单线程来做NIO消息收发

来到Netty面前 ,这都是啥和啥?

1.  Pipeline 里到底是怎么个方向?
2.  哪头是外面进来,消息出去都经过谁啊?
3.  向pipeline里add Handler后,消息处理什么顺序啊?
4.  EchoServer为啥我telnet 发消息后就给我关闭了,没看到close啊?
5.  怎么拿client socket的ip啊?

然后就是反复折腾EchoServer

听说Dubbo是基于Netty,去翻源码,发现telnet管理入口的源码,学习一番

google到Socket.io的一个基于Netty的实现,翻一翻

又发现了Netty一个 Best Practices 宝藏:

http://normanmaurer.me/presentations/2014-facebook-eng-netty/slides.html#1.0

image5.png

有的当时用不到,先留个印象

后面write

然后complete时候flush用到了

还有就是Netty 的官方wiki,居然发现最新的几条更新参考文章指向简书,棒👍

接下来着手对公司的Monitor Server进行重构,同时反复测试Netty

最终目标是socket server方式整体替换成Netty NIO方式

重构后JMeter load test一下还不错

总结一下:

1, 中间生成的sql存入static的 ConcurrentLinkedQueue ,对他的引用方式用class和用单例instance方式组合 ,竟然用Eclipse MAT发现了leak,全部改为class static 静态引用后消失了,这个还没搞懂为啥

2,JVM参数配置 抓了gc log 方便查看Young GC FGC发生的次数,间隔

imag6e.png

部署后,隔一段时间就上去

jstat -gc pid 看下gc

3,期间还有一次leak 是 让main函数所在的类实现了一个自定义一个listener,结果造成了leak

4,测试环境是直联DB,生产环境是Mycat,写库batch遇到写不进去问题

另外记录

参考:

Netty best practise

http://normanmaurer.me/presentations/2014-facebook-eng-netty/slides.html#1.0

《Netty in Action》翻了几遍只能入门感觉

Java Queue

https://www.logicbig.com/tutorials/core-java-tutorial/java-collections/concurrent-collection-cheatsheet.html

关于GC

https://blog.overops.com/garbage-collectors-serial-vs-parallel-vs-cms-vs-the-g1-and-whats-new-in-java-8/?utm_source=blog&utm_medium=in-post&utm_content=gcmisconceptions&utm_campaign=java

JVM Memory Management

https://lihaimei.wordpress.com/2015/09/24/jvm-memory-management/

java memory leaks:

https://www.baeldung.com/java-memory-leaks

http://java.jiderhamn.se/2011/12/11/classloader-leaks-i-how-to-find-classloader-leaks-with-eclipse-memory-analyser-mat/

上一篇下一篇

猜你喜欢

热点阅读