您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
   
 
 
     
   
 订阅
  捐助
调试大规模服务器集群的五大策略
 
作者:伍昆 来源:CSDN  发布于 2015-1-14
  1354  次浏览      31
 

对于开发者而言,是否具备一个完善的服务器调试策略将对整个部署维护工作有着至关重要的影响。Alex Zhitnitsky经常帮助Java、Scala开发人员解决服务器端的错误和对常用软件进行测试,本文是他分享的一些经验。

随着互联网迅速发展,用户访问量以及服务器规模的越来越大,因此,创建一个可靠、稳定、优质的互联网服务是开发者的首要目标。而对于开发者而言,是否具备一个完善的服务器调试策略将对整个部署维护工作有着至关重要的影响。作者Alex Zhitnitsky现就职于Takipi,其经常帮助Java、Scala开发人员解决服务器端的错误和对常用软件进行测试。本文是Alex分享的一些经验。

译文如下:

对运行中的真实环境进行调试,比在IDE中进行要困难很多。断点,单步执行等都会变得非常奢侈。因此要做的第一件事是要做出周密的调试计划,否则漫无目的单纯依靠日志记录的做法,将是非常低效的。其次,规模越大的架构会更容易出现差错。因此,如何筛查出错误源头,明确哪个步骤出错是非常重要的。

一、分布式日志

对于每条记录,我们需要认真分析并了解其背后的含义。但是对于庞大的日志记录我们需要高效的方法来处理,具体请参考这篇文章Logback调节的7个方法。

什么样的记录是真正需要的?

答案是全部!因为代码会影响到整个应用的方方面面。此外,事务ID也是很重要的。它能有助于处理异常,因为事务ID经常会贯穿于节点、进程、线程之间。一个较好的处理方法是在App的每个线程入口生成一个UUID。然后把该ID附加到日志记录中,进行全程监视。该方法在分布式和异步日志中起着举足轻重的作用,特别是与日志管理工具如Logstash和Loggly等一起使用时。

异常处理

未知异常很容易会导致系统崩溃。所以建议在代码末端设置一个全局异常处理句柄,例如在Java中进行下面的代码编写:

这或许看起来与Tomcat或Akka框架有点类似。最后这里给出三种处理未知异常时的方法:

1.  线程名:根据需要处理的请求来变更线程名是个巧妙的方法。例如在事务处理的任何时间,把事务ID先附加到线程,然后在结束时移除掉。

2.  本地线程存储(Thread-local storage,TLS):这是一种使线程特定数据从线程对象分离的方法。借助这些特定数据能便于对出现的错误进行排查。例如事务ID,时间或用户名。否则在欠缺这些数据和线程名的情况下,我们将不得不花费更多时间来处理未知异常。

3.  线程映射表(Mapped Diagnostic Context,MDC):MDC类似于本地线程概念,是日志框架的一部分如Log4j或Logback。它在日志级别生成了一个静态映射表,能够较TLS实现更多高级特性。

二、快人一步的Jstack

Jstack对Java开发者来说并不陌生,这是一款强大的JDK工具。简单来说,Jstack能够进入一个正在运行的进程然后输出所有的线程meta信息,例如堆跟踪,框架,锁等等。此外它能够对已销毁的进程进行heap dumps或core dumps分析。

不过很多时候Jstack是用在回顾的环节,如果错误已经发生,它反馈的可能是过时的信息。因此如何更主动地使用Jstack是关键所在。例如,设置一个吞吐量阀值然后在该值下降时启动jstack。

三、 Stateful Jstack

Jstack应用时需要注意的另一个问题是由于它会返回非常多的线程meta数据,如果缺乏相关的实际状态数据,将会对错误排查造成不便。以数据库查询为例子,可以加上如下一行代码:

我们来比较加入前后的数据输出:

加入前:

加入后:

不难看出,加入代码后的信息输出显得更加清晰了。例如线程正在做什么,接收了什么参数如事务ID和消息ID。这些对后续的回滚,错误重现、分离等步骤都是很有帮助的。

四、 开源追踪工具BTrace

如果在不依靠日志和改变代码的前提下,如何去追踪运行时JVM状态呢?答案是BTrace Java代理。在添加该代理后,可使用BTrace脚本语言来获取相关信息。

例如以下脚本:

上述代码对全部ClassLoaders及其子类进行跟踪,当defineClass返回时,该脚本会列出载入的类并启动JStack。但是我们不建议在实际环境中长期使用BTrace。因为Java代理会造成一定的资源开销,同时需要编写不同的脚本来进行追踪。不过在想避免重启JVM的情况下在运行时环境修改跟踪脚本,BTrace是个不错的选择。

五、自定义JVM代理

在不改动服务器代码的前提下进行调试,JVM代理是最佳选择。类似于BTrace,我们可以尝试编写自定义Java代理。这种代理可以进入对象结构体然后在对象实例化的时候进行堆追踪。然后我们可以对结果进行分析并掌握具体的载入过程。这是BTrace所不具备的,因为BTrace有限制和只能进行读操作。请看下面的示例代码:

这里创建了一个transformer对象,并注册到一个能对类进行变更的对象之上。

小结

综上所述,获得的有价值数据越多,解决问题的速度就越快。在当今信息为王的时代,宕机时间的影响几以秒计,因此是否具备一个完善的服务器调试策略将对整个部署维护工作有着至关重要的影响。

   
1354 次浏览       31
相关文章

为什么要做持续部署?
剖析“持续交付”:五个核心实践
集成与构建指南
持续集成工具的选择-装载
相关文档

持续集成介绍
使用Hudson持续集成
持续集成之-依赖管理
IPD集成产品开发管理
相关课程

配置管理、日构建与持续集成
软件架构设计方法、案例与实践
单元测试、重构及持续集成
基于Android的单元、性能测试
最新活动计划
嵌入式软件架构设计 12-11[北京]
LLM大模型与智能体开发实战 12-18[北京]
嵌入式软件测试 12-25[北京]
AI原生应用的微服务架构 1-9[北京]
AI大模型编写高质量代码 1-14[北京]
需求分析与管理 1-22[北京]

集成与构建指南
项目管理:Maven让事情变得简单
持续集成工具hudson
持续集成
Maven权威指南
程序集(UML中的包)之间循环
更多...   


产品发布管理
配置管理方法、实践、工具
多层次集成配置管理
使用CC与CQ进行项目实践
CVS与配置管理
Subversion管理员


海航股份 重构及持续集成
电研华源 设计原理、建模与重构
软件配置管理日构建及持续集成
单元测试、重构及持续集成
中国软件研发中心 单元测试与重构
单元测试、重构和持续集成实践
罗克韦尔 C++单元测试+重构+Gtest
更多...