Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Nginx+lua+mysql实时存日志

Nginx+lua+mysql实时存日志

作者头像
YG
发布于 2018-05-23 09:05:58
发布于 2018-05-23 09:05:58
2.4K00
代码可运行
举报
文章被收录于专栏:YG小书屋YG小书屋
运行总次数:0
代码可运行

准备材料

安装

  • LuaJIT 安装
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
tar -zxf LuaJIT-2.0.5.tar.gz
  cd LuaJIT-2.0.5
  make
  make install PREFIX=/home/myself/lj2
 
  • pcre 安装
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  tar -zxvf pcre-8.32.tar.gz
  cd pcre-8.32
  make
  make install 
  • Nginx 安装
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
export LUAJIT_LIB=/path/to/luajit/lib   
export LUAJIT_INC=/path/to/luajit/include/luajit-2.1   
./configure --prefix=/opt/nginx \        
--with-ld-opt="-Wl,-rpath,/path/to/luajit-or-lua/lib" \        
--add-module=/path/to/ngx_devel_kit \        
--add-module=/path/to/lua-nginx-module   
make   
make install
 

配置文件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
user  root;
worker_processes  2;

events {
worker_connections  1024;
}


http{
lua_package_path "/home/oicq/guomm/nginx_lua/lua-resty-mysql-master/lib/?.lua;;"; 
lua_shared_dict logs 10m;
#初始化worker进程,在这个进程中递归调用put_log_into_mysql函数,达到一种类似于crontab的功能
init_worker_by_lua_block {
    local delay = 10
    function put_log_into_mysql(premature)      
            local mysql = require "resty.mysql"
            local db, err = mysql:new()
            if not db then
                ngx.log(ngx.ERR,"failed to instantiate mysql: ", err)
                return
            end

            db:set_timeout(1000)
            local ok, err, errcode, sqlstate = db:connect{
                host = "xxx",
                port = 3306,
                database = "database_name",
                user = "username",
                password = "password",
                charset = "utf8",
            }

            if not ok then
                ngx.log(ngx.ERR,"failed to connect: ", err, ": ", errcode, " ", sqlstate)
                return
            end

            -- get data from shared dict and put them into mysql 从共享内存中读取出10s的日志,写入mysql
            local key = "logs"
            local vals = ""
            local temp_val = ngx.shared.logs:lpop(key)
            while (temp_val ~= nil)
            do
                vals = vals .. ",".. temp_val
                temp_val = ngx.shared.logs:lpop(key)
            end

            if vals ~= "" then
                vals = string.sub(vals, 2,-1)
                local command = ("insert into es_visit_record(access_ip,server_ip,access_time,run_time,es_response_time,request_body_byte,run_state,url,post_data) values "..vals)
                ngx.log(ngx.ERR,"command is ",command)
                local res, err, errcode, sqlstate = db:query(command)
                if not res then
                    ngx.log(ngx.ERR,"insert error: ", err, ": ", errcode, ": ", sqlstate, ".")
                    return
                end
            end

            local ok, err = db:close()
            if not ok then
                ngx.log(ngx.ERR,"failed to close: ", err)
                return
            end
            -- decycle call timer to run put_log_into_mysql method, just like crontab
            local ok, err = ngx.timer.at(delay, put_log_into_mysql);
            if not ok then
                ngx.log(ngx.ERR, "failed to create timer: ", err)
                return
            end
    end
    
    local ok, err = ngx.timer.at(delay, put_log_into_mysql)
    if not ok then
        ngx.log(ngx.ERR, "failed to create timer: ", err)
        return
    end
}


upstream elasticsearch_servers {
    server xxx max_fails=3 fail_timeout=30s;
    server xxx max_fails=3 fail_timeout=30s;
    server xx max_fails=3 fail_timeout=30s;
}

log_format  porxy  '$remote_addr,$upstream_addr,[$time_local],$request,$request_body,$status,$body_bytes_sent,$request_time,$upstream_response_time';

server {
    listen 9202;
    location / {
        
        proxy_pass http://elasticsearch_servers;
        #在log_by_lua_block中将日志存入Nginx共享内存
        log_by_lua_block{

            local currentTime = os.date("%Y-%m-%d %H:%M:%S", os.time())
            currentTime = "\"" .. currentTime .. "\""
            
            local req_body = '-'
            if ngx.var.request_body then
                req_body = ngx.var.request_body
                req_body = string.gsub(req_body,"\n","")
                --req_body = string.gsub(req_body,"\t","")
            end
            req_body = "\"" .. req_body .. "\""

            local req_status = 0
            if ngx.var.status then
                req_status = ngx.var.status
            end

            local req_time = 0
            if ngx.var.request_time then
                req_time = ngx.var.request_time
            end
            
            local req_req = "\"" .. ngx.var.request .. "\""
            local remote_addr = "\"" .. ngx.var.http_x_forwarded_for .. "\""
            local server_addr = "\"" .. ngx.var.upstream_addr .. "\""
            local myparams = ("("..remote_addr..",".. server_addr..","..currentTime..","..ngx.var.request_time .. ",".. ngx.var.upstream_response_time..","..ngx.var.body_bytes_sent..","..ngx.var.status..","..req_req..","..req_body..")")
            local key = "logs"
            local len,err = ngx.shared.logs:rpush(key, myparams)
            
            if err then
                ngx.log(ngx.ERR,"failed to put log vals into shared dict")
                return
            end
            
        }
    }
    access_log logs/es_access.log porxy;
}
}

