运行sre10_在生产中运行Java:SRE的观点

运行sre10

作为站点可靠性工程师 (SRE),我确保我们的生产服务高效,可扩展且可靠。 典型的SRE是生产大师,必须对更广泛的体系结构有很好的了解,并精通许多更精细的细节。

SRE是会说多种语言的程序员,这是常见的,他们希望能够理解多种不同的语言。 例如,C ++可能很难编写,测试和正确使用,但具有高性能,非常适合诸如数据库之类的后端系统。 Python很容易编写,非常适合快速编写脚本,对自动化很有用。 Java位于中间位置,尽管它是一种编译语言,但它提供了类型安全性,性能以及许多其他优点,使其成为编写Web基础结构的理想选择。

尽管SRE采用的许多最佳实践可以推广到任何语言,但Java还是存在一些独特的挑战。 本文计划重点介绍其中一些,并讨论我们可以如何解决这些问题。

部署方式

一个典型的Java应用程序由数百个类文件组成,这些类文件由您的团队编写,或者由应用程序依赖的通用库编写。 为了控制类文件的数量,并提供更好的版本控制和分隔,通常将它们捆绑到JAR或WAR文件中。

托管Java应用程序的方法有很多,一种流行的方法是使用Java Servlet容器,例如Tomcat或JBoss 。 从理论上讲,它们提供了一些通用的Web基础结构和库,以使其更易于部署和管理Java应用程序。 以Tomcat(一个提供实际Web服务器并代表您加载应用程序的Java程序)为例。 在某些情况下,这可能会很好地起作用,但实际上会增加额外的复杂性。 例如,您现在需要跟踪JRE的版本,Tomcat的版本以及应用程序的版本。 测试不兼容性,并确保每个人都使用相同版本的完整堆栈可能会出现问题,并导致细微的问题。 Tomcat还带来了自己的定制配置,这是另一回事。

一个很好的承租人是“ 保持简单 ”,但是在Servlet容器方法中,您必须跟踪几十个Tomcat文件,一个或多个组成应用程序的WAR文件以及所有的Tomcat配置。随之而来。

因此,有些框架通过嵌入自己的Web服务器,而不是托管在完整的应用程序服务器中,试图减少这种开销。 仍然有一个JVM,但它会调用一个JAR文件,其中包含运行该应用程序所需的所有内容。 支持这些独立应用程序的流行框架是Dropwizard和Spring Boot 。 要部署该应用程序的新版本,只需更改一个文件,然后重新启动JVM。 这在开发和测试应用程序时也很有用,因为每个人都在使用相同版本的堆栈。 对于回滚(SRE的核心工具之一)来说,它也特别有用,因为只需更改一个文件(可以像更改符号链接一样快)。

Tomcat风格的WAR文件要注意的一件事是,该文件将包含应用程序类文件以及该应用程序依赖于所有JAR文件的库。 在独立方法中,所有依赖项都合并到单个Fat JAR中 。 单个JAR文件,其中包含整个应用程序的类文件。 这些Fat或Uber JAR不仅易于版本化和复制(因为它是单个不可变文件),而且由于对依赖项中未使用的类进行修剪而实际上可以小于等效的WAR文件。

通过不需要单独的JVM和JAR文件,甚至可以更进一步。 实际上,例如capsule.io之类的工具可以将JAR文件,JVM和所有配置捆绑到一个可执行文件中。 现在,我们可以真正确保整个堆栈使用相同的版本,并且部署与服务器上可能已经安装的内容无关。

保持简单,并使用单个Fat JAR或可能的可执行文件,使应用程序的版本快速便捷。

启动

即使Java是一种编译语言,它也不会编译为机器代码,而是会编译为字节码。 在运行时,Java虚拟机(JVM)解释字节码,并以最有效的方式执行它。 例如, 即时 (JIT)编译使JVM可以监视应用程序的使用方式,并即时将字节码编译为最佳机器代码。 从长远来看,这对应用程序可能是有利的,但是在启动过程中,它可能会使应用程序在数十分钟或更长时间内处于次优状态。 需要注意的是,这对负载平衡,监视,容量规划等有影响。

