先总结下常用的一些监控工具:

##linux命令

  • 1
    w
    

    系统负载

  • 1
    lsof -p pid
    

    进程打开的文件

  • 1
    lsof -i:port
    

    端口的运行情况

  • 1
    free -m
    

    内存情况

  • 1
    vmstat
    

    进程、内存、内存分页、堵塞IO、traps及CPU活动的信息

  • 1
    iostat
    

    磁盘io情况

  • 1
    top -n 1
    

    cpu/负载/内存等使用情况.

  • 1
    iotop
    

    磁盘io

  • 1
    ps aux | sort -k6nr | head -n 10
    

    查看linux 实际内存占用最多的10个

  • 1
    ps aux | sort -k5nr | head -n 10
    

    查看linux 虚拟内存占用最多的10个

  • 1
    dstat -lamps
    

    查看系统整体状况

  • 1
    pstree -al pid|head -n 1
    

    查看进程启动命令

  • 1
    strace -T -p pid
    

    查看进程系统调用.开销很大,使用时要小心.

  • 1
    netstat
    

    1
    netstat -an |grep port
    
    查看端口连接情况

    1
    netstat -alnp |grep pid
    
    通过pid查看进程所有端口情况

  • 1
    ss -lntp |grep port
    

    通过端口查看进程

  • 1
    nmon
    

    强大的监控工具.也可以方便的出报表.我一般用来在压力测试时监控系统性能.

  • 1
    latencytop
    

    用于查看系统内部慢.以前做mysql性能优化,多亏有这东东.

  • 1
    cat /proc/pid/status  |grep Threads
    

    查看进程内线程个数

##java工具

  • 1
    jvisualvm
    

    jvm的运行情况/各种dump的分析都可以干,没有JRMC牛.oracle承诺会把JRockit的特性迁移到HotSpot上面来.现在jdk下已经有jmc了.

  • 1
    jps -lv
    

    查看所有java进程.

  • 1
    jinfo -sysprops pid
    

    查看java进程系统参数

  • 1
    jinfo  -flag jvmflag pid
    

    查看jvm flag.比如查看xss,

    1
    jinfo  -flag ThreadStackSize pid
    

  • 1
    jstack pid
    

    查看线程栈信息

  • 1
    jmap -dump:live,format=b,file=xxx.hprof pid
    

    生成heap dump

  • 1
    jmap -histo pid
    

    查看java堆中对象统计信息

  • 1
    java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal
    

    查看jvm flag

    1
    2
    3
    4
      The first column appears to reflect the data type of the option (intx, uintx, uint64_t, bool, double, ccstr, ccstrlist). 
      The second column is the name of the flag and the third column is the value, if any, that the flag is set to.
      The fourth column appears to indicate the type of flag and has values such as {product},{pd product}, {C1 product} for client or {C2 product} for server, {C1 pd product} for client or {C2 pd product} for server, {product rw}, {diagnostic} 
      (only if -XX:+UnlockDiagnosticVMOptions was specified), {experimental}, and {manageable}. See Eugene Kuleshov's The most complete list of -XX options for Java 6 JVM for a brief description of most of these categories as well as a listing of most of these options themselves.
    
  • tda

    线程栈分析器,这个是jvisualvm的插件.

  • mat

    基于eclipse的heap dump分析工具,这个工具是比jvisualvm在heap分析这块专业.不过jvisualvm能cover住大多数场景,基本上我都只用jvisualvm了.

  • 1
    jmap -heap pid
    

    检查heap情况

  • GCViewer

    GC日志分析

  • 1
    jstat  -gcutil pid
    

    查看gc总体情况

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
      S0  — Heap上的 Survivor space 0 区已使用空间的百分比
      S1  — Heap上的 Survivor space 1 区已使用空间的百分比
      E   — Heap上的 Eden space 区已使用空间的百分比
      O   — Heap上的 Old space 区已使用空间的百分比
      P   — Perm space 区已使用空间的百分比
      YGC — 从应用程序启动到采样时发生 Young GC 的次数
      YGCT– 从应用程序启动到采样时 Young GC 所用的时间(单位秒)
      FGC — 从应用程序启动到采样时发生 Full GC 的次数
      FGCT– 从应用程序启动到采样时 Full GC 所用的时间(单位秒)
      GCT — 从应用程序启动到采样时用于垃圾回收的总时间(单位秒)
    
  • 1
    btrace
    

    神器,线上出问题了,想知道某个方法的调用情况,入参之类的,就靠btrace了. 此工具大致原理如下:

    1. 1
      btrace-client
      
      attach 目标进程(
      1
      com.sun.tools.attach.VirtualMachine#attach
      
      )
    2. 加载agent
      1
      btrace-agent
      
      (
      1
      com.sun.tools.attach.VirtualMachine#loadAgent
      
      )
    3. agent启动服务端,开启监听端口
    4. 1
      brace-client
      
      把编译好的用户btrace代码发送到服务端,并等待服务端响应
    5. 1
      btrace-agent
      
      通过asm修改运行时代码,织入用户btrace代码逻辑.监控到信息后,发给
      1
      btrace-client
      
  • jmc

    生成记录

    1
    2
    3
    4
    5
    6
    7
    8
      #检查特性是否开启
      jcmd 23385 VM.check_commercial_features
      #开启商业特性
      jcmd 23385 VM.unlock_commercial_features
      #检查JFR状态
      jcmd 23385 JFR.check
      #执行180sJFR收集
      jcmd 23385 JFR.start name=recording filename=/root/recording.jfr duration=180s
    

