Hello!
2014-05-19 2:55 GMT-07:00 Evil Mybliss:
> 我在通过lua来计算body_bytes_sent值时, 发现得出的值与机器流量相差很大.
> 机器上显示流量只有60-70Mb的样子, 可我这个统计出来单个域名就达到了1个G..
>
你应当交待一下你所说的“机器流量”具体的统计方法。毕竟有很多不同的统计方法。
> 下面是我的存字典的代码:
你的这段代码是放在什么上下文中的?
它应当放在 log_by_lua* 这样的上下文中。如果放在 body_filter_by_lua
中的话,则会重复统计,结果会比实际值大很多倍。毕竟对于单个请求而言,body filter 可能会被调用多次。
> local body_size = ngx.var.body_bytes_sent
> local time = ngx.time() - ngx.time() % 300
> local domain = ngx.var.host
> local tf_key = domain .. "/" .. SerialNub .. "/" .. time
> local total_size = log_dict:get(tf_key) or 0
> total_size = total_size + body_size
> log_dict:set(tf_key, total_size)
>
上面的 Lua 代码有一个明显的错误是你使用 get() 和 set() 这两个分开的调用来做累加。这两个调用中间并没有原子保护,所以你在
set() 之前由 get() 得到的值很可能已经被其他 nginx worker 进程改写了。正确的做法是使用 incr()
这一个调用,它可以保证原子性:
https://github.com/openresty/lua-nginx-module#ngxshareddictincr
另外,我不清楚你这里使用 SerialNum 和 time 作 key 的动机。
一个建议是先使用最简单的 Lua/nginx 例子和你自己设计的请求来测试你的 Lua 代码,这样方便调试你 Lua 代码里的低级错误。
你这里使用的 $body_bytes_sent 变量是 nginx 核心计算其值,ngx_lua 模块只是暴露接口而已。这个变量在
nginx 用户群中的使用极为广泛,出问题的可能性很低。
> 不知道代码统计是否有问题?
见上。
> 我这个机器上启动的了4个worker.
> 然后我搜索看到章老师说关于nginx多个进程是独自的累加器, 是否跟这个有关系呢?
>
我觉得你应该是断章取义了。你这里使用的共享内存字典 lua_shared_dict 是所有 worker
进程共享的内存区域。你看到的我之前说的独立累加器的建议应当是针对性能优化的,即当每个 worker 使用自己专用的
lua_shared_dict 时,各个 worker 访问自己的区域时锁的开销可以实现最小化。
Regards,
-agentzh