在多服务器部署中,最佳实践是将流量缓慢增加到新启动的任务,使其有时间进行预热,并且不损害服务的整体性能。 在将新任务放入用户服务路径之前,您可能会通过向其发送人工流量来预热新任务。 如果预热过程无法逼近正常的用户流量,则人工流量可能会出现问题。 实际上,这种伪造的流量可能会触发JIT对通常不会发生的情况进行优化,从而使应用程序处于次优状态,甚至处于比不进行JIT情况更糟的状态。

容量规划时也应考虑启动缓慢。 不要期望冷任务与热任务处理相同的负载。 推出新版本的应用程序时,这一点很重要,因为在任务预热之前,系统的容量将下降。 如果不考虑这一点,可能会同时重新加载太多任务,从而导致基于容量的级联中断。

期待冷启动,并尝试以实际流量预热应用程序。

监控方式

该建议是通用的监视建议 ,但是对于Java值得重复。 确保从Java应用程序中导出最重要和最有用的指标,并对其进行收集并轻松绘制图形。 有很多工具和框架可用于导出指标,甚至还有更多工具和框架可用于收集,汇总和显示。

当出现问题时,应该仅从收集的指标中排除故障即可 。 您不应该依赖日志文件或查看代码来处理中断。

大多数中断是由更改引起的。 也就是说,应用程序的新版本,配置更改,新的流量来源,硬件故障或后端依赖关系的行为不同。 应用程序导出的度量标准应包括识别Java版本,应用程序和使用中的配置的方法。 它应该分解流量,混合,错误计数等的来源。还应该跟踪后端依赖项的运行状况,延迟,错误率等。 在大多数情况下,这足以快速诊断出故障。

特定于Java的指标可以帮助您了解应用程序的运行状况和性能。 指导有关如何扩展和优化应用程序的未来决策。 垃圾收集时间,堆大小,线程数,JIT时间都很重要,并且特定于Java。

最后,关于测量响应时间或等待时间的注释。 也就是说,应用程序处理请求所花费的时间。 许多人在看平均等待时间方面犯了错误,部分原因是它很容易计算。 平均值可能会引起误解 ,因为它没有显示分布的形状 。 大多数请求可能会很快得到处理,但是请求的尾部可能很少,但是需要一段时间。 这对于JVM应用程序尤其令人不安,因为在垃圾回收过程中,有一个“ 停止世界” (STW)阶段,在此阶段,应用程序必须暂停以允许垃圾回收完成。 在此暂停中,不会响应任何请求,并且用户可能要等待几秒钟。

最好收集最大或99%(或更高)的百分比延迟。 对于百分位数,也就是说,每100个请求中,有99个比该数字更快地得到服务。 查看最坏情况下的延迟更有意义,并且更能反映用户感知的性能。

衡量重要的指标,您以后可以依赖。

内存管理

您花费大量时间来学习各种JVM垃圾收集算法 。 当前最先进的是并发收集器G1或CMS 。 您可以决定哪种方法最适合您的应用程序,但目前G1可能是赢家。 有很多很棒的文章解释了它们如何工作,但是我将介绍一些关键主题。

启动时,Java虚拟机(JVM)通常会保留大量OS内存,并将其分为堆和非堆。 非堆包含诸如Metaspace ( 正式称为Permgen )和堆栈空间之类的区域。 元空间用于类定义,而堆栈空间用于每个线程的堆栈。 堆用于创建的对象,这些对象通常占用大部分内存使用量。 与典型的可执行文件不同,JVM具有-Xms-Xmx标志 ,用于控制堆的最小和最大大小。 这些限制限制了JVM将使用的最大RAM量,这可以使服务器上的内存需求可预测。 通常将这两个标志设置为相同的值,以提供它们来填充服务器上的可用RAM。 还有一些针对Docker容器调整大小的最佳实践。

垃圾回收(GC)是通过查找不再使用(即不再引用)且可以回收的Java对象来管理此堆的过程。 在大多数情况下,JVM会扫描对象的完整图,并标记找到的对象。 最后,删除所有未访问的内容。 为了确保没有竞争条件,GC通常必须停止运行(STW),这会在应用程序完成时将其暂停一会儿。

