使用JDI进行线上程序断点信息记录

2016/02/22 08:26:21 No Comments

之前在某一次蚂蚁金服的分享当中,得知可以通过在线上程序中进行断点记录,当程序运行到断点的时候,即将此次调用的上下文信息记录下来,以进行进一次分析。实际上这也是相当于在程序中打log记录信息的方式了。当线上出现问题时,我们最希望的就是将相应的参数信息记录下来,以拿到当时的数据,以便知道到底是哪儿出现了问题。但又不希望通过重新在代码中加入代码,然后发布这样的方式,因为新的发布可能导致问题重现机率变小等。

java的整个调试体系为JDPA,Oracle提供了高级的jdi接口以方便使用java来连接调试程序进行相应的调试。这样,只需要调用相应的java接口,就能进行打断点,记录断点,然后继续运行,清除断点这样基本的断点调试手法了。

1. 连接远程JVM

连接其它JVM称之为附加(attach)操作,当前实现中有2种,如果是本地JVM,则通过Process的方式即可,如果是远程,则需要通过socket的方式才能进行连接。首先是server端需要开启调试agent,并且指定相应的端口,如下启动命令所示:

-Xdebug -agentlib:jdwp=transport=dt_socket,address=1234,server=y,suspend=n

上面的参数表示监听指定端口(1234),并且当存在断点时并不主动阻塞。
旧的JVM也有使用Xrunjdwp参数的,但不再被建议使用.

read more… »

redis中aof备份策略中的配置参数

2015/12/15 11:31:36 No Comments

在使用redis时,都会配置相应的存储策略,以保证redis并不会由于意外挂掉,在短时间内重启时数据不会消失。在当前的版本中,redis提供了bgsave和aof两种策略,本文主要描述了aof中的相关参数以及为什么这样是可以足够安全的。
本文的描述主要参考redis的conf文件以及各项网络

appendonly

开启aof特性,这个控制是否启用aof.

appendfilename

写入文件的文件名。开启aof之后,每条命令(除读之外的命令),均会写入到文件中,这里即实际写入的文件.

appendfsync

写入策略,默认值everysec,每秒写一次(调用flush)。另外两个值,always | no,分别表示每次redis写命令之外就写文件,和由操作系统保证。always对硬盘压力大,everysec是一个平衡值,no对硬盘压力最小,但调度由系统控制,丢失数据风险最大.

read more… »

Metrics相关技术使用点

2015/10/25 10:26:50 No Comments

本文参考了原metrics的get start以及用户手册,如链接:http://metrics.dropwizard.io/3.1.0/getting-started/

技术点

1 Gauge 取值功能

用来进行获取某个值的功能,其封装一个getValue方法,那么在指定的周期时间之内,metrics可以调用这个方法用于获取特定的值。比如,某个队列当前大小,当前cpu,内存等信息。
因为是实时获取,因此可能有些值获取成本较高,或者不需要每次都取最新值,因此可以考虑使用类似缓存的技术。如在5s之内是缓存的。

read more… »

解决jetty在windows下锁静态文件的问题

2015/10/13 18:36:57 No Comments

本文原英文地址:http://www.eclipse.org/jetty/documentation/9.3.0.v20150612/troubleshooting-locked-files-on-windows.html#d0e26059
在jetty容器内,对于静态文件,会采用内存缓存的实现方式,如采用buteBuffer的方式来进行缓存。如果使用NIO连接器(默认情况),jetty就会采用文件映射(filemapper)的方式。但是这个方式在windows下会存在一个问题,即使用文件内存映射会导致这个文件被进程锁住,其它进程就不能但修改或者替换这个文件了。解决这个问题的一个方法就会停掉jetty,但这种方式显示不太靠谱。

jetty提供了一个开关标记来开启或者禁止内存映射,在类DefaultServlet中有一个属性useFileMappedBuffer,此属性值默认为false,并且在配置文件webdefault.xml中进行配置。

默认的配置文件存储在jar包jetty-webapp-${version}.jar中的org/eclipse/jetty/webapp/webdefault.xml,还有一份存储在jetty-home/etc/目录中。两者的区别在于,后者由jetty运行时配置文件中默认使用。前者由在代码中WebAppContext默认使用(没有配置值的情况下).最简单的作法就是修改这个配置文件,如下所示:

<init-param>
   <param-name>useFileMappedBuffer</param-name>
   <param-value>true</param-value> <!-- change to false -->
</init-param>

read more… »

jdk线程池中调整coreSize无效的问题分析及处理

2015/10/08 15:40:24 No Comments

近期在ETL项目中,增加一个用于监控队列数和当前线程数之间的关系,并动态调节线程池大小的一个功能。其作用机制即是指当发现队列中任务太多时,能够增大线程数,以达到使用更多的线程来运行任务的目的。相应的伪代码如下所示:

    extThreadPoolExecutor.setCorePoolSize(newCorePoolSize);
    extThreadPoolExecutor.prestartCoreThread();

但是在后面通过监控发现以下的信息

队列总数:1670,核心线程数:500,活跃线程数:200

即相应的核心线程数是已经作了相应的调整,但是活跃线程数,却始终没有上升。没有达到调节线程数的目的。
从理论上说,如果增大了核心线程数,那么线程数会在新任务时,会自动创建新的线程来进行相应的任务,并且我们通过手动启动核心线程来强制运行任务,因此也不会出现线程并没有创建的问题(详细可以查看prestartCoreThread的作用)。

read more… »

redisson中连接对象创建及断线重连

2015/09/04 15:43:49 No Comments

在redisson中,由于使用了netty来封装对redis的协议访问,因此对于连接对象的创建和释放,也借由相应的connection来实现。由篇由masterSlave的角度,描述整个redisson中对于client的封装,以及在网络中断情况下,客户端会得到什么样的反馈,如何实现重连的情况。

本篇主要介绍master slave情况下各个对象的关系图信息,以及在具体创建时的一些处理问题.Redisson版本:2.1.1

1 对象关系图

整个关系如上所示,由下图进行描述

  1. 由MasterSlaveServersConfig负责配置连接的各项参数,比如master地址,slave地址,连接数大小等,这个对象是在redision创建时,由Config对象负责创建的
  2. 在调用Redission.create时,创建起相应的connectionManager对象,其持有相应的master连接信息,以及相应slave的连接信息
  3. 相应的connectionManager负责创建卢相应masterEntry以及slaveEntry信息,并且保存相应的映射信息
  4. connectionManager负责当前客户端对于具体服务器端的各项配置以下,比如转码器,连接池,使用的各项协议等,其根据这些信息,使用netty创建起相应的redisClient对象
  5. entry将已经创建好的redisClient交由connectionEntry负责持有,因此这里的client仅表示一个特有的客户端连接信息。在初始化时并不自动创建相应的连接
  6. entry因此持有相应的client,因此也自然根据当前的需要创建出相应的connection对象,这里entry的创建工作交由client负责,同时将创建好的connection管理起来

read more… »