openresty是一个http服务器,并内置了Lua,可以利用lua代码进行处理http请求.

  • 如下配置文件记录了客户端访问Nginx服务器时,nginx的log中记录了url中的project参数,以及访问时间,来访者的真实IP, 以及请求时的其他信息
  • 其中对project,时间,ip利用lua代码进行了处理,将其通过lua的table结果进一步转化为json形式,然后进一步加密.存储在access_log中.
  • access_log的存储路径定在logs目录下,格式在http块中通过log_format指令定义,格式名称为collect-app-log-format.格式$cad的具体定义在lua代码块中定义. 因为通过lua代码对获取的信息进行了一定的处理,比如编译成json,加密,连接等等.

配置文件

# main-nginx.conf
# nginx 用户和组
user root root;
# work进程数,
worker_processes 4;
# 错误日志路径,和日志级别    
error_log logs/collect-app-error.log error;
# nginx pid文件
pid       logs/collect-app-nginx.pid;
# 单个worker最大打开的文件描述符个数
worker_rlimit_nofile 65535;
events
{
	#使用epoll模型, 一个优化策略
	use epoll;
	# 单个worker进程允许的最多连接数
	worker_connections 65535;
}
http
{
	include mime.types;
	default_type application/octet-stream;
	gzip on;
    # 指定压缩的最小字节数
	gzip_min_length 1k;
    # 16k是 缓冲的单位,4是倍数,可以是其他值作为倍数
	gzip_buffers 4 16k;
	gzip_http_version 1.0;
    # 压缩等级
	gzip_comp_level 2;
    # 可以压缩的文件类型
	gzip_types text/plain application/x-javascript text/css application/xml;
    #启用应答头"Vary: Accept-Encoding"
	gzip_vary on;
    # 参数中的下划线是否忽略,on表示忽略
	underscores_in_headers on;
	log_format main
		'$remote_addr - $remote_user [$time_local] '
		'$request_length '
		 '"$request" $status $bytes_sent $body_bytes_sent '
		'"$http_referer" "$http_user_agent" '
		'"$gzip_ratio" "$request_time" '
		'"$upstream_addr" "$upstream_status" "$upstream_response_time"';
	# 定义我们数据采集的 access 日志格式
	log_format collect-app-log-format '$cad';   
	open_log_file_cache max=1000 inactive=60s;
	keepalive_timeout 0;
	client_max_body_size 20m;
	include /opt/apps/collect-app/conf/vhost/*.conf;
}

解释:
user root root; 这个user是关键词root为用户名称,后一个root为用户组.
worker_processes 4; 线程多了工作更快
worker_connections 65535; 可以看到nginx的并发能力. 允许有这么多的连接.
error_log logs/collect-app-error.log error; 设定errorlog的存储位置以及日志级别. 级别越高,输出的信息越多.
pid logs/collect-app-ngix.pid; 设置pid文件的存储位置
worker_rlimit_nofile 65535;单个worker打开的最大的文件描述符的格式
include mime.types; 引入这个文件.
log_format collect-app-log-format '$cad'; 这里并没有定义日志的格式,只是引入了一个变量
include /opt/apps/collect-app/conf/vhost/*.conf; 利用include指令引入外部配置文件.

#minor.conf
server {
    #listen命令设置nginx监听地址,对于IP协议,这个地址就是address和port
    listen  8802 default_server;
    # lua_need_request_body on;
    #设置网页上传文件的最大值
    client_max_body_size 5M;
    #Nginx分配给请求数据的Buffer大小,如果请求的数据小于client_body_buffer_size直接将数据先在内存中存储
    client_body_buffer_size 5M;
    #Nginx 的 location 实现了对请求的细分处理,有些 URI 返回静态内容,有些分发到后端服务器等,
    #没有修饰符 表示:必须以指定模式开始
    #=表示:必须与指定的模式精确匹配
    #~ 表示:指定的正则表达式要区分大小写
    #~* 表示:指定的正则表达式不区分大小写

    location /data/v1 {
        set $cad  '';
        #content_by_lua是内容处理器,接受请求并输出响应,适用于location、location if。
        #通过针对特定 url 的请求,用 lua 脚本完成业务,避免请求打到后端应用服务器、Redis、MySQL;
        content_by_lua_block {
        -- cjson模块
              --相当于import
              local cjson = require "cjson"
              -- 读取请求体信息
              ngx.req.read_body()
              -- 请求体信息存放到 body_data变量中
              local body_data = ngx.req.get_body_data()
              -- 如果请求体为空,返回错误
              if body_data == nil  then
              --say就是打印的意思
                ngx.say([[{"code":500,"msg":"req body nil"}]])
                return
              end
              -- 定义当前时间 ngx.now方法返回当前时间,单位/s
              local current_time = ngx.now()*1000
              -- 请求的URL project参数中获取其值
              local project = ngx.var.arg_project
              -- 定义一个字典,存放有当前服务为日志增加的信息,如ctime表示接受到请求的时间,ip地址等
              --table 是 Lua 的一种数据结构用来帮助我们创建不同的数据类型,如:数组、字典等。
              --表是Lua特有的功能强大的东西。最简单的构造函数是{},用来创建一个空表
              local data={}
              data["project"] = project
              data["ctime"] = current_time
              if ngx.var.http_x_forwarded_for == nil then
              --remote_addr代表客户端的IP,但它的值不是由客户端提供的,而是服务端根据客户端的ip指定的,当你的浏览器访问某个网站时,假设中间没有任何代理,那么网站的web服务器(Nginx,Apache等)就会把remote_addr设为你的机器IP
                data["ip"] = ngx.var.remote_addr;
              else
                data["ip"] = ngx.var.http_x_forwarded_for
              end
              -- 将增加的信息编码为json
              local meta = cjson.encode(data)
              -- 将编码的json信息做base64 和 body_data拼接
              --nginx中ngx.unescape_uri()函数会将+字符转成空格,
              local res = ngx.encode_base64(meta) .. "-" .. ngx.unescape_uri(body_data)
              -- 将数据赋值给我们定义的nginx变量cad中,我们定义的log_format就使用这个变量的值
              ngx.var.cad = res
              ngx.say([[{"code":200,"msg":"ok"}]])
    }
        #the access_log directive sets the path, format and buffer size for the access log file.
        access_log  logs/collect-app-access.log  collect-app-log-format;
    }
}

测试,当访问服务器时nginx就会收集到相关信息.也可以通过curl模拟访问.
curl是一个linux命令,-X指定访问形式,get 或者post 后面是访问的地址.-d参数表示提交的数据.

curl -X POST 'http://localhost:8802/data/v1?project=news' -d  helloworld 
{"code":200,"msg":"ok"}