GC是(可能是不必要的)怨恨的根源,因为它被归咎于许多性能问题。 通常,这归结为不了解GC的工作原理。 例如,如果堆的大小太小,则JVM可以主动进行垃圾收集,从而徒劳地释放空间。 然后,应用程序可能会陷入“ GC崩溃 ”循环中,这几乎没有什么进展来释放空间,并在GC中花费了越来越多的时间,而不是运行应用程序代码。

可能发生这种情况的两种常见情况是内存泄漏或资源耗尽 。 垃圾收集的语言不应该允许传统上称为内存泄漏的内容,但是,它们可能会发生。 例如,维护一个永不过期的对象的缓存。 该缓存将永远增长,即使该缓存中的对象可能永远不会再使用,它​​们仍然被引用,因此没有资格进行垃圾回收。

另一个常见的情况是无限队列 。 如果您的应用程序将传入的请求放置在无限制的队列中,则该队列可能永远增长。 如果出现请求高峰,队列中保留的对象可能会增加堆使用率,从而导致应用程序在GC中花费越来越多的时间。 因此,应用程序将有更少的时间来处理来自队列的请求,从而导致积压量增加。 随着GC努力寻找任何要释放的对象,这逐渐失去控制,直到应用程序无法取得任何进展。

另外一个细节是,垃圾收集器算法具有许多优化措施,可以尝试减少总的GC时间。 一个重要的发现( 弱代假设 )是对象要么存在很短时间(例如,与处理请求有关),要么存在很长时间(例如,管理寿命长的资源的全局对象)。

因此,堆进一步划分为年轻空间和旧空间。 在年轻空间中运行的GC算法假定对象将被释放,否则,GC会将对象提升到旧空间。 用于旧空间的算法做出了相反的假设,即对象将不会被释放。 因此,也可以调整年轻人/老人的大小,并且根据G1或CMS,方法会有所不同。 但是,如果年轻空间太小,那么应该只存在很短时间的物体最终将被提升到旧空间。 打破了旧的GC算法所做的某些假设,导致GC的运行效率降低,并导致了诸如内存碎片之类的次要问题。

如前所述,GC是长尾延迟的来源,因此应关闭监视。 应该记录GC每个阶段所花费的时间,以及GC运行之前和之后堆空间的满度(被年轻/旧/等等分解)。 这提供了调优或改进应用程序以控制GC所需的所有提示。

让GC成为您的朋友。 应该特别注意堆和垃圾收集器,并且应该对其进行调整(甚至是粗略地调整),以确保即使在满载/最坏的情况下也有足够的堆空间。

其他技巧

调试

Java有许多丰富的工具可用于在开发和生产中进行调试。 例如,可以捕获正在运行的应用程序中的实时堆栈跟踪和堆转储。 这对于了解内存泄漏或死锁很有用。 但是,通常必须确保应用程序已启动以允许这些功能,并且典型工具jmap , jcmd等在服务器上实际上可用。 在Docker容器或非标准环境中运行应用程序可能会使此操作更加困难,因此请测试并编写一本有关如何执行此操作的手册。

许多框架还通过Web服务公开了许多此类信息,以便于调试,例如Dropwizard / threads资源或Spring Boot生产端点 。

不要等到出现生产问题后,立即测试如何获取堆转储和堆栈跟踪。

更少但更大的任务

JVM的许多功能对每个运行的JVM都有固定的成本,例如JIT和垃圾回收。 您的应用程序也可能具有固定的开销,例如资源轮询(后端数据库连接)等。如果运行较少但较大的实例(就CPU和RAM而言),则可以减少此固定成本,从而实现规模经济。 我已经看到Java应用程序拥有的CPU和RAM数量增加了一倍,使它每秒能够处理4倍的请求(不影响延迟)。 但是,这对应用程序以多线程方式进行扩展的能力做出了一些假设,但是通常垂直扩展比水平扩展容易。

使您的JVM尽可能大。

32位和64位Java

如果您的应用程序使用的RAM不超过4GiB,通常会运行32位JVM。 这是因为32位指针的大小是64位大小的一半,这减少了每个Java对象的开销。 但是,由于现代CPU是64位的,通常具有64位特定的性能改进,并且RAM的价格便宜,这使得64位JVM无疑是赢家。

