10 月 23 - 25 日,QCon 上海站即将召开,现在购票,享9折优惠 了解详情
写点什么

Java 云托管服务的开支削减策略

  • 2017-09-19
  • 本文字数:3784 字

    阅读完需:约 12 分钟

摘要

  • 随着项目不断扩大,你需要将其迁移到更大的虚拟机上。但如果新虚拟机环境超出了你的需求则会产生额外开支。
  • 相比虚拟机,容器具有更小的粒度,并且无需重启运行中的实例即可垂直扩展。
  • 单体应用和历史遗留应用无需更改配置,即可从虚拟机迁移至容器中。
  • Java 的垂直扩展需要适当配置 JVM 和清理垃圾回收器。
  • “即用即付”和“按需付费”这两种云收费模型的对比,及提高效率的正确选择。

云服务会很昂贵,而当你为不需要的资源付费时尤其如此;另一方面,资源不足又会导致宕机。身为程序员该如何应对?这篇文章将会讨论一些技术,来帮助你恰到好处地只支付实际消耗的资源,且不受应用体量增长的限制。

认清现实:你在虚拟机上多花钱了

任何解决方案的第一步当然都是要承认问题的存在。以下详述大部分云用户都在面对的问题:

几乎所有的云服务供应商都提供一系列不同体量的虚拟机供选择。而如何选择合适的体量往往让人左右为难:选小了会有性能问题,负载上去搞不好还会挂。选多了?那常规负载和空闲时的资源就都浪费了。你自己的云托管应用是不是经历过类似的情形?

当项目开始横向扩展,资源使用低效的问题会重复出现在每个新加入的实例上。所以,这个问题也会相应地增长。

进一步说,如果你想在同一个虚拟机中增加一点点服务,目前大部分云服务供应商能提供的唯一方案是更换双倍体量的虚拟机。参考AWS 的方案:

更糟糕的是,迁移过程会导致服务中断:需要停掉现在的虚拟机,一步步重新部署或迁移应用,其中不可避免会有相关的棘手问题需要解决。

可见虚拟机在资源使用方面不够灵活高效,并且针对动态负载的调整能力很有限。这种缺乏弹性的方式导致了额外的开支。

如何高效地进行双向扩展

如果横向扩展无助于资源的高效利用,我们就需要深入虚拟机内部,理解垂直扩展是如何实现的。

垂直扩展可以在现有基础上优化任何应用实例的内存和CPU 使用。如果配置得当,这种方法对单体应用和微服务都同样有效。

在虚拟机内通过动态增加或减少资源来进行垂直扩展同时又不中断服务是一项艰巨的任务。虚拟机提供了内存膨胀(memory balloning)的技术,但它并不是自动化的,需要用工具监控宿主系统和客户系统中的内存压力,然后进行相应的向上或向下扩展。而实际情况是这个方法并不太好用,自动化的内存共享才更实用。

得益于开创性的同宿主内容器间资源自动分享,基于 cgroups 的容器技术拥有更高级别的灵活性。在设定范围内,空闲的资源会自动分配给相同硬件节点内的其他容器。

不同于虚拟机,容器内的资源无需重启应用实例即可轻松实现扩展。

结果就是,同一容器实时更改体量大小要比迁移至更大的虚拟机更加容易、经济和迅速。

从虚拟机迁移至容器

容器分为两种:应用容器和系统容器。应用容器(如Docker 或rkt)一般运行在单个进程中,而系统容器(LXD、OpenVZ)则更像是完整的操作系统,可以运行全功能的初始化系统如systemd、SysVinit 和openrc,这些初始化系统允许在单一容器中的进程孵化出其他进程如openssh、crond 或syslogd 等。这两种容器都支持垂直扩展来让资源分配更有效率。

理想情况下,在一个新项目中你可能想基于应用容器开始从头设计,因为应用容器可以使用Docker 公开的模板较为容易地创建所需镜像。但关于容器的一个普遍存在的认知误区就是容器只适用于全新的应用(微服务和原生云)。已有的经验和用例可以证实,将已有的工作从虚拟机迁移至容器,而不重写或重新设计应用也是完全可能的。

对于单体应用和遗留应用来说,使用系统容器会更合适,因为你可以重用之前为虚拟机设计的架构和配置等:使用标准网络配置,如组播;在容器内运行多个进程,避免因不恰当的内存限制决策导致的问题;确保在容器重启过程写入本地文件系统是安全的;依照现有的方法排查问题和分析日志;使用大量基于SSH 的配置工具;对其他老旧但重要的任务有较好兼容性。

为了从虚拟机中迁移出来,单体应用的拓扑结构需要拆解成更小的逻辑块,分布于互联的容器内。下图简单示意了拆解过程:

