NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

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:261424

评论

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

web技术分享| 图片上传与图片裁剪结合 vue3

anyRTC开发者

Vue 前端 Web 图片上传 图片裁剪

AI技术实践|用腾讯云录音文件识别让无字幕视频自动生成字幕

牵着蜗牛去散步

人工智能 腾讯云 腾讯 语音识别

与Web3支付赛道主要项目相比,Zebec生态潜力相当大

EOSdreamer111

架构实战营模块一作业

😊😊😊

作业一

专业开发人员需要低代码开发平台吗

力软低代码开发平台

大数据培训学习需要注重哪些知识呢

小谷哥

前端leetcde算法面试套路之堆

js2030code

JavaScript LeetCode

秒云成功入选《2022爱分析 · 信创厂商全景报告》

MIAOYUN

信创 信创云 金融信创 信创产业

华为云发布CodeArts Req需求管理工具 让需求管理化繁为简

Geek_2d6073

【PCB技能】脑瓜疼的PCB反复评审难题,解决方法在这!

华秋PCB

工具 PCB PCB设计

深圳前端培训学习编程的就业方向有哪些?

小谷哥

大数据培训学习后程序员就业前景如何

小谷哥

北京前端培训程序员学习方法有哪些

小谷哥

数读甘肃数字经济 | 2022年甘肃14市州数字经济发展活跃度指数发布

易观分析

数字经济 甘肃

看场景、重实操,实时数仓不是“纸上谈兵”

阿里云大数据AI技术

大数据 实时数仓 12 月 PK 榜

前端leetcde算法面试套路之树

js2030code

JavaScript LeetCode

各开发语言DNS缓存配置建议

京东科技开发者

#DNS

文盘Rust -- r2d2 实现redis连接池

京东科技开发者

redis 后端 封装 连接池 rust语言

java架构师培训学习需要多久?

小谷哥

【中国信通院|低代码·无代码应用沙龙】低代码平台在云智慧的实践探索

云智慧AIOps社区

大前端 低代码 数据可视化 无代码 可视化大屏

如何通过C#合并Word文档

在下毛毛雨

C# .net word文档 文件合并

架构训练营模块一作业

Dinfan

架构实战营

前端精准测试实践

京东科技开发者

前端 测试 精准测试 webhook 精准分析

迁移回归问题新突破,火山语音团队论文被人工智能顶级期刊IEEE TPAMI接收

科技热闻

PostgreSQL 技术内幕(三)聚集算子

酷克数据HashData

postgresql

2022阿里云研发效能峰会,来啦!

阿里云云效

DevOps 研发效能 开发 数字化转型

用javascript分类刷leetcode3.动态规划(图文视频讲解)

js2030code

JavaScript LeetCode

与Web3支付赛道主要项目相比,Zebec生态潜力相当大

股市老人

Redis数据持久化机制(备份恢复)、缓存淘汰策略、主从同步原理、常见规范与优化详解

C++后台开发

数据库 redis 中间件 后端开发 C++开发

事务相关知识集锦

京东科技开发者

MySQL 数据库 spring mybatis 事务

架构训练营模块1作业

gigifrog

架构训练营

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