使用64位JVM。

减载

还是一般性建议,但对Java很重要。 为避免 GC崩溃或任务繁重而导致过载 ,应用程序应积极减少负载。 也就是说,超出某个阈值,应用程序应拒绝新请求。 尽早拒绝某些请求似乎很糟糕,但是比允许应用程序变得不可恢复并导致所有请求失败都更好。 有许多避免过载的方法,但是常见的方法是确保队列有界,并且线程池的大小正确 。 此外,出站请求应具有适当的截止日期 ,以确保缓慢的后端不会对您的应用程序造成问题。

处理尽可能多的请求,并且不再处理。

结论

希望本文使您考虑一下Java生产环境。 尽管不是说明性的,但我们重点介绍了一些重点领域。 整个链接都应指导您正确的方向。

如果您有任何疑问或意见,请通过@TheBramp与我联系,或访问我的网站和博客bramp.net了解更多文章。

翻译自: https://www.javacodegeeks.com/2017/12/running-java-production-sres-perspective.html

运行sre10

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/333943.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

不同符号的两个整数求余和取模的计算技巧(规律)

文章目录求余函数和取模函数的区别x 和 y 符号不同,求余数和模数的技巧求余的运算规律(技巧)取模的运算规律(技巧)求余函数和取模函数的区别 求余函数rem(x,y) 和取模函数 mod(x,y) 的区别: 当 x 和 y 的符…

pytorch数据处理的操作

张量(256,256)转换为三维通道图片张量(256,256,3)可以采用下面方法: 1.先将张量转换为数组。 2.在numpy数组增加维数(相当于在张量里增加了通道的维度),即(256,256,1)。 3.增加numpy数组维度中的数量(也就是将张量里的一个通道变为3),即(256,256,3)。 4.根据需要来决…

toastutils报错_史上最好用的Android全量版本更新库XUpdate使用指南

在这里插入图片描述项目简介XUpdate是一个轻量级、高可用性的Android全量版本更新框架。XUpdate是为了解决在不同项目组、不同平台之间进行统一的Android全量版本更新的库。它具有轻量、灵活、低耦合、高可用等特点,可以很方便地定制属于自己的版本更新。设计原由在…

travis-ci_使用Travis-CI的SpringBoot应用程序的CI / CD

travis-ci在本文中,我们将学习如何将Travis CI用于SpringBoot应用程序的持续集成和持续部署(CI / CD)。 我们将学习如何运行Maven构建目标,使用JaCoCo插件,使用SonarCloud代码质量检查,建立泊坞窗图像进行测…

音标、音节、音素、音符

[kəˌmjuːnɪˈkeɪʃn] 👆上面这个叫『音标』,里面有三个『音节』,kə、mjuːnɪ、keɪʃn,mjuːnɪ是『轻读音节』,keɪʃn是『重读音节』,这个『音标』含有11个『音素』,分别为&#xff1…

outlook邮箱邮件大小限制_设置Office 365邮箱默认发送和接收邮件大小限制

Office 365默认的 35MB 的邮件大小限制。Office 365 最大是支持 150MB 的邮件体积的。我们只需用 Windows Powershell 连接 Office 365 ,然后通过命令修改 Exchange Online 中的邮箱计划即可。方法如下:1、连接到 Office 365 PowerShell借助 Office 365 …

python中形参*args和**kwargs简述

