热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

用Nginx单独记录并可示化显示响应慢的TOP20Web接口

相信很多小伙伴都见过一些商业产品中的url接口响应时间,实时汇总显示功能。可以理解为web接口的慢查询,与sql的慢查询有异曲同工之妙,但是想做却无从入手不知道怎么实现此功能,所以

0x0

   其实nginx本身就带有接口响应时间的功能,只不过还需要改造下,比如说单独记录超过1000ms(1秒)的响应,并写入数据库中。要注意的是并不建议大家将记录直接写入数据库中,因为数据库有时会成为nginx的负担,间接写入即可。需要简单修改下log模块,涉及文件ngx_http_log_module.c 通常位于nginx-1.17.9/src/http/modules/ngx_http_log_module.c 

 大约838行, 找到ngx_http_log_request_time函数并修改如下:


static u_char *
ngx_http_log_request_time(ngx_http_request_t *r, u_char *buf,
    ngx_http_log_op_t *op)
{
	ngx_time_t *tp;
	ngx_msec_int_t ms;
    time_t t = time(NULL);
	struct tm *loc_time = localtime(&t);
	tp = ngx_timeofday();
	u_char slow_log[2048];
	memset(slow_log, 0, sizeof(slow_log));
	ms = (ngx_msec_int_t) ((tp->sec - r->start_sec) * 1000
			+ (tp->msec - r->start_msec));
	ms = ngx_max(ms, 0);
	ngx_sprintf(slow_log, "%04d/%02d/%02d %02d:%02d:%02d %V %V?%V waste time %d.%d
",
			loc_time->tm_year + 1900, loc_time->tm_mon + 1, loc_time->tm_mday,
			loc_time->tm_hour, loc_time->tm_min, loc_time->tm_sec,
			&r->headers_in.server, &r->uri, &r->args, (time_t) ms / 1000,
			ms % 1000);
	int logfd;
	if ((logfd = open("/var/log/nginx/nginx_slow.log", O_RDWR | O_CREAT | O_APPEND,
	S_IRUSR | S_IWUSR)) == -1) {
		ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
				"can not open file:logfile
");
	}
	char Server_name[256];
	const char *server_name = "%.*s";
	memset(Server_name, 0, sizeof(Server_name));
	snprintf((char *) Server_name, sizeof(Server_name), server_name,
					r->headers_in.server.len, r->headers_in.server.data);
	/* 只记录大于1秒的并且域名不是grafana.sshfortress.com  */
    if (ms > 1000 && strcmp("grafana.sshfortress.com", Server_name) != 0) 
		write(logfd, slow_log, strlen((char *)slow_log));
	close(logfd);
	return ngx_sprintf(buf, "%T.%03M", (time_t) ms / 1000, ms % 1000);
}

之后再编译即可

# ./configure --prefix=/usr/local/nginx1.17.9
# make -j4 ; make install

#mkdir -p /var/log/nginx; chmod -R 777 /var/log/nginx

简单配置下

   server {
                listen *:80;
                server_name slow.sshfortress.com;
                location / {
                        proxy_set_header   Host    $host;
                        proxy_set_header   X-Real-IP $remote_addr;
                        proxy_set_header   REMOTE-HOST $remote_addr;
                        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
                        proxy_pass http://127.0.0.1:3000;
                }
        }
 

启动nginx即可,如果接口响应时间超过1秒,那么var/log/nginx/nginx_slow.log中就会有记录了。但这只是将慢查询记录而已,我们还需要排序以及可示化的展示。记录也可以直接写入mysql但我并没有这么做,为什么不直接写入呢,原因是如果mysql如果响应慢则会影响nginx的响应,但写入磁盘就不会出现这种情形了。接下来就简单实现下把数据同步写入到数据库中。

0x01 

   首先建个表 用于同步写入记录

 CREATE TABLE `nginx_slow` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `date` datetime NOT NULL,
  `server_name` varchar(255) NOT NULL,
  `url` varchar(255) NOT NULL,
  `waste_time` decimal(11,3) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;

之后实现一个同步数据的工具,这里用shell即可实现,代码如下:

#!/bin/bash
#    insert_mysql.sh
set -x
if [ $# != 1 ]
  then
 echo "Usage insert_mysql.sh /var/log/nginx/nginx_slow.log"
  exit 1
fi
tail -n 1 -f ${1}|while read var
do 
         value=`echo $var|awk "{print $3}"`
         value2=`echo $var|awk "{print $4}"`
         value3=`echo $var|awk "{print $7}"`
         echo "$value $value2 $value3"
         mysql -h 127.0.0.1 -usuper -pxxxxxxxxx -e "use nginx; INSERT INTO nginx_slow( date, server_name, url, waste_time) VALUES ( now(), "${value}", "${value2}", "$value3");"
done

运行脚本就可以同步写入数据了,是不是很简单呢

# ./insert_mysql.sh /var/log/nginx/nginx_slow.log

0x02 

   最后在grafana里面配置下当天接口慢查询TOP 20即可,相关语句是

select n.url,avg(n.waste_time) 平均响应时长 
from nginx_slow n
WHERE n.`date` > curdate()
group by 1
order by 2 desc
limit 20

最后效果图如下


推荐阅读
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • SpringBoot uri统一权限管理的实现方法及步骤详解
    本文详细介绍了SpringBoot中实现uri统一权限管理的方法,包括表结构定义、自动统计URI并自动删除脏数据、程序启动加载等步骤。通过该方法可以提高系统的安全性,实现对系统任意接口的权限拦截验证。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文探讨了C语言中指针的应用与价值,指针在C语言中具有灵活性和可变性,通过指针可以操作系统内存和控制外部I/O端口。文章介绍了指针变量和指针的指向变量的含义和用法,以及判断变量数据类型和指向变量或成员变量的类型的方法。还讨论了指针访问数组元素和下标法数组元素的等价关系,以及指针作为函数参数可以改变主调函数变量的值的特点。此外,文章还提到了指针在动态存储分配、链表创建和相关操作中的应用,以及类成员指针与外部变量的区分方法。通过本文的阐述,读者可以更好地理解和应用C语言中的指针。 ... [详细]
  • Python瓦片图下载、合并、绘图、标记的代码示例
    本文提供了Python瓦片图下载、合并、绘图、标记的代码示例,包括下载代码、多线程下载、图像处理等功能。通过参考geoserver,使用PIL、cv2、numpy、gdal、osr等库实现了瓦片图的下载、合并、绘图和标记功能。代码示例详细介绍了各个功能的实现方法,供读者参考使用。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • 本文介绍了PE文件结构中的导出表的解析方法,包括获取区段头表、遍历查找所在的区段等步骤。通过该方法可以准确地解析PE文件中的导出表信息。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
author-avatar
寒风中挣扎_427
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有