Nginx日志统计接口被调用次数

cat access.log | awk ‘{ if($6~”POST” && $7~”jsdoctor-mobile-api”)print $7 }’ | awk -F ‘?’ ‘{print $1}’ | sort | uniq -c | sort

Nginx日志统计接口被调用次数

最近公司系统总是出问题,看到项目经理通过日志统计出了后台 API 接口的调用次数(统计在了 Excel 表中)。因为之前自己都没有做过类似的统计,今天看到了不禁在想他是怎么统计的,自己能否也可以做出这样的报表。

初步设想他应该是统计 Nginx 的 access.log 里面所有的请求,然后对数据进行过滤和分组统计次数。

初步分析:

观察 access.log 里面的日志记录的规则。
先通过 tail -n 2000 access.log > fenxi.log 将 access.log 日志中的后 2000 行单独放到名为 fenxi.log 的文件中,方便后面的分析和测试。

分析日志的生成规则,通过查看 Nginx.conf 配置文件,日志的组成部分如下:

1
2
3
log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" "$request_body"';

看上去还是挺规则的,下面是部分日志文件:

1
2
3
4
21.228.17.85 - - [18/Oct/2019:15:46:45 +0800] "POST /mobile-api/index_layout/config/query?token=1e8cb0ffe3ca6253a46c013ac067cb69 HTTP/1.1" 200 791 "-" "okhttp/3.10.0" "-" "{...}"
221.228.17.85 - - [18/Oct/2019:15:46:45 +0800] "GET /platform-admin/member_second/info_manage/edit?id=b74d1bb9ea3b4fd78657ba565caa1c03 HTTP/1.1" 200 2396 "http://test.xxx.com/platform-admin/member_second/info_manage/list" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36" "-" "-"
221.228.17.85 - - [18/Oct/2019:15:46:46 +0800] "POST /mobile-api/member_message_reader/query HTTP/1.1" 200 35 "-" "yancheng/2.3.4 (iPhone; iOS 12.4; Scale/2.00)" "-" "{...}"
221.228.17.85 - - [18/Oct/2019:15:46:47 +0800] "POST /mobile-api/medical_branch_apply_record/query_newest_self?token=08ff294b6ad93aa700fc2d010387c4c7 HTTP/1.1" 200 917 "-" "okhttp/3.10.0" "-" "{...}"

然后对数据进行清理下:

1
2
3
4
21.228.17.85 - - [18/Oct/2019:15:46:45 +0800] "POST /mobile-api/index_layout/config/query?token=1e8cb0ffe3ca6253a46c013ac067cb69 HTTP/1.1"
221.228.17.85 - - [18/Oct/2019:15:46:45 +0800] "GET /platform-admin/member_second/info_manage/edit?id=b74d1bb9ea3b4fd78657ba565caa1c03 HTTP/1.1"
221.228.17.85 - - [18/Oct/2019:15:46:46 +0800] "POST /platform-admin/member_message_reader/query HTTP/1.1"
221.228.17.85 - - [18/Oct/2019:15:46:47 +0800] "POST /mobile-api/medical_branch_apply_record/query_newest_self?token=08ff294b6ad93aa700fc2d010387c4c7 HTTP/1.1"

现在这个日志看起来就比较清晰了,我们需要过滤掉 GET 请求,然后只需要 mobile-api 的数据,最后再把 URL 后的参数去除,统计出 /mobile-api/xxxx 分别被调用的次数即可。

数据清洗

1.过滤非 POST 请求
2.过滤非 mobile-api 请求
3.去除 URL 后的参数
4.统计各个 URL 被调用的次数

技术选型:我们可以使用 awk 命令对数据进行过滤

1.过滤非 POST 请求

1
2
3
4
5
6
cat fenxi.log | awk '{ if($6~"POST")print }'


21.228.17.85 - - [18/Oct/2019:15:46:45 +0800] "POST /mobile-api/index_layout/config/query?token=1e8cb0ffe3ca6253a46c013ac067cb69 HTTP/1.1"
221.228.17.85 - - [18/Oct/2019:15:46:46 +0800] "POST /platform-admin/member_message_reader/query HTTP/1.1"
221.228.17.85 - - [18/Oct/2019:15:46:47 +0800] "POST /mobile-api/medical_branch_apply_record/query_newest_self?token=08ff294b6ad93aa700fc2d010387c4c7 HTTP/1.1"

2.过滤非 mobile-api 请求

1
2
3
4
5
6
7
8
9
10
11
12
cat fenxi.log | awk '{ if($6~"POST" && $7~"mobile-api")print}'


1.228.17.85 - - [18/Oct/2019:15:46:45 +0800] "POST /mobile-api/index_layout/config/query?token=1e8cb0ffe3ca6253a46c013ac067cb69 HTTP/1.1"
221.228.17.85 - - [18/Oct/2019:15:46:47 +0800] "POST /mobile-api/medical_branch_apply_record/query_newest_self?token=08ff294b6ad93aa700fc2d010387c4c7 HTTP/1.1"