形参*args的作用:传递任意数量的实参。 形参*args中的星号让python创建一个名为args的空元组,并将收到的所有值都封装到这个元组中。其实args换成其他的标识符完全没问题,只是习惯上用args。 如下举例: def fun(*args):print(a…

运动基元_Java更快地对基元数组进行排序?

运动基元看来,在不久的将来,Java中的原语排序数组可能会提高性能。 弗拉基米尔雅罗斯拉夫斯基(Vladimir Yaroslavskiy)已在core-libs-dev邮件列表中发布了一条消息 ,标题为“ Dual-Pivot Quicksort的新优化版本 ”&…

Linux 命令之 rpmbuild -- 用于创建 rpm 格式的二进制软件包和源码软件包

文章目录一、命令介绍二、命令选项(一)从 specfile 建立(二)从 tarball 包建立(三)从 source package 包建立(四)其它选项(五)所有 rpm 都可使用的选项&#…

只做macd二次金叉_【教你一招】MACD低位二次金叉

原标题:【教你一招】MACD低位二次金叉来源:K线密码MACD低位二次金叉技术要点1、第二次金叉离第一次金叉距离越近越好;2、MACD第二次金叉的位置以高于第一次金叉为好;3、MACD第二次金叉时结合K线形态上的攻击形态研判(如&#xff1…

计算机领域专业术语中英文对照(时常更新)

机器学习 线性回归(linear regression) 多标签分类(multi-label classification,MLC) 验证集(validation) 均方误差(MSE) 偏差(bias) 方差(variance) 深度学习 多层感知机(MLP) 反向传播(Back Propagation) 张量(Tensor) 随机梯度下降(SGD) 向量(Vector) 标量(Sc…

owasp maven_OWASP依赖性检查Maven插件–必须具备

owasp maven我不得不非常遗憾地承认,我不知道OWASP依赖检查maven插件 。 自2013年以来似乎已经存在。显然GitHub上已有千个项目正在使用它。 过去,我手动检查了依赖项,以根据漏洞数据库检查它们,或者在很多情况下,我只…

软件包管理器 RPM 升级软件包过程分析

升级软件包 alsaplayer-0.99.76-2.2.fc4.i386.rpm,并显示详细的升级信息: rpm -Uvv alsaplayer-0.99.76-2.2.fc4.i386.rpm把显示内容当中对我们有用的挑出来: D: opening db environment /var/lib/rpm/Packages joinenv D: opening d…

ubtunu打开firefox_Linux Ubuntu 终端命令行打开firefox报错

1,报错$ firefox(firefox:2673): GConf-WARNING **: Client failed to connect to the D-BUS daemon:Failed to connect to socket /tmp/dbus-80Eq35bHIz: Connection refused(firefox:2673): GConf-WARNING **: Client failed to connect to the D-BUS daemon:Fail…

自然语言处理领域基本概念笔记

自然语言处理 词向量: 自然语言处理问题要转化为机器学习的问题,首先就要把单词数学化表示,就是用n维实数向量来代表一个单词。 对话系统 对话系统发展历程的三个阶段: 1.基于符号规则和模板的对话系统 2.基于统计机器学习的…

spring-junit4_基于Spring的应用程序-迁移到Junit 5

spring-junit4这是关于将基于Gradle的Spring Boot应用程序从Junit 4迁移到闪亮的新Junit 5的快速文章。Junit 4测试继续与Junit 5 Test Engine抽象一起工作,该抽象为在不同编程模型中编写的测试提供支持。例如,Junit 5支持能够运行JUnit 4测试的Vintage …

如何理解 inode

一、inode是什么? 理解inode,要从文件储存说起。 文件储存在硬盘上,硬盘的最小存储单位叫做"扇区"(Sector)。每个扇区储存512字节(相当于0.5KB)。 操作系统读取硬盘的时候&#xff0c…

go语言os.exit(1)_Go语言-信号os.Interrupt和信号syscall.SIGTERM的应用

实例package mainimport("fmt""os""os/signal""sync""syscall""time")func worker(stop for {select {case fmt.Println("exit")returndefault:fmt.Println("running...")time.Sleep(3)}}}fu…

深度学习基本概念笔记

注意力机制(Attention Mechanism): 注意力机制受到人类视觉注意力机制的启发,即关注图像特定部分的能力。即当神经网络发现输入数据的关键信息后,通过学习,在后继的预测阶段对其予以重点关注。 Attention Mechanism可以帮助模型对输入的X每个…

java api 开发_Java开发人员应该知道的前20个库和API

java api 开发优秀且经验丰富的Java开发人员的特征之一是对API的广泛了解,包括JDK和第三方库。 我花了很多时间来学习API,尤其是在阅读了Effective Java 3rd Edition之后 ,Joshua Bloch建议在Java 3rd Edition中使用现有的API进行开发&#x…