My WordPress Development Toolbox

http://tommcfarlin.com/wordpress-developer-toolbox/

本来是准备找git的客户端,看到这篇文章.不喜欢tower,大爱SoureTree.

browserstack也挺好的,适合做浏览器兼容性测试.

JVM plus Docker: Better together

http://www.javaworld.com/article/2456960/java-app-dev/jvm-plus-docker-better-together.html

docker刚好弥补jvm对资源管理(CPU/IO)的不足.

SharedHashMap vs Redis

http://vanillajava.blogspot.jp/2014/05/sharedhashmap-vs-redis.html

这位哥异常牛掰,java低延迟方面的专家.把性能做到极致啊!!!

1
It was designed to be used in Java in a pause less, garbage free manner.
狂赞!!!先留着,有时间了看看源代码.

##高性能服务器架构 http://blog.csdn.net/zhoudaxia/article/details/14223755

这些经验可以参考下:

  • 数据拷贝

    特别是java,很多数据拷贝的代码埋得深,比如

    1
    StringBuilder
    
    扩容,集合扩容等等.java中的数据拷贝除了带来cpu的压力,也会给gc带来压力.

    参考:使用零拷贝提高数据传输效率

  • 上下文切换

    线程越多,上下文切换就会越多.需要合理评估处理模型和系统情况.按照SEDA的方式把一个请求划分为多个阶段,但是多个阶段的独立线程池真的会增加上下文的切换,但这样可能会让系统利用率最高.

  • 内存分配

    采用类似于Buddy memory allocation的策略来减少开销.

  • 锁竞争

    一定要控制好锁的粒度.某些场景用map来存放锁对象,而不要使用一把大锁.

##数据库版本控制工具liquibase http://www.liquibase.org/quickstart.html

今天和勇哥讨论了如何来控制数据库版本.我们想的方案是,数据库里面有张versions表,里面记录当前的版本是多少.然后数据库更新文件存在项目中,并以目录来区分.这样就可以在项目启动时,来对比是否有新版本,是否需要升级.这样可以做到全自动化,需要规范现在的开发同学的行为,更重要的一点是,没有人来做这个事情.

liquibase正好在做这个事情,他也支持sql格式的版本,学习成本相当低.而且有内置的数据库版本和集群场景的检测,给力,先试试.

参考:如何跟踪数据库结构变动

##可伸缩性最佳实践:来自eBay的经验 (http://www.infoq.com/cn/articles/ebay-scalability-best-practices)[http://www.infoq.com/cn/articles/ebay-scalability-best-practices]

手里有本2011年的架构师特刊,翻开看到的第一篇文章.虽然有点老了,但是经验还是值得我们借鉴.

  • 按功能分割

咱们现在的架构体系基本上遵循这条最佳实践.借助于dubbo/cxf实现功能服务化.应用层可以实现水平线性扩展.

  • 水平切分

应用层面的无状态很重要,会话之类的东西可以放在缓存服务器上,尽量让LB来实现水平切分.

数据库层面读写分离/分区/分库/分表.

  • 避免分布式事务