cat fenxi.log | awk '{ if($6~"POST" && $7~"mobile-api")print $7}'


/mobile-api/index_layout/config/query?token=1e8cb0ffe3ca6253a46c013ac067cb69
/mobile-api/medical_branch_apply_record/query_newest_self?token=08ff294b6ad93aa700fc2d010387c4c7

3.去除 URL 后的参数

1
2
3
4
5
cat fenxi.log | awk '{ if($6~"POST" && $7~"mobile-api")print $7}' | awk -F '?' '{print $1}'


/mobile-api/index_layout/config/query
/mobile-api/medical_branch_apply_record/query_newest_self

4.统计各个 URL 被调用的次数

1
2
3
4
5
cat fenxi.log | awk '{ if($6~"POST" && $7~"mobile-api")print $7}' | awk -F '?' '{print $1}' | sort | uniq -c


1 /mobile-api/index_layout/config/query
1 /mobile-api/medical_branch_apply_record/query_newest_self

将当前Git最新版本回退到指定版本号并创建新分支

1.git log
查询需要回退到的那一次提交的 commitId

2.git checkout e29440
假设需要回退的版本号为 ‘e29440234ZZZ234234…’,commitId 是很长的一个 id,我们这里只需要输入前几位即可。

3.git checkout -b e29440
创建一个新的分支(e29440)来保留切换后的版本分支,这里的名字是 ‘e29440’,也可以取一个有意义的名字,比如 dev_20191011

4.git push origin e29440
将本地分支推送到远程分支上,分支名称为 ‘e29440’,也可以取一个有意义的名字,比如 dev_20191011

反爬虫日记

最近服务器接口一直被疑似爬虫爬取数据,之前从来都没有在意过这方面的东西。发现这个爬虫还是因为磁盘空间不足发现的。公司的接口都是通过 Nginx 反代的,所以 Nginx 一直都有日志记录的,这次爬虫爬取的速度非常的快,4 个小时有将近 300W 次的请求。从而导致日志异常庞大,最后触发磁盘使用量报警。磁盘容量报警后才发现有人恶意的请求服务器的接口,通过分析接口的参数发现攻击者一直在请求后端的一个接口,于是这几天都在和攻击者斗智斗勇。

利用iftop找出是谁占用了带宽

安装 iftop
yum install iftop,然后用 iftop 命令即可查看相关信息

进入 iftop 界面后
按 p 切换是否显示端口信息;
按 j 或按 k 可以向上或向下滚动屏幕显示的连接记录;
按 B 切换计算 2 秒或 10 秒或 40 秒内的平均流量;
按 L 切换显示画面上边的刻度,刻度不同,流量图形条会有变化;
按 t 切换显示格式为 2 行/1 行/只显示发送流量/只显示接收流量;

EmEditor

EmEditor 是日本的江村软件公司(Emurasoft)所开发的一款在 Windows 平台上运行的文字编辑程序。功能非常的强大,丰富。基本上你能想到文本编辑器该有的功能它都是拥有的。而它对我来说最大的优点就是可以打开非常大的文件,这在查看 log 日志或者是 sql 文件的时候是一个无可替代的功能点。假如你面对一个 2G 的 sql 文件却想打开它并编辑它的时候,你会感谢 EmEditor 给你带来的便利。

官网

下载地址 x64 zip

密钥:DMAZM-WHY52-AX222-ZQJXN-79JXH 如果可以,请支持正版

mysql5.7免安装版配置

1.下载 mysql5.7 免安装版本,mysql5.7-downloads
2.解压文件到 D:\mysql-5.7.27-winx64
3.配置环境变量,系统环境变量新增 MYSQL_HOME 值为 D:\mysql-5.7.27-winx64。在 path 变量中添加 %MYSQL_HOME%\bin
4.在 D:\mysql-5.7.27-winx64 目录下新增 my.ini 文件,文件类容如下:

1
2
3
4
5
6
7
8
9
10
[mysqld]
port = 3306
basedir=D:/mysql-5.7.27-winx64
datadir=D:/mysql-5.7.27-winx64/data
max_connections=200
character-set-server=utf8
default-storage-engine=INNODB
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
[mysql]
default-character-set=utf8

5.以管理员身份打开 cmd 命令窗口,将目录切换到 MySQL 的安装目录的 bin 目录下。依次执行

1
2
3
mysqld --install
mysqld --initialize-insecure --user=mysql
net start mysql

eclipse activiti-designer 插件安装

在学习 activiti 框架的过程中,设计流程是必不可少的一步,虽然官方给出了一个 war 包,提供了 web 网页形式的流程设计工具。但是其不和开发环境集成在一起,每次新增修改流程图都是一件比较麻烦的事情,于是使用 eclipse 插件的方式来设计和修改流程图模型。这里简单记录一下插件的安装过程。

