2019年7月1日 星期一

Python Flask 解決內網啟動很慢

發現 IP 設成192.168.x.y 時,啟動FLASK 的時間會多30秒


查python code 發現卡在socket.py 的getfqdn 裡面,該method 內容如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def getfqdn(name=''):
    """Get fully qualified domain name from name.
 
    An empty argument is interpreted as meaning the local host.
 
    First the hostname returned by gethostbyaddr() is checked, then
    possibly existing aliases. In case no FQDN is available, hostname
    from gethostname() is returned.
    """
    name = name.strip()
    if not name or name == '0.0.0.0':
        name = gethostname()
    try:
        hostname, aliases, ipaddrs = gethostbyaddr(name)
    except error:
        pass
    else:
        aliases.insert(0, hostname)
        for name in aliases:
            if '.' in name:
                break
        else:
            name = hostname
    return name
程式會卡在第14行的gethostbyaddr

推測原因是gethostbyaddr 他會發封包丟到name 的位置,反查真正的hostname 及ipaddrs  
在ARM Linux 無自帶mDNS功能的情況下,hostname 轉換IP靠的是DHCP server
但手動綁IP的情況下,無DHCP server ,hostname 自然無作用
對照到此時在系統上自ping hostname 是卡住的

實驗1:
設置DHCP IP時,將input name = '172.16.6.114'
gethostbyaddr(name) 回傳的內容
hostname = myarm.google.com
aliases = [] 
ipaddrs = ['172.16.6.114']
最後return 內容為 myarm.google.com

實驗2:
設置DHCP IP時,將input name = '0.0.0.0'
會先gethostname() 取得myarm
然後 gethostbyaddr 會failed
直接return myarm.google.com

不過此段code 很奇怪, gethostbyaddr 回傳的三個參數 卻是在else 的分支處理才用到
查到python的try 結構有else 語法,也就是成功取得回傳的三個參數就會進到第一個else 處理資料

完整的Try-catch架構

Try-catch的完整結構應該是這樣:try, except, else, finally
try:需要被監控是否會出錯的程式區塊
except:出了哪種錯誤,要有怎樣相對應的處理
else:都沒錯誤,就會執行此區塊的程式
finally:不論如何都會執行此區塊的程式

第二個else 則是搭配for的
查到python 的for 搭配else , 等於會接著執行
所以跳出for 就會執行name = hostname

最後是直接把try - except 四行code 註解掉,即可解決
因為目前的用法,都是輸入input name = '0.0.0.0' , 會終還是回傳hostname
那就不要浪費時間去呼叫gethostbyaddr

沒有留言:

張貼留言

NoSQL Redis intro

Redis是一個使用ANSI C編寫的開源、支援網路、基於記憶體、可選永續性的鍵值對儲存資料庫。 支援rdb 及aof 兩種儲存方式 From  https://zh.wikipedia.org/wiki/Redis Redis 目前擁有兩種資料...