监控server重构记录
监控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.pngNetty
异步 ,事件驱动
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
关于GC
JVM Memory Management
https://lihaimei.wordpress.com/2015/09/24/jvm-memory-management/
java memory leaks: