写点什么

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

评论

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

深度揭秘技术创新:全球首个知识增强千亿大模型是怎样炼成的?

百度大脑

人工智能

zookeeper的数据同步是如何完成的?

卢卡多多

zookeeper 28天写作 12月日更

解决:standard_init_linux.go:219: exec user process caused

liuzhen007

28天写作 12月日更

Linux之ls命令

入门小站

Linux

睁眼、耸肩、觉醒:人形机器人的吊诡与最终幻想

脑极体

架构实战营第 4 期 -- 模块二作业

烈火干柴烛灭田边残月

架构实战营

我们一起,盘点 2021 十大技术领域的全部精彩

InfoQ写作社区官方

大数据 云原生 编程语言 话题讨论 2021年度技术盘点与展望

Volatile 原理(二)

悟空聊架构

volatile 28天写作 可见性 悟空聊架构 12月日更

在线将JS/JavaScript-Object转JSON工具

入门小站

工具

想象与实践的过程

Nydia

工业4.0时代:低代码的兴起,或将掀起制造业格局的变革

优秀

低代码 工业4.0

什么是网络安全?网络安全威胁存在哪些?

喀拉峻

网络安全

Helm 快速入门

xcbeyond

Helm 28天写作 12月日更

记录-最骄傲的事(3)

将军-技术演讲力教练

中小型研发团队的一种考核思路

wood

团队管理 28天写作 研发考核

JavaScript 中8 个最佳电子邮件库

devpoint

JavaScript nodejs 12月日更 email pop3

Spring AOP(二) 修饰者模式和JDK Proxy

程序员历小冰

spring Java、 28天写作 spring aop 12月日更

「如何从0到1实现一个基于vite的前端基础库👾」

速冻鱼

前端 Node 签约计划第二季 12月日更

40 K8S之Calico网络插件

穿过生命散发芬芳

k8s 28天写作 12月日更

Hoo虎符研究院 | 币海寻珠——2021年区块链投融大事记

区块链前沿News

区块链 虎符 Hoo虎符 Hoo 虎符交易所

当诗人遇到熟读2600亿中文参数的大模型

白洞计划

9.《重学 JAVA》-- 控制语句(一)

杨鹏Geek

Java 25 周年 28天写作 12月日更

数据库大赛50强之「华东师范大学」:恰同学少年,代码激扬!

OceanBase 数据库

数据库 学习 开源 oceanbase

盘点2021:一年读完的50本书

石云升

书单 年终总结 28天写作 12月日更 盘点2021

Eureka基础

李子捌

微服务 28天写作 12月日更

.NET内存管理必备知识

喵叔

28天写作 12月日更

iKuai与DNSPod合作,搞了一个大动作!

网络安全 DNS DNS劫持

hmily学习笔记

风翱

12月日更 Hmily

你不得不掌握的前端提交规范(git cz)

你好bk

JavaScript 前端 代码注释 代码规范 12月日更

[Pulsar] Batch message的确认

Zike Yang

Apache Pulsar 12月日更

设计电商秒杀系统

Rabbit

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