应用场景和日志文件解析

本配置主要解决Nginx向mysql中实时插入日志的问题。

  1. 刚开始的时候看了Nginx和mysql的连接模块。比如说nginx-mysql-module,可以连接mysql。但是插入日志时遇到问题,我们知道nginx的执行过程先是location解析并重写阶段,然后是访问权限控制阶段,接着是内容生成阶段,最后是日志记录阶段。mysql访问阶段属于内容生成阶段,所以代理运行的时间和状态,mysql都无法获取的到。因此,这种通过nginx直连mysql的方式无法达到我们的要求。
  2. 通过lua脚本在日志生成阶段获取信息,然后将数据插入mysql。nginx有一个限制,无法在log阶段访问socket即无法访问mysql,所以无法在log阶段直接将数据存入mysql。但是可以通过运行包含mysql操作的shell脚本来解决这个问题。但是这个方法有两个弊端:
    1. 获取到Nginx代理的结果后,每次都要连接mysql并向其插入数据。当并发量大时,mysql端会出现问题。
    2. 不向mysql插入数据,整个时间的消耗大约在0.02-0.04s之间。而向mysql插入数据后,整个时间消耗大约在0.4-0.9之间,消耗的时间是原来的10倍。
  3. 通过lua + ngx.time.at + lua_mysql + lua.share.dict 解决问题。整个过程如下所示:
    1. 在nginx启动阶段,ngx.time.at启动一个延时任务。在任务中,每隔一段时间取出nginx内存共享区的log数据,将数据合并,存入mysql,同时再一个相同的延时任务,递归调用。这样就与crontab命令相似。当定时器到期,定时器中的 Lua 代码是在一个“轻线程”中运行的,它与创造它的原始请求是完全分离的,因此不存在大量线程同时运行的情况。
    2. 在日志生成阶段,将数据封装并存入nginx的内存共享区。

Mysql 访问权限的问题

不但访问Mysql的Mysql用户需要有操作对应数据库的权限,还需要调用Mysql命令的用户具有访问mysql的权限。授权命令如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
GRANT ALL PRIVILEGES ON *.* to root@xxx IDENTIFIED BY 'password';

Mysql 编码类型

