高性能硬件上的程序部署策略

    一个15万PV/天左右的在线文档类型网站最近更换了硬件系统,新的硬件为4个CPU、16GB 物理内存,操作系统为64位CentOS 7.4, Resin 作为Web服务器。整个服务器暂时没有部署别的应用,所有硬件资源都可以提供给这访问量并不算太大的网站使用。管理员为了尽量利用硬件资源选用了64位的JDK 1.5,并通过-Xmx和-Xms参数将Java堆固定在12GB。使用–段时间后发现使用效果并不理想,网站经常不定期出现长时间失去响应的情况。
    监控服务器运行状况后发现网站失去响应是由GC停顿导致的,虚拟机运行在Server模式,默认使用吞吐量优先收集器,回收12GB的堆,一次Full GC的停顿时间高达14秒。并
且由于程序设计的关系,访问文档时要把文档从磁盘提取到内存中,导致内存中出现很多由文档序列化产生的大对象,这些大对象很多都进入了老年代,没有在Minor GC中清理掉。这种情况下即使有12GB的堆,内存也很快被消耗殆尽,由此导致每隔十几分钟出现十几秒的停顿,令网站开发人员和管理员感到很沮丧。
    这里先不延伸讨论程序代码问题,程序部署上的主要问题显然是过大的堆内存进行回收时带来的长时间的停顿。硬件升级前使用32位系统1.5GB的堆,用户只感觉到使用网站比较缓慢,但不会发生十分明显的停顿,因此才考虑升级硬件以提升程序效能,如果重新缩小给Java堆分配的内存,那么硬件上的投资就显得很浪费。
    在高性能硬件上部署程序,目前主要有两种方式:
        口通过64位JDK来使用大内存。.
        口使用若千个32位虚拟机建立逻辑集群来利用硬件资源。
    管理员采用了第一种部署方式。对于用户交互性强、对停顿时间敏感的系统,可以给Java虚拟机分配超大堆的前提是有把握把应用程序的FullGC频率控制得足够低,至少要低到不会影响用户使用,譬如十几个小时乃至- -天才出现- -次Full GC,这样可以通过在深夜执行定时任务的方式触发Full GC甚至自动重启应用服务器来保持内存可用空间在一个稳定的水平。
    控制Full GC频率的关键是看应用中绝大多数对象能否符合“朝生夕灭”的原则,即大多数对象的生存时间不应太长,尤其是不能有成批量的、长生存时间的大对象产生,这样才能保障老年代空间的稳定。
    在大多数网站形式的应用里,主要对象的生存周期都应该是请求级或者页面级的,会话级和全局级的长生命对象相对很少。只要代码写得合理,应当都能实现在超大堆中正常使用而没有Full GC,这样的话,使用超大堆内存时,网站响应速度才会比较有保证。除此之外,
如果计划使用64位JDK来管理大内存,还需要考虑下面可能面临的问题:
         口内存回收导致的长时间停顿。
         口现阶段,64位JDK的性能测试结果普遍低于32位JDK。
         口需要保证程序足够稳定,因为这种应用要是产生堆溢出几乎就无法产生堆转储快照
(因为要产生十几GB乃至更大的Dump文件),哪怕产生了快照也几乎无法进行分析。口相同程序在64位JDK消耗的内存一般比32位JDK大,这是由于指针膨胀,以及数据类型对齐补白等因素导致的。
    上面的问题听起来有点吓人,所以现阶段不少管理员还是选择第三种方式,使用若千个:32位虚拟机建立逻辑集群来利用硬件资源。具体做法是在一台物理机器上启动多个应用服务器进程,每个服务器进程分配不同端口,然后在前端搭建一个负载均衡器,以反向代理的方式来分配访问请求。读者不需要太过在意均衡器转发所消耗的性能,即使使用64位JDK,许多应用也不正有一台服务器,因此在许多应用中前端的均衡器总是要存在的。
     考虑到在一台物理机器上建立逻辑集群的目的仅仅是为了尽可能利用硬件资源,并不需_要关心状态保留、热转移之类的高可用性需求,也不需要保证每个虚拟机进程有绝对准确的均衡负载,“因此使用无Session复制的亲合式集群是一个相当不错的选择。我们仅仅需要保一障集群具备亲合性,也就是均衡器按一定的规则算法(一般根据SessionID分配》将一个固.定的用户请求永远分配到固定的一个集群节点进行处理即可,这样程序开发阶段就基本不用为集群环境做什么特别的考虑了。
    当然,很少有没有缺点的方案,如果读者计划使用逻辑集群的方式来部署程序,:
可能会遇到下面一些问题:
         口尽量避免节点竞争全局的资源,最典型的就是磁盘竞争,各个节点如果同时访问某个上磁盘文件的话-(尤其是并发写操作容易出现问题),很容易导致1O异常。
         口很难最高效率地利用某些资源池,:譬如连接池,一般都是在各个节点建立自己独立的连接池,这样有可能导致一些节点池满了而另外一些节点仍有较多空余。尽管可以使用集中式的JNDI,但这个有一定复杂性并且可能带来额外的性能开销。
         口各个节点仍然不可避免地受到32位的内存限制,在32位Windows平台中每个进程只能使用2GB的内存,考虑到堆以外的内存开销。堆-般最多只能开到1.5GB。在某些Einux或UNIX系统:(如Solaris)中,可以提升到3GB乃至接近4GB的内存,=但32位中仍然受最高4GB (22)内存的限制。
         口大量使用本地缓存:(如大量使用HashMap作为K/V缓存)-的应用; :在逻辑集群中会二天
造成较大的内存浪费,因为每个逻辑节点1都有二份缓存,这时候可以考虑把本地缓存改为集中式缓存一.
    介绍完这两种部署方式,再重新回到这个系统之中,最后的部署方案调整为建立5个.一32位JDK的逻辑集群,每个进程按2GB内存计算:(其中堆固定为1.5GB),占用了10GB内存。另外建立一个Apache服务作为前端均衡代理访问门户。考虑到用户对响应速度比较关心,并且文档服务的主要压力集中在磁盘和内存访问,CPU资源敏感度较低,因此改为CMS收集器进行垃圾回收。部署方式调整后,服务再没有出现长时间停顿,速度比硬件升级前有较大提升。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值