运行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

运行sre10_在生产中运行Java:SRE的观点相关推荐

  1. 在生产中使用Java 11:需要了解的重要事项

    来源:SpringForAll社区 如果您正考虑更新最新版本的Java,阅读本文以了解有关Oracle Java 11的最重要信息. 如果您及时了解Java社区的新闻,您可能听说Oracle改变了他们 ...

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

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

  3. 性能测试测试环境与生产环境_不在生产中测试? 在生产中进行测试!

    性能测试测试环境与生产环境 如果您上一次更新IT安全标准是在5年前或更早,那么它们很可能与当今的DevOps和站点可靠性工程 (SRE)实践的现状不符. 一个特别棘手的话题是生产中的测试,以及因此使用 ...

  4. 如何在生产中实现Elasticsearch的零停机升级

    文章目录 1. 版本注意事项 2.定义升级策略 2.0 快照备份 2.1 滚动升级(minor或单个major升级) 2.1.1 Elasticsearch运行在最新的次要版本上 2.1.2 Elas ...

  5. Idea运行web项目时,提示java.lang.ClassNotFoundException: com.mysql.jdbc.Driver解决方法

    Idea运行web项目时,提示java.lang.ClassNotFoundException: com.mysql.jdbc.Driver解决方法 参考文章: (1)Idea运行web项目时,提示j ...

  6. hive运行mysql脚本_用java代码调用shell脚本执行sqoop将hive表中数据导出到mysql

    1:创建shell脚本 1 touch sqoop_options.sh2 chmod 777 sqoop_options.sh 编辑文件  特地将执行map的个数设置为变量  测试 可以java代码 ...

  7. java 运行main_使用maven运行Java Main的三种方法解析

    maven使用exec插件运行java main方法,以下是3种不同的操作方式. 一.从命令行运行 1.运行前先编译代码,exec:java不会自动编译代码,你需要手动执行mvn compile来完成 ...

  8. 利用jdk自带的运行监控工具JConsole观察分析Java程序的运行 Jtop

    利用jdk自带的运行监控工具JConsole观察分析Java程序的运行 原文链接 一.JConsole是什么 从Java 5开始 引入了 JConsole.JConsole 是一个内置 Java 性能 ...

  9. java面试题4 牛客:运行下列代码,运行结果为

    第四题:运行下列代码,运行结果为() class A {public A() {System.out.println("class A");}{ System.out.printl ...

最新文章

  1. C++中的修饰符类型
  2. asp.net播放声音
  3. linux下ip冲突检测 arp
  4. asp:HyperLink中 Eval要用string.Format绑定
  5. 一款世界上最快的固态硬盘
  6. redis的淘汰策略
  7. Android控制文字水平间距android:letterSpacing
  8. ASP.NET MVC5+EF6+EasyUI 后台管理系统(65)-MVC WebApi 用户验证 (1)
  9. python 遍历文件夹下文件修改并保存_利用python完成自动化的任务之遍历文件夹修改文件之后并保存备份...
  10. base64与base64url编码
  11. 大型分布式Java项目--宜立方商城
  12. java true false 异或_三元运算符21?true:false;
  13. 转载:人生真相之为何你应该假装自己是一个电脑白痴(原文pconline)
  14. ubuntu 最新提权漏洞_Ubuntu和Debian最新的KDE安全漏洞,附-修复指南
  15. 磁盘不见了只剩一个c盘_电脑磁盘忽然只剩c盘怎么回事_win10除了c盘都不见了的处理方法...
  16. vs2010注册码 激活方法
  17. myqq框架 python插件
  18. 渲染算法学习(四)-- Environment Lighting
  19. TiDB 实战优化之 SQL 常见问题与优化案例
  20. 疲惫的 618,很难再激起年轻人的多巴胺?

热门文章

  1. 牛客2020年愚人节比赛
  2. 大吉大利【牛客网】(牛客练习赛60)
  3. Function Query(树状数组)
  4. YBTOJ:灯光控制(贪心)(公倍数)(暴力枚举)
  5. CF396B-On Sum of Fractions【数学】
  6. POJ3263-Tallest Cow【前缀和】
  7. jzoj1373-食物链【并查集】
  8. Codeforces Round #676 (Div. 2) E待补
  9. Kafka Controller Redesign 方案
  10. 腾讯面试题:一条SQL语句执行得很慢的原因有哪些?