总的来说,Mysql的数据库对应三种编码。Mysql客户端显示数据的编码,连接Mysql用的编码(即数据存入mysql时,数据的编码),Mysql存储用的编码(字段,表,数据库三种格式可能不同)。不管Mysql存储用的编码是什么,只要Mysql客户端显示数据的编码和连接Mysql用的编码相同,数据就能通过mysql客户端正确显示。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017.09.05 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Nginx Lua扩展模块
淘宝开发的 ngx_lua 模块通过将 Lua 解释器集成进 Nginx,可以采用 Lua 脚本实现业务逻辑,由于 Lua 的紧凑、快速以及内建协程,所以在保证高并发服务能力的同时极大地降低了业务逻辑实现成本。
用户9615083
2022/12/25
3.7K0
Nginx Lua扩展模块
7.Nginx实践之使用Lua-nginx模块脚本连接Redis数据库读取静态资源并隐式展现
本章目录 [TOC] 0x00 前言简述 为啥有此篇文章? 描述: 在进行公司的图片存储解决方案研究中,最开始准备使用的是FastDFS,但是经过深思熟虑,以及后期运维成本考虑还是放弃了,只能转而使用
全栈工程师修炼指南
2022/09/29
3.1K1
7.Nginx实践之使用Lua-nginx模块脚本连接Redis数据库读取静态资源并隐式展现
Nginx与Lua
火云邪神语录:天下武功,无坚不破,唯快不破!Nginx的看家本领就是速度,Lua的拿手好戏亦是速度,这两者的结合在速度上无疑有基因上的优势。
LA0WAN9
2021/12/14
5160
玩转 Nginx 之:使用 Lua 扩展 Nginx 功能
1、Nginx 简介 Nginx 作为一款面向性能设计的HTTP服务器,相较于Apache、lighttpd具有占有内存少,稳定性高等优势。其流行度越来越高,应用也越来越广泛,常见的应用有:网页服务器、反向代理服务器以及电子邮件(IMAP/POP3)代理服务器,高并发大流量站点常用来做接入层的负载均衡,还有非常常见的用法是作为日志采集服务器等。 Nginx 整体采用模块化设计,有丰富的模块库和第三方模块库,配置灵活。其中模块化设计是nginx的一大卖点,甚至http服务器核心功能也是一个模块。要注意的是:n
用户1177713
2018/02/24
22.6K0
玩转 Nginx 之:使用 Lua 扩展 Nginx 功能
OpenResty + Lua + Kafka 实现日志收集系统以及部署过程中遇到的坑
********************* 部署过程 **************************
小勇DW3
2019/08/05
3.3K0
OpenResty + Lua + Kafka 实现日志收集系统以及部署过程中遇到的坑
实战:使用lua脚本在nginx层解决高并发访问问题
公司产品最近出了一个需求,说需要进行ABtest进行自动切换页面投放,因为页面本身挺复杂,动态性比较大很多数据都在后台返回的。所以本来想着挺简单的需求,直接通过网关动态进行转发就ok~
小草飞上天
2024/12/25
3550
实战:使用lua脚本在nginx层解决高并发访问问题
通过Nginx/Lua给Redis的PIPELINING减肥
某手机应用市场项目,其中请求量最大的功能是查询升级接口,具体点来说:客户端会不定期的把手机中应用名称及其应用版本发送到服务端,服务端通过比较版本来判断客户端的应用是否需要升级,如果需要就返回若干项相关信息。通常,一台手机里会装几十个到上百个应用不等,当海量客户端一起请求时,服务端的压力可想而知。
LA0WAN9
2021/12/14
3520
自学成菜-openrestry(1)
nginx可以定义日志精选的几个变量 http://www.xxx.com/test/a?a=1&age=1 location /test { default_type text/html;
用户2825413
2019/07/16
1.2K0
自学成菜-openrestry(1)
openresty+lua+kafka方案与Tomcat接口并发度对比分析
  之前的项目基于nginx反向代理后转发到Tomcat的API接口进行业务处理,然后将json数据打入kafka中,但是随着业务的扩大,访问量越来越大,并发数也很高,导致程序遇到性能问题;
