• 现代Java应用的性能调优方法及开发要点


    上一篇里,我们谈到了JVM的GC,以及GC的实现思想和方法。这一篇里,将会简单介绍一下现代Java应用在开发中需要注意到的要点和性能调优的一些方式方法。

    现代Java应用,究其基本特点,可以归纳为一个词,就是大。数据量大,用户数大,各种大。用户的要求呢,是各种小。等待时间小,耗费资源小,操作难度小,各种各样小。

    数据量大了,最直接的问题就是,会不断的填满内存的各种heap。从最早的新生代,一直到最后的持久代,很快就满了。在此过程中,各种程度的GC不断发生,一直到最后部分GC也不行了,于是full GC就挂起了所有的线程,于是应用停顿了。当数据量再大,更加大,越来越大的时候。。。GC毕竟不是万能的,内存持有量超过了一定限度以后,彻底崩盘,大家都别玩了。最近不是有个什么网,然后搞活动,结果服务器直接挂了么,即为明证。

    那么GC为什么会导致这么严重的后果,应用挂起乃至崩溃呢?这要从GC的原理上说起。GC的基本思想是,扫描对象的被持有数,如果是没人要的孤儿,那么就回收掉。这里有一个很关键的问题,怎么保证这个被持有数的准确。毕竟程序每分每秒都在运行,持有者的数目也在不断变化,怎么保证不出错呢?

    在CMS及以前的GC中,选择的方法是挂起所有线程,扫描对象。形象化一点,就是GC跑进房间来说,大家都是木头人,我来检查你们。检查完了,大家都不是木头人了,都可以活动了。这里的木头人需要时间,是吧?线程暂停运行了,那么系统就会暂停响应,这个我想不必多解释原因了,是吧。在吞吐量不是很高的系统里,这么搞完全没问题,pause就pause咯,没什么。但是我想问,如果实时性要求高的应用,你隔三差五来个pause,估计老板就让你pause了吧?况且,我们以taobao为例。淘宝的数据量相当大,相信很容易触发GC,不管是部分的还是全部的,如果不做一定程度的处理和优化的话,那么只会有一个后果,就是宕机。因为数据量很大,不断的需要GC,但是GC又需要时间,于是就陷入了GC –>  数据填满 –> GC 这样一个循环里。随着数据越来越多,不能清理的数据也越来越多,最后要么是爆棚了,要么就是因为GC Thread不断挂起其他线程而导致整个app失去响应。

    我想,无论哪个,都不是我们作为一个coder想看到的结果,是吧。

    在提出一些建议之前,我先声明一个论调。不是所有问题,都能得到解决。有的时候,问题是解决不了的。或者说,不能解决也是一种解决,这个问题被放弃,被否决。

    GC导致系统挂起乃至崩溃,主要矛盾就是用户数据量过大,丢不得,但是又不能不丢。最简单的,就是换64位的机器,32和64之间的内存管理能力完全不在一个水平层次上。不过,根据来自淘宝的数据,双11活动中,神棍节当天的最早五分钟,淘宝API调用貌似就超过了十万数量级。全天貌似是超过了十亿数量级。这个数字,直接对应了交易数量。淘宝的交易,简单抽象一下的话,可以认为是拉取数据库数据展示页面,随后调用登录系统API,再与银联接口通讯,最后和物流TBOSS通讯,最终在买家签收后完成付款,结束流程。这里抽象和省略了很多细节,呵呵。

    1G就是十亿,粗略估算,淘宝进行这么多交易的总内存使用量肯定超过10GB。而且这些调用是在同一天内不分前后同时进行的,再加上一些守护进程什么的,淘宝所有服务器的内存使用量应当超过40GB,甚至更多。当然,如果有所误差,还请文初兄等指正,呵呵。。。

    下面,我们来尝试拆解这几十GB的内存。

    首先,用一台64位的机器来试试看?就算内存够,我估计没哪个CPU能顶得住这么搞吧?

    其次,搞类似RAC之类的集群?或者是搞iCloud之类的云端存储?这些都可行,只不过,设计的时候有几个要点。

    1 注意缓存一致性和数据的有效性。多个Server之间的通信,会导致通讯的可靠性随着通信环节的增多而降低。有可能这头还在通讯,请求各种资源,那边已经session.destroy()了。

    2 注意处理能力的限制和系统压力的有效分摊。一台机器,硬件性能放在这里,处理能力也就决定了,tpmC也就基本固定了。不要为这台机器设计超出其处理能力的负载。就我的经验而言,最少空出百分之二十用做冗余和缓冲。也就是说,五台一样的机器放在一起,你只能当成有四台,还有一台是缓冲的,不能动用。这里的处理能力是指内存和磁盘性能,CPU性能,网卡性能等各种相关部分的综合性能中最短板的一个。也就是所谓的短板效应。不能说网卡只有百兆,你计算的时候因为内存磁盘性能好,就说可以处理千兆级别的任务,呵呵。

    3 做好灾备和冗余工作。套用IBM的一个概念,HACMP,高可用性群集多处理。你必须保证哪怕是地震了,你的数据也能安然无恙的存在这个地球上。或者说的宽容一些,可以有少量损失,但是这个损失要越少越好。这个概念在Oracle的圈子里早就提出来了,叫做异地灾备和高可用性。他们会把数据中心放在不同的城市,甚至是不同的国家,目的只有一个,安全。

    4 当你发现超出处理能力和设计能力的时候,要怎么办呢?比如用户忽然一下变多了,比如被僵尸网络搞了,怎么办呢?你可以拒绝服务,比如说,System is now busy.但是切记,你可以拒绝能力之外的数据,但是绝对不能宕机。毕竟服务器忙和服务器宕,是两个完全不同等级的概念。这个呢,说简单点,可以降低服务等级,但是绝对不能没有服务。

    关于现代Java应用的性能调优和开发要点呢,先写到这里。下次想到啥,再写就是,呵呵。想约稿子,想聊聊的,都可以在下面跟帖说明。

    最后,赞一下taobao的放翁和其他高人们。比如我知道的,优昙,在宽,肉爷,震子,七爷,等等等等,以上排名不分先后。。。你们创造了一个又一个的技术奇迹,叹为观止。每天核心API调用过十亿,双十一活动每毫秒超过5笔交易,自己动手改Jetty,手工写日志集群,自己写OS,写DFS,佩服,五体投地。虽然上次去面了,没过。有我的原因,有各种原因,但是,对淘宝的技术文化的敬仰,从未停止。

    最后送上一句所谓的哈佛校训,与大家共勉。

    我荒废的今日,正是昨日殒身之人祈求的明日。

  • 相关阅读:
    BDOC ROUTER
    web dom api中的Selection和Range
    基于第三方vuejs库组件做适配性个性开发
    香草js侦测元素是否离开视窗viewport
    xampp windows10下xdebug调试环境安装及配置
    beyond compare全文件夹比较,仅显示变化的文件
    给定制的vuejs组件添加v-model双向绑定支持
    javascript工厂函数(factory function)vs构造函数(constructor function)
    edrawmax使用技巧备忘
    babel plugin和presets是什么,怎么用?
  • 原文地址:https://www.cnblogs.com/xhr8334/p/2272430.html
Copyright © 2020-2023  润新知