用swoole实现nginx日志解析
1.原技术路线解析
在nging配置中将日志信息交给syslog处理,rsyslog配置中将数据传递给了514端口解析,然后将解析好的数据传入elasticsearch中。
nginx配置
server {
listen 80;
listen [::]:80;
server_name test.86dev.wrddns.com;
# 以下两行将日志写入syslog
access_log syslog:server=unix:/dev/log,facility=local5,tag=web_1,severity=info main;
error_log syslog:server=unix:/dev/log,facility=local5,tag=web_1,severity=error warn;
# ....其他配置
}
/etc/rsyslog.conf
# 配置文件,存放解析规则xxx.conf和ruleBase文件xx.rb
$IncludeConfig /etc/rsyslog.d/*.conf
# 配置将日志放到哪个端口解析
local5.* @10.3.19.86:514
在实际应用过程中有一些问题,不能和php上面的一些配置进行配合记录,解析规则不好配置,有些内容解析不好,所以探索使用新的技术路线。
2.新技术路线
尝试使用新技术路线,通过swoole起一个服务,然后监听9502端口,rsyslog将日志推向该端口,对日志进行解析后推入elasticsearch,此时可以获取到php端的一些配置。以下是大体思路
2.1 选择swoole的server类型。
这里不再赘述swoole的安装,首要考虑的问题是原推向514的协议类型。
先查看端口的协议类型
# root @ WENGINE in ~ [9:48:51]
$ netstat -antup | grep 514
udp 0 0 0.0.0.0:514 0.0.0.0:* 23560/rsyslogd
udp 0 0 :::514 :::* 23560/rsyslogd
可以看到是udp协议,所以选用swoole的 upd服务
结合laravel的commands来编写服务端
<?php
namespace App\Console\Swoole;
use Illuminate\Console\Command;
use swoole_websocket_server;
use swoole_server;
use swoole_process;
use swoole_sock_udp;
use UAParser\Parser;
use GeoIp2\Database\Reader;
use Wrd\Framework\Models\SysConfig;
use Elasticsearch\ClientBuilder;
class SwooleServer extends Command
{
protected $signature = 'swoole-server start
{cmd=start : can use start}
{--daemon : set to run in daemonize mode}
';
protected $description = 'swoole server control';
public $access_buffer = [];
public function __construct()
{
parent::__construct();
}
public function handle()
{
$command = $this->argument('cmd');
$option = $this->option('daemon');
switch ($command) {
case 'start':
$this->initWs($option);
break;
default:
$this->info('请按照下面格式输入命令:php artisan swoole-server {start}');
break;
}
}
public function initWs($daemonize = false)
{
if ($daemonize) {
$this->info('Starting Websocket server in daemon mode...');
} else {
$this->info('Starting Websocket server in interactive mode...');
}
$server = new swoole_server('0.0.0.0', 9502, SWOOLE_PROCESS, SWOOLE_SOCK_UDP);
$server->set([
'daemonize' => $daemonize,
'log_file' => '/var/www/html/storage/logs/websocket.log',
'worker_num' => 1,
'task_worker_num' => 1,
]);
$server->on('Packet', function($serv, $data, $clientInfo)
{
$serv->task($data);
});
$server->on('Task', function ($serv, $task_id, $from_id, $data) {
//通过正则表达式提取出需要的信息,不同的日志格式需要不同的正则,这里只写一种情况
$rule = '/\<\d*\>.*\d{2}\:\d{2}\:\d{2}\s[^\s]*\s[^\s]*\s(\w*\_\d*)\:\s\[Customize-format\]/';
preg_match($rule, $data, $matches);
if (empty($matches)) {
$this->writeLog($data); //记录下无法解析的日志,更正正则
return false;
}
$vhost = $matches[1];
$ip = $matches[2];
//...更多参数
$ua = $matches[12];
//解析UA,这里使用的解析库https://github.com/ua-parser/uap-php
$parser = Parser::create();
$parser_ua = $parser->parse($ua);
$browser = $parser_ua->ua->family;
$os = $parser_ua->os->family;
$device = $parser_ua->device->family;
//解析IP,这里使用的解析库https://github.com/maxmind/GeoIP2-php
$reader = new Reader(public_path().'/geoip2/GeoLite2-City.mmdb');
try{
$record = $reader->city($ip);
$country = $record->country->isoCode;
$continent = $record->continent->names['zh-CN'];
$subdivisions = $record->mostSpecificSubdivision->names['zh-CN'];
$city = $record->city->names['zh-CN'];
$geoip = array(
'location' => array($record->location->longitude, $record->location->latitude)
);
} catch (\Exception $e) {
//如果ip没有被收录(项目有很多内网ip),则拿数据库中的提前配置项,进行解析
}
$res = array(
'vhost' => $vhost,
'ip' => $ip,
// ...其它项
'token' => $token,
'browser' => $browser,
'os' => $os,
'device' => $device,
'continent' => $continent,
'country' => $country,
'subdivisions' => $subdivisions,
'city' => $city,
'geoip' => $geoip,
);
$this->access_buffer[] = $res;
//每隔一段时间,写入到elasticsearch
if (count($this->access_buffer) > 0 && time() - strtotime($this->access_buffer[0]['@timestamp']) > 10) {
$insert_data = $this->access_buffer;
$this->access_buffer = [];
$this->insertElasticsearch('access', $insert_data);
}
//return 数据 给 Finish
return "Task {$task_id}'s result";
});
$server->on('Finish', function ($serv,$task_id, $data) {
echo "Task {$task_id} finish\n";
});
$server->start();
}
public function insertElasticsearch($type='access', $data){
foreach($data as $item){
$params['body'][] = [
'index' => [
'_index' => $type.'-'.date('Y.m.d', time()),
'_type' => 'events',
]
];
$params['body'][] = $item;
}
extract(\Config::get('app.elastic', [
'host' => '127.0.0.1',
'port' => '9200'
]));
//往elasticsearch写数据,这里使用的库https://github.com/elastic/elasticsearch-php
$helper = ClientBuilder::create()
->setHosts([$host.":".$port])
->build();
if (!empty($params['body'])) {
$response = $helper->bulk($params);
//var_dump($response);
}
}
public function writeLog($info){
$alert_message = array(
'error' => '此条信息未能命中日志格式,未写入elasticsearch',
'info' => $info
);
\Log::alert($alert_message);
}
2.2 通过更改nginx的main日志格式简化正则表达式
nginx的配置中的
log_format main [$proxy_add_x_forwarded_for]-[$remote_user]-[$time_local]-[$request]-[$status]-[$bytes_sent]-[$http_host]-[$http_referer]-[$http_user_agent]-[$cookie_wengine_ticket]-[archer-main];
加了特殊符号,并且最后给了一个标识,这样能提高命中准确度
2.3 更改rsyslog的端口
local5.* @10.3.19.86:9502
2.4 其它一些问题
可以通过nc来检测swoole的udp服务是否通
yum install -y nc
# root @ WENGINE in ~ [10:17:07] C:130
$ nc -u 127.0.0.1 9502
ceshi
可以写supervisor的脚本来使swoole服务器一直启动
[program:swooleserver]
directory = /var/www/html
command=php artisan swoole-server
user=apache
autostart=true
startsecs=2
autorestart=true
redirect_stderr=true
stopsignal=INT
stderr_logfile_maxbytes=1MB
stderr_logfile_backups=10
stderr_capture_maxbytes=1MB
stderr_events_enabled=false
用swoole实现nginx日志解析的更多相关文章
- tomcat及nginx相关,格式化输出,配置及日志解析
1.https://www.cnblogs.com/jingmoxukong/p/8258837.html?utm_source=gold_browser_extension Tomcat ...
- Logstash使用grok插件解析Nginx日志
grok表达式的打印复制格式的完整语法是下面这样的: %{PATTERN_NAME:capture_name:data_type}data_type 目前只支持两个值:int 和 float. 在线g ...
- Logstash收集nginx日志之使用grok过滤插件解析日志
grok作为一个logstash的过滤插件,支持根据模式解析文本日志行,拆成字段. nginx日志的配置: log_format main '$remote_addr - $remote_user [ ...
- ELK+Redis 解析Nginx日志
一.ELK简介 Elk是指logstash,elasticsearch,kibana三件套,我们一般使用它们做日志分析. ELK工作原理图: 简单来讲ELK具体的工作流程就是客户端的logstash ...
- 使用Hive的正则解析器RegexSerDe分析nginx日志
1.环境: hadoop-2.6.0 + apache-hive-1.2.0-bin 2.使用Hive分析nginx日志,站点的訪问日志部分内容为: cat /home/hadoop/hivetest ...
- [日志分析]Graylog2进阶 通过正则解析Nginx日志
之前分享的 [日志分析]Graylog2采集Nginx日志 主动方式 这篇文章介绍了Graylog如何通过Graylog Collector Sidecar来采集nginx日志. 由于日志是未经处理的 ...
- Goaccess解析nginx日志备忘
参考 http://nginx.org/en/docs/http/ngx_http_log_module.html?&_ga=1.92028562.949762386.1481787781#l ...
- 烂泥:利用awstats分析nginx日志
本文由ilanniweb提供友情赞助,首发于烂泥行天下 想要获得更多的文章,可以关注我的微信ilanniweb 昨天把nginx的日志进行了切割,关于如何切割nginx日志,可以查看<烂泥:切割 ...
- nginx日志分析利器GoAccess
面试的时候一定会被面到的问题是:给出web服务器的访问日志,请写一个脚本来统计访问前10的IP有哪些?访问前10的请求有哪些?当你领略过goaccess之后,你就明白,这些问题,除了考验你的脚本背诵记 ...
随机推荐
- C语言总结的知识点
什么是有效数字? ------------------------- 数据类型 运算符: 函数: 程序结构: 存储结构 内存管理 关键字: ------------------------- C语言: ...
- pat甲级1085
1085 Perfect Sequence (25 分) Given a sequence of positive integers and another positive integer p. T ...
- 动态控制C4C UI元素的显示和隐藏
C4C UI上UI元素的显示和隐藏可以通过Key User在Adaptation模式里通过编辑一些简单的rule去控制,诸如这种格式: if ( logic expression = true ) t ...
- react里面怎么引入样式
模块样式 在刚开始构建好框架的时候,准备开始写业务,在第一个页面的时候就会碰到怎么引入样式的问题,踩过一些坑,不是使用style,头部也不需要另外取名,直接引入css就可以,引入方式是这样 <d ...
- 百度非会员满速下载利器(IDM)Internet Download Manager v6.30.8 中文特别版
下载利器(IDM)Internet Download Manager v6.30.8 中文特别版 所属分类:工具软件 应用平台:Windows 资源版本:v6.30.8 最后更新:2018年04月14 ...
- dotNetFx40_Client_x86_x64和dotNetFx40_Full_x86_x64这两个有什么区别?两个都要安装还是安装其中一个?
这个是NET Framework 4.0的安装文件它是支持生成和运行下一代应用程序和 XML Web Services 的内部 Windows 组件,很多基于此架构的程序需要它的支持才能够运行.简单的 ...
- Ajax的学习笔记(一)
AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML),ajax并不是一门单独的语言,而是一种技术,是指一种创建交互式网页应用的网页开发技术. ...
- Linux 性能检查常用命令
####消耗CPU最多的进程 [root@Yong ~]# ;|head ##拼接进程号 [root@Yong ~]# |awk '{print $1}' |awk BEGIN{RS=EOF}'{gs ...
- JS底层挖掘
//Promise版本的Ajaxconst getJSON = function(url) { const promise =new Promise(function(resolve, reject) ...
- JS常见内置对象和方法
JS中常用的内置对象:Array对象.Date对象.正则表达式对象.string对象.Global对象 Array对象中常用方法: concat() 表示把几个数组合并成一个数组join() 设 ...