调试大规模服务器集群的五大策略.doc_第1页
调试大规模服务器集群的五大策略.doc_第2页
调试大规模服务器集群的五大策略.doc_第3页
调试大规模服务器集群的五大策略.doc_第4页
调试大规模服务器集群的五大策略.doc_第5页
已阅读5页,还剩1页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

调试大规模服务器集群的五大策略【编者按】随着互联网迅速发展,用户访问量以及服务器规模的越来越大,因此,创建一个可靠、稳定、优质的互联网服务是开发者的首要目标。而对于开发 者而言,是否具备一个完善的服务器调试策略将对整个部署维护工作有着至关重要的影响。作者Alex Zhitnitsky现就职于Takipi,其经常帮助Java、Scala开发人员解决服务器端的错误和对常用软件进行测试。本文是Alex分享的一些经验。译文如下:对运行中的真实环境进行调试,比在IDE中进行要困难很多。断点,单步执行等都会变得非常奢侈。因此要做的第一件事是要做出周密的调试计划,否则漫无目的单纯依靠日志记录的做法,将是非常低效的。其次,规模越大的架构会更容易出现差错。因此,如何筛查出错误源头,明确哪个步骤出错是非常重要的。一、分布式日志对于每条记录,我们需要认真分析并了解其背后的含义。但是对于庞大的日志记录我们需要高效的方法来处理,具体请参考这篇文章Logback调节的7个方法。什么样的记录是真正需要的?答案是全部!因为代码会影响到整个应用的方方面面。此外,事务ID 也是很重要的。它能有助于处理异常,因为事务ID经常会贯穿于节点、进程、线程之间。一个较好的处理方法是在App的每个线程入口生成一个UUID。然后 把该ID附加到日志记录中,进行全程监视。该方法在分布式和异步日志中起着举足轻重的作用,特别是与日志管理工具如Logstash和Loggly等一起 使用时。异常处理未知异常很容易会导致系统崩溃。所以建议在代码末端设置一个全局异常处理句柄,例如在Java中进行下面的代码编写:js view plaincopy1. publicstaticvoidThread.setDefaultUncaughtExceptionHandler(2. 3. UncaughtExceptionHandlereh);4. 5. voiduncaughtException(Threadt,Throwablee)6. 7. logger.error(“Uncaughterrorinthread“+t.getName(),e);8. 9. 这或许看起来与Tomcat或Akka框架有点类似。最后这里给出三种处理未知异常时的方法:1. 线程名:根据需要处理的请求来变更线程名是个巧妙的方法。例如在事务处理的任何时间,把事务ID先附加到线程,然后在结束时移除掉。2. 本地线程存储(Thread-local storage,TLS):这是一种使线程特定数据从线程对象分离的方法。借助这些特定数据能便于对出现的错误进行排查。例如事务ID,时间或用户名。否则在欠缺这些数据和线程名的情况下,我们将不得不花费更多时间来处理未知异常。3. 线程映射表(Mapped Diagnostic Context,MDC):MDC类似于本地线程概念,是日志框架的一部分如Log4j或Logback。它在日志级别生成了一个静态映射表,能够较TLS实现更多高级特性。二、快人一步的JstackJstack对Java开发者来说并不陌生,这是一款强大的JDK工具。简单来说,Jstack能够进入一个正在运行的进程然后输出所有的线程meta信息,例如堆跟踪,框架,锁等等。此外它能够对已销毁的进程进行heap dumps或core dumps分析。不过很多时候Jstack是用在回顾的环节,如果错误已经发生,它反馈的可能是过时的信息。因此如何更主动地使用Jstack是关键所在。例如,设置一个吞吐量阀值然后在该值下降时启动jstack。js view plaincopy1. publicvoidstartScheduleTask()2. 3. 4. scheduler.scheduleAtFixedRate(newRunnable()5. 6. publicvoidrun()7. 8. 9. checkThroughput();10. 11. 12. 13. 14. ,APP_WARMUP,POLLING_CYCLE,TimeUnit.SECONDS);15. 16. 17. 18. 19. privatevoidcheckThroughput()20. 21. 22. 23. intthroughput=Value();/theadderisincdwhenamessageisprocessed24. 25. 26. if(throughputMIN_THROUGHPUT)27. 28. Thread.currentThread().setName(Throughputjstackthread:+throughput);29. 30. System.err.println(Minimalthroughputfailed:executingjstack);31. 32. executeJstack();/SeethecodeonGitHubtolearnhowthisisdone33. 34. 35. 36. 37. adder.reset();38. 三、 Stateful JstackJstack应用时需要注意的另一个问题是由于它会返回非常多的线程meta数据,如果缺乏相关的实际状态数据,将会对错误排查造成不便。以数据库查询为例子,可以加上如下一行代码:js view plaincopy1. Thread.currentThread().setName(Context+TID+Params+currentTime,.);我们来比较加入前后的数据输出:加入前:“pool-1-thread-1 #17 prio=5 os_prio=31 tid=0x00007f9d620c9800 nid=0x6d03 in Object.wait() 0x000000013ebcc000加入后:”Queue Processing Thread, MessageID: AB5CAD, type:AnalyzeGraph, queue: ACTIVE_PROD, Transaction_ID: 5678956,Start Time: 10/8/2014 18:34#17 prio=5 os_prio=31 tid=0x00007f9d620c9800 nid=0x6d03 in Object.wait() 0x000000013ebcc000不难看出,加入代码后的信息输出显得更加清晰了。例如线程正在做什么,接收了什么参数如事务ID和消息ID。这些对后续的回滚,错误重现、分离等步骤都是很有帮助的。四、开源追踪工具BTrace如果在不依靠日志和改变代码的前提下,如何去追踪运行时JVM状态呢?答案是BTrace Java代理。在添加该代理后,可使用BTrace脚本语言来获取相关信息。例如以下脚本:js view plaincopy1. BTracepublicclassClassload2. 3. OnMethod(4. 5. Clazz=”+java.lang.ClassLoader”,6. 7. method=”defineClass”,8. 9. location=Location(Kind.RETURN)10. 11. )12. 13. publicstaticvoiddefineClass(Returnclasscl)14. 15. println(Strings.strcat(“loaded”,R(cl);16. 17. Threads.jstack();18. 19. println(“=”);20. 21. 22. 23. 上述代码对全部ClassLoaders及其子类进行跟踪,当defineClass返回时,该脚本会列出载入的类并启动 JStack。但是我们不建议在实际环境中长期使用BTrace。因为Java代理会造成一定的资源开销,同时需要编写不同的脚本来进行追踪。不过在想避 免重启JVM的情况下在运行时环境修改跟踪脚本,BTrace是个不错的选择。五、自定义JVM代理在不改动服务器代码的前提下进行调试,JVM 代理是最佳选择。类似于BTrace,我们可以尝试编写自定义Java代理。这种代理可以进入对象结构体然后在对象实例化的时候进行堆追踪。然后我们可以 对结果进行分析并掌握具体的载入过程。这是BTrace所不具备的,因为BTrace有限制和只能进行读操作。请看下面的示例代码:js view plaincopy1. privatestaticvoidinternalPremain(StringagentArgs,Instrumentationinst)throwsIOException2. 3. .4. 5. Transformertransformer=newTransformer(targetClassName);6. 7. inst.addTransformer(transformer,true)

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论