2011年12月31日 星期六

阿班私房菜- 初探 Networking debug Logging (網路偵錯日誌)

tcpdump-with-cap

(註: 筆者愛用 nc(netcat) + tcpdump 來做網路實驗,上圖即其結果。 )

記得許久前,某人問我一個問題,有比較好的遠端偵錯的方法嗎?

首先,我先定義所謂"遠端偵錯":
  • 無法利用即時偵錯
    • 你的程式可能在數百公里外執行。簡言之,你沒辦法到現場去查臭蟲。
    • 24X7伺服端程式,你不能停止它來使用單步偵錯。
筆者先談談針對網路相關問題偵錯心得:

排除法:先簡化錯誤發生的因素。

案例:某公司開發用伺服器上的網站,使用手機(Android Phone)或較慢的機器(如:Eeepc),時常發生連線逾時的情形;但手機連線至他站均無問題。
  • 先檢查,區網內的硬體是否有問題?(無線Access Point (AP)及Router 檢查,甚至網路線更換,無改善。)
  • 再查,AP的DNS是否有問題。(無發現)
  • 查看google 大神,是否Eeepc 網路卡有相容性問題。(無發現)
  • 拿出無敵大絕招,使用擷取網路封包方法。(注意:要擷取封包時,請同時抓取,Server 及 Client 端。)
    • Server 遠端使用tcpdump 擷取封包並儲存為Wireshark 可開啟的檔案.cap
    • Client 端使用Wireshark來擷取封包。
    • 在Client 重現連線網路問題。
    • 比對封包 (其中發現Server端收到3個SYN 封包,卻無回應到client 端)
    • 範圍縮小至Server端
    • 利netstat –na | grep TIME_WAIT‘ , 發現TCP TIME_WAIT 很快被系統移除。
小結:

  到此階段,筆者有很高的把握,應該是系統網路優化設定所造成。

再和朋友試一下,網路相關設定才發現與tcp_tw_recycle有關;關閉後一切正常。

$ grep recycle /etc/sysctl.conf
net.ipv4.tcp_tw_recycle=1   --> net.ipv4.tcp_tw_recycle=0


結論:

對於網路程式的偵錯而言,看懂封包的協定是十分必要的,
另外在撰寫網路相關的程式,若能瞭解所使用標準協定(如:TCP TimeWait RFC793, HTTP RFC2616),將有莫大的幫助,以避免所開發程式與其它第三方程式發生不相容情事。

(有任何誤謬,請不吝指正。)


2011年12月30日 星期五

阿班私房菜-Design Pattern(DP)初探使用Python (1)


Design Patterns: Elements of Reusable Object-Oriented Software

最近使用Python 寫程式,心血來潮,使用 (DP) 套用看看。
以 Factory worker 為例。
首先建立一個物件Worker 包含姓名、屬性等等。
class Worker:
    def __init__(self, name=None):
        self.name = capfirst(name) if name else "The worker"
    def getName(self):
        return self.name
    def attrib(self):        return "Worker"
    def lookandfeel(self):
        print "%s is a %s" % (self.name, self.attrib())

Designer與Engineer繼承它,並覆寫attrib() Method。
class Designer(Worker):
    def attrib(self):        return "Designer"
class Engineer(Worker):
    def attrib(self):        return "Engineer"

當使用各自物件來建立,並執行lookandfeel() 時,會呼叫各自的attrib method。
以下使用 factory pattern 來實作僱用workers 的容器物件。
# factory pattern
class Factory:
    type_designer = 1
    type_engineer = 2
    def __init__(self):
        self.workers = []
    def employ(self, worker_type, name=None):
        if worker_type == Factory.type_designer:
            self.workers.append(Designer(name))
        elif worker_type == Factory.type_engineer:
            self.workers.append(Engineer(name))
    def workerCount(self):
        return len(self.workers)
    def browse(self):
        for a in self.workers:
            a.lookandfeel()
z = Factory()
z.employ(Factory.type_designer)
z.employ(Factory.type_designer, 'bill')
z.employ(Factory.type_engineer, 'sue')
z.browse()

執行結果:
$ python factory_dp1.py
The worker is a Designer
Bill is a Designer
Sue is a Engineer

承上篇重構一文:我們來重構一下它,並加入singleton pattern(利用@staticmethod 來實作)。
class Factory:
    # class static variable
    type_designer = "1"
    type_engineer = "2"
    _Factoryself = None
    _factorydict = {
           type_designer: Designer,
           type_engineer: Engineer,
        }
    def __init__(self):
        self.workers = []

    @staticmethod
    def singleton():
        if Factory._Factoryself == None:
            Factory._Factoryself = Factory()
        return Factory._Factoryself



    def employ(self, worker_type, name=None):
        caller = Factory._factorydict.get(worker_type)
        if caller:
            self.workers.append(caller(name))
        return None



    def workerCount(self):
        return len(self.workers)

    def browse(self):
        i = 0
        for a in self.workers:
            print " - Worker[%s]:%s" % (i, a.getLookandfeel())
            i+=1

def main():
    f = Factory.singleton()
    f2 = Factory.singleton()
    if f == f2:
        print "* Singleton pattern of Factory"



    print "* Factory pattern to employ"
    f.employ(Factory.type_designer)
    f.employ(Factory.type_designer, 'Bill')
    f.employ(Factory.type_engineer, 'Sue')
    print "* Factory pattern to browse"
    f.browse()
    print "* The factory has %s workers." % f.workerCount()

if __name__ == "__main__":
    main()

小結

使用python 來寫DP程式,功能強大,自由度高;
但這意味,寫其程式時,要有其紀律,遵守一定規範(coding convention)來寫;
不然程式會變得非常難讀及維護。 最近上列範例程式均可在github-class_dp中找到。
上述範例還可進一步,重構或修改為工廠人員管理系統的雛形,留待有興趣的讀者們來添加!