每个应用组件被置于隔离的容器内。通常这样可以简化应用的拓扑结构,因为项目中的某些部分可能在新架构中不是必需的。

例如,Jave EE WebLogic Server 在虚拟机环境中运行大致需要包含三种实例:管理服务器、节点管理(进程)和被管理服务器。拆解之后,我们可以去掉节点管理,因为它是作为虚拟机代理来添加或删除被管理服务器实例的。而现在,利用容器的编排(orchestration)平台以及一系列 WLST(WebLogic Server Scriting Tool)脚本,容器可以自动添加被管理服务器实例并将其直连到管理服务器上。

为继续迁移,你需要准备所需的容器镜像。对系统容器来说,这个过程比应用容器要复杂一点。你可以自己编译生成,或者使用像 Jelastic 之类的包含系统容器预设模板的编排工具来完成。

最后,部署项目并配置所需的互联接。

现在每个容器都可以动态向上向下扩展而无需停机。相比于虚拟机,容器更加轻量,所以扩展花费的时间比起虚拟机也要少得多。因为容器很容易从头再分配或克隆,所以横向扩展同样变得很顺畅。

启用带有内存收缩机制的垃圾回收器

对y 于Java 的垂直扩展来说,只用容器是不够的;JVM 同样需要合理配置。尤其值得注意的是,你所选择的垃圾收集器需要在运行时提供内存收缩机制。

这种垃圾收回收会将所有存活对象打包,去除垃圾对象,撤回(uncommit)和释放空闲内存。相较而言,如果是不支持内存紧缩的垃圾收集器或未经优化配置的JVM,Java 应用会占用所有提交的内存,不能实现按应用负载变化的垂直扩展。很不幸,JDK 8 的默认并行垃圾收集器(-XX:+UseParallelGC)就不支持内存收缩,且没能解决JVM 低效使用内存的问题。幸运的是,将垃圾收集器更换为 Garbage-First (-XX:+UseG1GC)可以很容易地解决这个问题。

请看下面的例子:即使你的应用内存占用很低(图中蓝色部分),未使用的资源还是不能分配给其他进程或其他容器,因为它们全部分给了 JVM(桔红色部分)。

(点击看大图)

好消息是,JDK 9 会默认启用支持内存收缩的G1 垃圾回收器。主要的好处之一就是可以减少空闲内存碎片,同时缩短垃圾回收的停顿时间,且无需撤回未使用的堆内存。

如果你的JDK 版本低于9,可以使用以下参数启用G1 垃圾收集器:

-XX:+UseG1GC

后面这两个参数用来配置内存资源的垂直扩展:

  • Xms——设置扩展的步长

  • Xmx——设置扩展的上限

并且,在低负载或空闲期,应用应该定期调用 Full GC,如 System.gc()。此过程可在应用逻辑内部实现,或借助外部工具 Jelastic 垃圾回收代理实现。

在下图中,我们展示了启用以下JVM 启动参数后300 秒内的内存使用情况:

-XX:+UseG1GC -Xmx2g -Xms32m

(点击看大图)

如图所示,资源使用方面对比之前的例子有了巨大的提升。保留内存部分(桔红色)随着真实使用的部分(蓝色)缓慢增长,且空闲期内的资源没有浪费,所有最大堆内未使用的资源都可以被同一宿主内的其他容器或进程利用。

由此可证,容器技术和G1 垃圾回收器的结合为Java 云服务提供了最高效的资源利用。

选择按需付费的云服务

最后(但很重要)的一步是选择“按需付费”收费模型的云服务,这样我们的花销就完全基于所消耗的部分。

云计算经常被拿来和电力使用相比较,(电力公司)按需求提供资源,属于“即用即付”。但他们之间有一个主要的区别——当你只多用了一点电时,电费账单并不会翻倍!

大部分云服务供应商采用“即用即付”的收费模型,这意味着可以一开始选一个小一点的服务器,然后随着项目增长再逐步增加服务器。但就像我之前描述的那样,你不可能简单地选择刚好适合你现在需求的服务体量,然后不用额外的人工操作,不用停止服务,就能按你的需求扩展。所以你会一直为这些限制买单——一开始是小机器,然后体量加倍,最后扩展为许多虚拟机,但每个都未被充分使用。

对比而言,得益于容器技术,“按需付费”的收费模型考虑的是当前应用实例的负载,并且实时供应或回收必需的资源。结果就是,你只需支付实际使用的那部分资源,并且不需要复杂的重新配置就可以扩展。

(点击看大图)

但如果你已经受制于某个供应商,虚拟机已经在工作了,你正在为那些限制买单,且没准备好改变它,那是否还有机会缓解状况,提高效率,节省开支?答案是,你可以用一个大一点的虚拟机,在上面安装一个容器引擎,然后把工作负载从那堆小虚拟机上迁移过来。这样你的应用就会运行在虚拟机中的容器内——像夹心蛋糕一样。但这样有助于巩固和精简已占用资源,同时释放和共享未占用资源。

