resty.upload使用中经常把cpu跑到100%

96 views
Skip to first unread message

pengm...@163.com

unread,
Apr 15, 2023, 3:14:04 AM4/15/23
to open...@googlegroups.com
代码如下
local upload = require 'resty.upload'

function _M:form_upload(dir_path)
    local chunk_size = 4096
    local form, err = upload:new(chunk_size)
    if not form then
        return nil
    end
    form:set_timeout(400000)
    local file
    if not dir_path then
        dir_path = '/etc/www/xx/'
    end
    local filenames = {}
    while true do
        local typ, res, err = form:read()
        if not typ then
            return nil
        end
        if typ == 'header' then
            if res[1] and res[1] == 'Content-Disposition' then
                local filename = get_file_name(res)
                if filename then
                    local t_res = os.execute('cd ' .. dir_path)
                    if t_res ~= 0 and t_res ~= true then
                        os.execute('mkdir ' .. dir_path)
                    end
                    file = io.open(dir_path .. filename, "w+")
                    if not file then
                        print("failed to open file " .. filename)
                        return
                    end
                    table.insert(filenames, filename)
                end
            end
        elseif typ == 'body' then
            if file then
                file:write(res)
            end
        elseif typ == 'part_end' then
            if file then
                file:close()
                file = nil
            end
        elseif typ == 'eof' then
            break
        end
    end
    return filenames
end

这上面的代码看不出有什么问题,上传的文件最大不超过3M,ngx worker偶尔在100%的状态卡几分钟,偶尔要几少时。
这上面的使用有什么问题吗,请各位大佬不吝赐教。

Carl Huang

unread,
Apr 15, 2023, 4:40:35 AM4/15/23
to open...@googlegroups.com

這段代碼中有幾個阻塞性操作。阻塞性操作是指在等待某個操作完成期間,程序無法繼續執行其他任務的操作。這些操作包括:

  1. form:read():這個函數讀取上傳文件的一部分,直到遇到文件的末尾。如果上傳速度較慢,這可能會花費較長的時間。

  2. os.execute('cd ' .. dir_path):此函數會將當前工作目錄更改為指定的目錄。在執行此操作時,程序可能會被阻塞。

  3. os.execute('mkdir ' .. dir_path):此函數會在文件系統中創建一個新目錄。根據文件系統的性能,這可能需要一定的時間,導致程序阻塞。

  4. io.open(dir_path .. filename, "w+"):此函數會打開一個文件,以便將上傳的數據寫入其中。如果操作系統過於繁忙,文件打開操作可能需要一定的時間,導致程序阻塞。

  5. file:write(res):這個函數將上傳的數據寫入文件。這可能需要一定的時間,特別是當要寫入的數據量較大或磁盤性能較差時,導致程序阻塞。


pengm...@163.com <pengm...@163.com>於 2023年4月15日 週六,下午3:14寫道:
--
--
邮件来自列表“openresty”,专用于技术讨论!
订阅: 请发空白邮件到 openresty...@googlegroups.com
发言: 请发邮件到 open...@googlegroups.com
退订: 请发邮件至 openresty+...@googlegroups.com
归档: http://groups.google.com/group/openresty
官网: http://openresty.org/
仓库: https://github.com/agentzh/ngx_openresty
教程: http://openresty.org/download/agentzh-nginx-tutorials-zhcn.html
---
您收到此邮件是因为您订阅了Google网上论坛上的“openresty”群组。
要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到openresty+...@googlegroups.com
要在网络上查看此讨论,请访问https://groups.google.com/d/msgid/openresty/2023041515133663760310%40163.com
--

------------------------------------------------------

卡爾國際資訊有限公司

黃奕璽   Carl Huang

行動電話:0973126602

E-Mail:ca...@cii.com.tw

統一編號:61776594

地址:新北市新莊區新北大道4段185號5樓

------------------------------------------------------




pengm...@163.com

unread,
Apr 15, 2023, 5:57:13 AM4/15/23
to open...@googlegroups.com
确实存在阻塞操作,但这一段代码并没有出现死循环的可能对吗。
现在我遇到的问题,表现确实不像是遇到了死循环,因为卡住的worker会在一段时间(可能有几小时)后自行退出。
但是对于写文件来说,这几个操作似乎也并没有如此耗时。
可能较耗时的是否在form:read(),代码中timeout设置在了400000ms,chunk_size为4096。比如一个文件最大约为2-3M,从sock中读取一段chunk_size的数据,最坏的可能就是400000ms,在保持连接的情况下读完整个2-3M则要消耗非常长的时间,请问我这样的理解是准确的吗。
偶尔能在accesslog中,发现耗时几千秒的日志。


 
发件人: Carl Huang
发送时间: 2023-04-15 16:40
收件人: openresty
主题: Re: [openresty] resty.upload使用中经常把cpu跑到100%

Junlong Li

unread,
Apr 15, 2023, 7:42:39 AM4/15/23
to openresty
local t_res = os.execute('cd ' .. dir_path)
                    if t_res ~= 0 and t_res ~= true then
                        os.execute('mkdir ' .. dir_path)
                    end
os.execute 是很昂贵的操作,可以试用lfs模块代替这些os的操作。

可以申请 OpenResty XRay 来分析这个CPU 100%的问题。

彭密

unread,
Feb 20, 2024, 8:05:31 PMFeb 20
to open...@googlegroups.com

很长时间忘了回复,cpu跑到100%的原因是死循环clone系统调用导致的,clone执行时间稍长就有可能被信号中断,中断后又会重新执行,陷入循环。信号是由timer_resolution控制发出的,所以我把timer_resolution去掉就没再出现过了。

Reply all
Reply to author
Forward
0 new messages