已注销用户的gravatar头像
已注销用户 2016-04-12 14:59:21

java http某些接口GET请求响应时间超长应该如何排查?

先上图,如下:

java http某些接口GET请求响应时间超长应该如何排查?

看标红的地方1000+ ms,很奇怪,同一个接口响应时间有的快有的慢,只是参数不一样而已。

请求的内容是 从redis里面查是否存在缓存,如果有缓存从redis里面取数据,如果没有就查数据库,这几个接口都设置了缓存时间,缓存时间为7秒。

看了半天,老大叫我看看redis连接的类。

好吧 贴下代码:

public class JedisUtil {
	private static JedisPool pool;

	// configurations
	private static String ip;
	private static int port;
	private static int maxTotal;
	private static int maxIdle;
	private static int maxWait;
	private static int timeout;
	private static int maxRetry;
	public static Properties jedisProps = new Properties();
	private static InputStream in;
	static {
		try {
			in = Thread.currentThread().getContextClassLoader().getResourceAsStream("redis.properties");
			jedisProps.load(in);
			ip = jedisProps.getProperty("ip");
			port = Integer.parseInt(jedisProps.getProperty("port"));
			maxTotal = Integer.parseInt(jedisProps.getProperty("maxTotal"));
			maxIdle = Integer.parseInt(jedisProps.getProperty("maxIdle"));
			maxWait = Integer.parseInt(jedisProps.getProperty("maxWait"));
			timeout = Integer.parseInt(jedisProps.getProperty("timeout"));
			maxRetry = Integer.parseInt(jedisProps.getProperty("maxRetry"));
		} catch (Exception ex) {
			ex.printStackTrace();
		}finally{
			if(null != in){
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public static void init() {

	}

	/**
	 * Setup configuration.
	 */
	public static void setup(String serverIP, int serverPort, int poolMaxTotal, int poolMaxIdle, int poolMaxWait, int readTimeout, int resourceMaxRetry) {
		ip = serverIP;
		port = serverPort;
		maxTotal = poolMaxTotal;
		maxIdle = poolMaxIdle;
		maxWait = poolMaxWait;
		timeout = readTimeout;
		maxRetry = resourceMaxRetry;
	}

	/**
	 * Close jedis resource.
	 */
	public static void closeJedis(Jedis jedis) {
		if (null == jedis || null == pool)
			return;

		pool.returnResource(jedis);
	}

	/**
	 * Get jedis resource.
	 */
	public static Jedis getJedis() throws Exception {
		if (null == pool)
			initPool();

		if (null == pool)
			return null;

		// retrieve resource from pool
		Jedis jedis = null;
		int retry = 0;
		do {
			try {
				jedis = pool.getResource();

			} catch (Exception ex) {
				ex.printStackTrace();
				pool.returnBrokenResource(jedis);
			}

			retry++;
		} while (null == jedis && retry < maxRetry);

		return jedis;
	}

	public synchronized static void initPool() throws Exception {
		if (null != pool)
			return;

		JedisPoolConfig config = new JedisPoolConfig();
		config.setMaxTotal(maxTotal);
		config.setMaxIdle(maxIdle);
		config.setMaxWaitMillis(maxWait * 1000);
		config.setTestOnBorrow(true);
		config.setTestOnReturn(true);

		pool = new JedisPool(config, ip, port, timeout * 1000);
	}

这里关闭redis这里应该没什么问题吧~

配置文件 properties内容如下:

maxTotal=10000
maxIdle=200
maxWait=1000
timeout=300
maxRetry=20

@最代码官方 说说优化接口的方法或技巧吧~

可能描述的不是特别好,可以提一些建议!先给大家 了

所有回答列表(1)
最代码官方的gravatar头像
最代码官方  LV167 2016年4月12日

1.先通过nginx access log查找出那些http接口响应平均时间超长,如果是同一接口不同参数导致请排查参数问题,如果是不同接口请排查出问题的接口

2.如果java接口内部由n多个查询组成,比如:用户数据由mysql或其他关系数据库查询得到,用户分享代码总数由redis查询得到,用户分享代码列表由mongodb查询得到则分别增加统计信息,比如:

public List<Codes> queryUserCodes(long uid,int page,int count){
		long start=System.currentTimeMillis();
		User user=userService.findUserById(uid);
		List<Long> codeIds=codeService.findCodesByUserid(uid,page,count);
		List<Code> codes=codeService.findCodesByIds(codeIds);
		long end=System.currentTimeMillis();
		System.out.println("queryUserCodes:"+(end-start));

	}
	
	
	public User findUserById(long uid){
		long start=System.currentTimeMillis();
		//从mysql系统查询数据
		long end=System.currentTimeMillis();
		System.out.println("findUserById:"+(end-start));
	}
	

	public List<Long> findCodesByUserid(long uid){
		long start=System.currentTimeMillis();
		//从redis系统查询数据
		long end=System.currentTimeMillis();
		System.out.println("findCodesByUserid:"+(end-start));
	}
	
	
	public List<Code> findCodesByIds(long uid){
		long start=System.currentTimeMillis();
		//从mongodb系统查询数据
		long end=System.currentTimeMillis();
		System.out.println("findCodesByIds:"+(end-start));
	}

3.通过输出的这些log来统计到底哪个方法影响了性能

当然还可以通过aop方式拦截比如Controller,Service,Dao的所有方法查询性能,这样得到的数据会更全面,同时也为后续性能优化做好数据量化准备。

参考资料:

python基于nginx访问日志统计客户端ip访问量

AOP基础--动态代理实现用户操作日志统计代码

另外不用通过System.currentTimeMillis()硬编码计算消耗时间,java的开源框架Perf4J可以实现类似功能。

Perf4J

评论(3) 最佳答案
顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友