认识到垂直扩展的好处有助于快速排除一系列性能问题,避免盲目横向扩展带来的不必要的复杂性,以及减少云端应用的开销——无论是单体应用还是微服务。

关于作者

Ruslan Synytsky是 Jelastic 的 CEO 和联合创始人。Jelastic 向开发者提供多云平台即服务(multi-cloud Platform-as-a-Service)。他设计了平台的核心技术,可在全世界范围内的数据中心部署和运行上百万个容器。Synytsky 致力于搭建高可用集群方案,为云端遗留应用和微服务应用的自动垂直扩展和水平扩展提供改进和增强方案。他在技术和商业方面都有丰富经验,并热衷参与各种程序员、主机提供商、集成商和企业相关的交流会议。

查看英文原文: Cost Reduction Strategies on Java Cloud Hosting Services


感谢薛命灯对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

2017-09-19 17:262178

评论

发布
暂无评论
发现更多内容

web技术分享| WebRTC控制摄像机平移、倾斜和缩放

anyRTC开发者

前端 音视频 WebRTC 摄像头 web技术分享

海外主机是什么意思?与国内主机有什么区别?

行云管家

服务器 主机 服务器运维 海外 主机运维

这场汇聚行业顶级大咖的Meetup,有哪些不容错过的干货?| IDP Meetup 01

Baihai IDP

人工智能 AI 生态 Meetup

云原生小课堂 | Envoy请求流程源码解析(二):请求解析

York

云原生 istio 网络 envoy Service Mesh (ASM)

31 家企业入选阿里云首期云原生加速器,共建云原生行业新生态

阿里巴巴云原生

阿里云 云原生 云原生加速器 招募 行业生态

黄东旭当选 CCF 数据库专业委员会、开源发展委员会、大数据专家委员会执行委员

PingCAP

程序设计优化之管道数据流

有道技术团队

如何高效完成ECS多环境部署?

阿里云云效

阿里云 云原生 开发 部署与维护 ECS

upload上传文件类型的限制的几种方式(element)

lo

JavaScript

作为前端上传图片的两种方法

小学僧

3月程序媛福利 3月月更

优雅的编码习惯总是让人心情愉悦(Shell篇)

XinXing

Shell Code 优雅 脚本 规范

恒源云(GpuShare)_加速pytorch训练的方法来喽~

恒源云

深度学习 PyTorch

Linux之ss命令

入门小站

Linux

墨天轮国产数据库沙龙 | 胡津铭:时序数据库DolphinDB,从量化金融到万物互联

墨天轮

数据库 时序数据库 DolphinDB 国产数据库

云管理平台有哪些?建议选择哪家?

行云管家

云计算 多云 云管理

Go学习笔记——条件判断if

为自己带盐

Go 学习笔记 3月月更

面试官:对于宏任务和微任务,你知道多少?

是乃德也是Ned

JavaScript 面试 前端 ES6 Promise

AI算力加速之道

安第斯智能云

人工智能 深度学习 异构计算

OpenHarmony开源开发者成长计划 | 知识赋能第四期课程——标准系统HDF开发

Anna

直播 赋能 OpenHarmony

在 Nebula K8s 集群中使用 nebula-spark-connector 和 nebula-algorithm

NebulaGraph

数据库 开源 分布式系统 图数据库

声网崩溃数据的自动化闭环处理

声网

自动化 测试 Dev for Dev

CNI 这么多,怎么选?| 容器网络系列第1期

BoCloud博云

Kubernetes 容器云 cni 容器网络平台

java培训:Redis和Mysql数据怎么保持一致

@零度

MySQL redis JAVA开发

HarmonyOS UI组件在线预览,程序员直呼“不要太方便~”

HarmonyOS开发者

UI HarmonyOS

Promise静态四兄弟,你学会了吗?

战场小包

JavaScript 前端 Promise 3月月更

理解Restful风格

蜜糖的代码注释

RESTful 接口规范 REST API 3月月更

豆瓣9.6分,Scala编程圣经第5版重磅来袭!

博文视点Broadview

一文带你了解动态数组方法实现

xiaoyu

数据结构 算法 数组 java; 动态数组

web前端培训:react基础面试题分享

@零度

前端开发 React

大数据Flink培训:维表Join/双流Join的方法

@零度

flink join 大数据开发

虎符交易所完成2月HOO回购 HOO单月涨幅高达40%

区块链前沿News

Hoo 虎符交易所 平台币

Java云托管服务的开支削减策略_Java_Ruslan Synytsky_InfoQ精选文章