美文网首页开发记录
监控server重构记录

监控server重构记录

作者: 叮咣铛 | 来源:发表于2019-04-03 20:21 被阅读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/

    相关文章

      网友评论

        本文标题:监控server重构记录

        本文链接:https://www.haomeiwen.com/subject/dnrtiqtx.html