JPA实体关系映射

JPA 实体关系映射:@ManyToMany 多对多关系、@OneToMany @ManyToOne 一对多多对一关系和 @OneToOne 的实例解析。

代码精进之路——减少错误

编写优秀的代码,不能仅仅依靠 一个人的战斗。高质量的代码,依赖于高质量的流水线。作为一个程序员,大家都希望写出优秀的代码。不被 bug 所困扰,可是如何才能编写出没有错误的代码呢?

代码精进之路——开篇

写出优秀的代码是我们每一个程序员的毕生追求,毕竟写代码本身就是个技术活,代码的 好坏,其实也就是我们工艺的好坏。作为一个技术类的工种,我们没有理由不去思考如何 写出优秀、让人惊叹的代码。

作为一个程序员,每天都在和代码打交道,但是在写代码的时候我们一部分是在完成任务,大多数的时候我们都会在想如何将代码写的漂亮,易于维护。中国程序员有一个问题,那就是“不会写代码”。我们自以为将某某语言的 API 学习了一遍,通过一些教程将框架搭建了起来然后写了一个 Hello World,或者是在公司的框架上完成了某一个复杂的功能点就算是会写代码了。

Thread类

Java 多线程最基本的类就是位于 java.lang 包下的 Thread 类 ,这个类继承 Object 类,实现了 Runnable。

public class Thread extends Object implements Runnable

Thread 有优先级的区分,优先级较高的线程优先于优先级较低的线程执行(但不是绝对的)。每一个线程都可以作为一个守护线程。

itextpdf简单使用

前不久公司需要为用户生成一份报告,报告的模板是统一的,内容不同,并且用户可以打印。于是调研了有关 PDF 生成的方式,这里简单记录一下。方案是使用 itextpdf 这个类库对 PDF 模板进行内容填充,从而达到效果。demo 代码中有用到 zxing 进行二维码的生成,多张 PDF 合并成一张 PDF 等。

MacLaunchpad图标大小调整

defaults write com.apple.dock springboard-columns -int 10

defaults write com.apple.dock springboard-rows -int 8

defaults write com.apple.dock ResetLaunchPad -bool TRUE

killall Dock

MybatisPagehelper分页局限

这几天在搭建框架的时候使用了 Mybatis 的一款分页插件,名叫 MybatisPagehelper。在阅读官网文档中常见问题的时候,有一个问题——为什么不支持一对一和一对多结果映射的分页查询?官方给出的答案是:在一对一和一对多时,根据分页条件查询出 100 条数据时,由于一对一和一对多会去重,经过嵌套处理后数据量会减少,因此分页想要获得 100 条数据无法实现。想要支持这种情况可以使用嵌套查询。嵌套查询是要额外执行SQL,主SQL可以得到正确的结果数量,因此可以正常分页。

减小war包体积

现在使用 Jenkins 自动化部署项目有这样一个问题,那就是项目使用到的 jar 包比较多,这就导致每次将 war 包上传到服务器上的时间就比较长。今天无意间看到一个方法可以大幅减少 war 包大小,提升效率。

阻塞、非阻塞和同步、异步的区别

同步场景中阻塞和非阻塞

我们是用传统的水壶烧水。在水烧开之前我们一直做在水壶前面,等着水开。这就是阻塞的。

我们是用传统的水壶烧水。在水烧开之前我们先去客厅看电视了,但是水壶不会主动通知我们,需要我们时不时的去厨房看一下水有没有烧开。这就是非阻塞的。

异步场景中阻塞和非阻塞

我们是用带有提醒功能的水壶烧水。在水烧发出提醒之前我们一直做在水壶前面,等着水开。这就是阻塞的。

我们是用带有提醒功能的水壶烧水。在水烧发出提醒之前我们先去客厅看电视了,等水壶发出声音提醒我们。这就是非阻塞的。

Java中的三种IO模型

在Java语言中,一共提供了三种IO模型,分别是阻塞IO(BIO)、非阻塞IO(NIO)、异步IO(AIO)。

BIO (Blocking I/O):同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。

NIO (New I/O):同时支持阻塞与非阻塞模式,但主要是使用同步非阻塞IO。

AIO (Asynchronous I/O):异步非阻塞I/O模型。

白话文:

BIO (Blocking I/O):有一排水壶在烧开水,BIO的工作模式就是,叫一个线程停留在一个水壶那,直到这个水壶烧开,才去处理下一个水壶。但是实际上线程在等待水壶烧开的时间段什么都没有做。

NIO (New I/O):NIO的做法是叫一个线程不断的轮询每个水壶的状态,看看是否有水壶的状态发生了改变,从而进行下一步的操作。

AIO ( Asynchronous I/O):为每个水壶上面装了一个开关,水烧开之后,水壶会自动通知我水烧开了。