小勇DW3
2019/08/20
1.4K0
接入层限流之OpenResty提供的Lua限流模块lua-resty-limit-traffic
【转载请注明出处】:https://cloud.tencent.com/developer/article/1625480
后端老鸟
2020/05/09
2.1K0
接入层限流之OpenResty提供的Lua限流模块lua-resty-limit-traffic
【Nginx】实现负载均衡、限流、缓存、黑白名单和灰度发布,这是最全的一篇了!
作者个人研发的在高并发场景下,提供的简单、稳定、可扩展的延迟消息队列框架,具有精准的定时任务和延迟队列处理功能。自开源半年多以来,已成功为十几家中小型企业提供了精准定时调度方案,经受住了生产环境的考验。为使更多童鞋受益,现给出开源框架地址:
Bug开发工程师
2020/07/24
8420
【Nginx】实现负载均衡、限流、缓存、黑白名单和灰度发布,这是最全的一篇了!
openresty基于lua/geoIp/redis实现ip限制
一、问题背景二、聊一嘴ip库三、解决方案四、下载安装openresty五、验证效果六、geoIp自动更新七、参考
叔牙
2023/02/26
4.4K0
openresty基于lua/geoIp/redis实现ip限制
高级技巧:利用Lua编写安全场景的测试数据生成工具
在上述架构中,交换机通过流量镜像的方式,将用户与应用服务器之间的流量“复制”给流量采集/分析服务器。流量服务器上部署的采集探针负责协议数据包的重组,以及一部分流量分析工作,比如判断数据包是否触发某些规则。此时,需要对流量采集探针进行两方面的测试工作:
小阑本阑
2023/08/11
4640
高级技巧:利用Lua编写安全场景的测试数据生成工具
Nginx + Lua搭建文件上传下载服务
本文介绍了Nginx在文件上传、下载以及大文件断点续传功能中的实践应用,同时介绍了一些与文件操作相关的系统调用和Lua模块的扩展用法。此外,还探讨了如何使用Nginx和Lua实现简单的文件下载服务和基于TCP的RPC调用。
庄进发
2017/04/20
6.4K0
Nginx + Lua搭建文件上传下载服务
Nginx基础 - Nginx+Lua实现灰度发布与WAF
1.Nginx加载Lua环境 默认情况下Nginx不支持Lua模块, 需要安装LuaJIT解释器, 并且需要重新编译Nginx, 建议使用openrestry
子润先生
2021/08/03
1.7K0
Nginx缓存解决方案:SRCache
前些天帮别人优化PHP程序,搞得灰头土脸,最后黔驴技穷开启了FastCGI Cache,算是勉强应付过去了吧。不过FastCGI Cache不支持分布式缓存,当服务器很多的时候,冗余的浪费将非常严重,此外还有数据一致性问题,所以它只是一个粗线条的解决方案。
LA0WAN9
2021/12/14
4290
Nginx缓存解决方案:SRCache
Openresty能帮我们做什么
OpenResty 是一个强大的 Web 应用服务器,Web 开发人员可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,更主要的是在性能方面,OpenResty可以 快速构造出足以胜任 10K 以上并发连接响应的超高性能 Web 应用系统。
品茗IT
2023/10/22
4760
Openresty能帮我们做什么
Lua+OpenResty快速入门
Lua是一种轻量、小巧的脚本语言,用标准C语言编写并以源代码形式开发。设计的目的是为了嵌入到其他应用程序中,从而为应用程序提供灵活的扩展和定制功能。
大忽悠爱学习
2022/05/11
2.3K0
Lua+OpenResty快速入门
通过openresty+lua+nginx实现nginx缓存机制
OpenResty是一个基于Nginx的高性能Web应用服务器,它集成了Lua脚本语言,可以使用Lua编写Nginx模块,从而实现更多的高级功能。在本篇博客中,我们将介绍如何使用OpenResty和Lua来实现缓存机制。
司夜
2023/03/31
1.2K0
一文从原理到实践教你使用Nginx_lua实现WAF
过去企业通常会采用防火墙,作为安全保障的第一道防线;当时的防火墙只是在第三层(网络层)有效的阻断一些数据包;而随着web应用的功能越来越丰富的时候,Web服务器因为其强大的计算能力,处理性能,蕴含较高的价值,成为主要的被攻击目标(第七层应用层)而传统防火墙在阻止利用应用程序漏洞进行的攻击方面,却没有办法;在此背景下,WAF(Web Application Firewall)应运而生。
公众号: 云原生生态圈
2022/02/16
2.8K0
推荐阅读
相关推荐
Nginx Lua扩展模块
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验