分布式第一定律,不要使用分布式.特别是两阶段提交,对系统的吞吐影响很大.ebuy通过周密调整数据库操作的次序、异步恢复事件,以及数据核对(reconciliation)或者集中决算(settlement batches)来实现最终一致性.

  • 用异步策略解耦程序

组件之间的异步带来的好处是解耦/缓冲压力.组件内的异步能提供跟灵活的资源管理策略(当然带来了上下文切换的开销).我们还需要异步任务管理/确保机制.

  • 将过程转变为异步的流
  • 虚拟化所有层次

虚拟化所有层次我们还做的不够好.硬件资源层面的虚拟化可以通过docker来实现.目前docker最缺少的是资源的管理/发现/注册能力.通用资源服务层面的虚拟化也可以通过注册中心来实现.结合配置管理系统/框架组件化,可以做到对应用的透明.

  • 适当地使用缓存

缓存组件很多,分布式/集中式/进程内,不要选花了眼.同类型的我们只需要一种缓存组件,他必须要能支持丰富的数据结构,如果能提供持久话的能力最好(前提是在down掉的情况下要保证数据的一直.).

##Why Choose Jetty? https://webtide.com/why-choose-jetty/

一直有想法把jetty嵌入到我们的程序中来运行,jetty自身的体系结构优势便于我们去裁剪或者新增功能.

jetty的设计哲学很酷:

Don’t put your application into Jetty, put Jetty into your application.

http proxy

http://rehorn.github.io/livepool/

http://mitmproxy.org/

两个都是好东东.可以看下手机里面在干啥,吐槽下某些粗制滥造的app.也可以用来模拟http请求.

jvm flag

http://stas-blogspot.blogspot.jp/2011/07/most-complete-list-of-xx-options-for.html

最全的jvm flag.

1.场景描述:

某项目使用hibernate,在切换到dubbo后,在构造结果对象时从延迟加载对象中获取数据时,报

1
org.hibernate.LazyInitializationException: could not initialize proxy - no Session

构造结果对象的操作没有在事务环境下执行.

2.原因分析:

cxf不报错是因为在web.xml中配置了

1
org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
,在请求到达web filter后,创建了
1
EntityManager
,请求结束后关闭
1
EntityManager
.在请求线程处理过程中,都可以拿到
1
EntityManager
,所以不会报错(至少可以从ThreadLocal中拿到).

切换为dubbo后,请求不会经过web filter,在事务模版代码中执行业务操作,可以正确的拿到

1
EntityManager
,不会报错.但是执行到构造结果对象时,就悲剧了.

3.解决办法:

1.修改模版方法,把构造结果对象部分的代码也放到事务中执行.

2.编写支持dubbo的OpenEntityManagerInViewFilter

可以通过

1
TransactionSynchronizationManager
做到如果
1
EntityManagerFactory
在线程变量中不存在则创建
1
EntityManager
,服务处理结束时,关闭
1
EntityManager
.

4.优劣分析

  1. 性能考虑

    1
    open session in veiw
    
    模式还是不怎么优雅,事务执行链路太长了,会影响性能.而且对于我们提供的服务接口来说,构造结果对象已经是最后一步了,后面再也不需要延迟加载对象,不需要在filter里面来做此操作.

    web应用有在渲染模版时读取延迟加载对象的场景,这种场景使用还有意义.

  2. 功能角度

    如果遇到应用内的两个dubbo服务调用,dubbo会走injvm协议.此时请求不会经过io栈,但是会执行所有的dubbo filter.

    比如外部请求调用服务A,服务A调用内部服务B.

    外部请求调A时,filter创建

    1
    EntityManager
    
    ,然后调用服务B时,filter不创建
    1
    EntityManager
    
    ,但是在请求B结束时,filter关闭了
    1
    EntityManager
    
    .在请求A中处理剩下的业务逻辑,如果遇到要操作数据库,就只有哭了.

    为什么web请求就不怕这种filter重入呢?web请求在forward时,你必须把request对象带进去,所以可以在request对象的attribute里面记录是否进过了这个filter.可以参考

    1
    org.springframework.web.filter.OncePerRequestFilter
    
    .但是调用dubbo时,你只需要拿到服务代理对象就ok了,没有办法来知道整个请求链的情况.

5.最后结论

还是修改下我们自己的代码,把构造结果对象部分的代码也放到事务中执行.