Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

查询时内存不断增长--内存泄露 #6

Closed
spyth opened this issue Jun 7, 2018 · 8 comments
Closed

查询时内存不断增长--内存泄露 #6

spyth opened this issue Jun 7, 2018 · 8 comments

Comments

@spyth
Copy link

spyth commented Jun 7, 2018

Hi,不知道是不是调用的方式不对,查询的时候内存会一直不断增长。

下面是我写的脚本,可以重现。
环境是:CentOS 7.5.1804, openresty/1.13.6.2

-- test.lua
local geoip = require("resty.maxminddb").new("/usr/local/share/GeoIP/GeoLite2-Country.mmdb")
for i = 1, 200000 do
  local ip = string.format("%s.%s.%s.%s", math.random(1, 255), math.random(1, 255), math.random(1, 255), math.random(1, 255))
  local res, err = geoip:lookup(ip)
  if res and res.country and res.country.iso_code then
    print(i, res.country.iso_code)
  end
end

$ resty test.lua

@anjia0532
Copy link
Owner

如果内存匀速增长的话,可能是内存泄露了,你可以通过火焰图来看看。

@anjia0532
Copy link
Owner

ping @spyth ,你是通过resty-cli来测试的?有没有尝试用最新的openresty+ab/wrk/jmeter等进行测试?

@spyth
Copy link
Author

spyth commented Jun 22, 2018

pong @anjia0532 ;
一开始是在生产环境的 openresty 上发现的,上线了几个钟服务器就内存爆了重启。openresty 是最新版本。我没有用 ab 去测试,不过有简单写了个脚本发模拟请求就复现了。
上面的脚本我之前有生成了个火焰图 perf.svg.zip,不知道生成的对不对。

@anjia0532
Copy link
Owner

真是不太好意思,最近一段时间比较忙,并且后来我们换用了ipip.net的ip库,所以就不怎么用maxminddb了。不过看你的火焰图不太明显,最好是新起一个openresty(排除其他因素的影响),只通过ab/wrk压测ip(ip最好是随机ip,防止ip缓存),并记录火焰图,可以看出瓶颈在哪。

同时,根据你的描述,应该是内存泄露.可以通过春哥开源的 https://github.com/openresty/stapxx#sample-bt-leakshttps://github.com/openresty/openresty-systemtap-toolkit#ngx-leaked-pools 进行调试。

或者如果你不是很着急的话也可以等我稍后有空的时候再跟踪此问题。

@znikang
Copy link

znikang commented Jul 3, 2018

MMDB_get_entry_data_list . 沒有 release

entry_data_list

extern void MMDB_free_entry_data_list(MMDB_entry_data_list_s *const entry_data_list);
補進流程上 就會清 memory 了

anjia0532 added a commit that referenced this issue Jul 3, 2018
@anjia0532 anjia0532 changed the title 查询时内存不断增长 查询时内存不断增长--内存泄露 Jul 3, 2018
@anjia0532
Copy link
Owner

anjia0532 commented Jul 3, 2018

@znikang 感谢指点,开始我也以为是未进行垃圾回收导致的(我是java程序员。。。) 但是加了回收后(参考 https://github.com/maxmind/libmaxminddb/blob/master/doc/libmaxminddb.md#mmdb_free_entry_data_list ),依然存在内存泄露问题,后来根据火焰图分析,发现核心问题是不断初始化导致的问题。不是指针未回收。据此将对象重用即可解决。通过

cat server.conf
server {
    listen 80;
    server_name 127.0.0.1;
    location / {
        content_by_lua_block{
            local cjson = require 'cjson'
            local geo = require 'resty.maxminddb'
            if not geo.initted() then
                geo.init("/path/to/GeoLite2-City.mmdb")
            end
            local res,err = geo.lookup(ngx.var.arg_ip or ngx.var.remote_addr) --support ipv6 e.g. 2001:4860:0:1001::3004:ef68

            if not res then
                ngx.log(ngx.ERR,'failed to lookup by ip ,reason:',err)
            end
            ngx.say("full :",cjson.encode(res))
            if ngx.var.arg_node then
               ngx.say("node name:",ngx.var.arg_node," ,value:", cjson.encode(res[ngx.var.arg_node] or {}))
            end
        }
    }
}
cat test.lua
wrk.method = "GET";
wrk.body = "";

logfile = io.open("wrk.log", "w");

request = function()
ip = tostring(math.random(1, 255)).."."..tostring(math.random(1, 255)).."."..tostring(math.random(1, 255)).."."..tostring(math.random(1, 255))
path = "/?ip=" .. ip
return wrk.format(nil, path)
end

response = function(status,header,body)
logfile:write("\nbody:" .. body .. "\n-----------------");
end
wrk -t10 -c10 -d60s -s ./test.lua --latency http://127.0.0.1

docker run --rm  -v `pwd`:/data williamyeh/wrk -s test.lua --latency  http://127.0.0.1

内存一直保持在0.x%-1%左右

附件是0.4和0.5的火焰图对比。

maxmind_flame.zip

@spyth 你可以用0.5的测一下

@znikang
Copy link

znikang commented Jul 3, 2018

呵呵 把它放在 lua init 搞定了

@anjia0532
Copy link
Owner

@znikang 恩,放在 init_by_lua*也可以,是我在readme.md里写的demo误导了大家。

            local geo = require 'resty.maxminddb'
            if not geo.initted() then
                geo.init("/path/to/GeoLite2-City.mmdb")
            end

适用性更强一些,既可以放到init 初始化 ,也可以在access_by_lua,log_by_lua,content_by_lua处直接使用。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants