firefly(暗黑世界版v1.4)教程(三)工具類

輔助工具相關(guān)的文件都存放在utils文件內(nèi)鳍置,也就是工具模塊中
utils模塊的文件結(jié)構(gòu)
- utils
    - __init__.py
    - interface.py # 接口類
    - service.py # 服務類
    - singleton.py # 單例模式

工具類在firefly中也非常重要,尤其是工具類中的服務器類(service.py)
該類幾乎貫穿整個分布式布局送淆,而分布式布局又是firefly的重中之重
下面我們首先就來看看服務類究竟都做了些什么

#coding:utf8
"""
Created on 2011-1-3
服務類
@author: sean_lan
"""
import threading
from twisted.internet import defer, threads
from twisted.python import log

class Service(object):
    """A remoting service

    attributes:
    ============
     * name - string, service name.
     * runstyle
    """
   
    # 在這里税产,我想作者應該是提供了兩種運行模式(我對這部分的理解,如有錯誤偷崩,請幫忙指出)
    # 單線程模式 這種模式下運行的服務應該是一個 deffered 對象辟拷,也就是延遲服務,不能運行同步的耗時任務环凿,因為會堵塞整個服務線程梧兼,甚至導致軟件奔潰
    # 多線程模式 在這種模式下放吩,服務是以twisted的多線程遲滯回調(diào)模式運行的智听,要求軟件返回的必須是一個同步對象,如果返回異步對象,則同樣會導致軟件異常到推,甚至崩潰
    # 所以在這里考赛,你必須擁有足夠的twisted使用知識,如果沒有莉测,請查閱相關(guān)文檔

    SINGLE_STYLE = 1  # 單線程運行
    PARALLEL_STYLE = 2 # 多線程運行

    def __init__(self, name, runstyle = SINGLE_STYLE):
        self._name = name # 服務名稱
        self._runstyle = runstyle #運行模式
        self.unDisplay = set() # 類似黑名單
        self._lock = threading.RLock() # 線程鎖
        self._targets = {} #目標服務字典
        # Keeps track of targets internally

    def __iter__(self):
        return self._targets.itervalues() # 返回所有服務

    def addUnDisplayTarget(self,command):
        """Add a target unDisplay when client call it."""
        self.unDisplay.add(command) # 將某個服務拉入黑名單

    def mapTarget(self, target):   # 注冊服務
        """Add a target to the service."""
        self._lock.acquire()
        try:
            key = target.__name__
            if key in self._targets:
                exist_target = self._targets.get(key)
                raise "target [%d] Already exists,\
                Conflict between the %s and %s"%(key,exist_target.__name__,target.__name__)
            self._targets[key] = target
        finally:
            self._lock.release()

    def unMapTarget(self, target): # 注銷服務
        """Remove a target from the service."""
        self._lock.acquire()
        try:
            key = target.__name__
            if key in self._targets:
                del self._targets[key]
        finally:
            self._lock.release()

    def unMapTargetByKey(self,targetKey): # 根據(jù)服務名稱注銷服務
        """Remove a target from the service."""
        self._lock.acquire()
        try:
            del self._targets[targetKey]
        finally:
            self._lock.release()

    def getTarget(self, targetKey):  #獲取服務
        """Get a target from the service by name."""
        self._lock.acquire()
        try:
            target = self._targets.get(targetKey, None)
        finally:
            self._lock.release()
        return target

    def callTarget(self, targetKey,*args,**kw): # 調(diào)用服務
        """call Target
        @param conn: client connection
        @param targetKey: target ID
        @param data: client data
        """
        if self._runstyle == self.SINGLE_STYLE:
            result = self.callTargetSingle(targetKey,*args,**kw)
        else:
            result = self.callTargetParallel(targetKey,*args,**kw)
        return result

    def callTargetSingle(self,targetKey,*args,**kw): # 用單線程方式調(diào)用服務
        """call Target by Single
        @param conn: client connection
        @param targetKey: target ID
        @param data: client data
        """
        target = self.getTarget(targetKey)

        self._lock.acquire()
        try:
            if not target:
                log.err('the command '+str(targetKey)+' not Found on service')
                return None
            if targetKey not in self.unDisplay:
                log.msg("call method %s on service[single]"%target.__name__)
            defer_data = target(*args,**kw)
            if not defer_data:
                return None
            if isinstance(defer_data,defer.Deferred):
                return defer_data
            d = defer.Deferred()
            d.callback(defer_data)
        finally:
            self._lock.release()
        return d

    def callTargetParallel(self,targetKey,*args,**kw): # 用多線程方式調(diào)用服務
        """call Target by Single
        @param conn: client connection
        @param targetKey: target ID
        @param data: client data
        """
        self._lock.acquire()
        try:
            target = self.getTarget(targetKey)
            if not target:
                log.err('the command '+str(targetKey)+' not Found on service')
                return None
            log.msg("call method %s on service[parallel]"%target.__name__)
            d = threads.deferToThread(target,*args,**kw)
        finally:
            self._lock.release()
        return d


class CommandService(Service):             
    """A remoting service
    繼承于服務類颜骤,主要用于指令服務(當客戶端數(shù)據(jù)被解析成指令后可以直接根據(jù)指令內(nèi)容調(diào)用服務)
    這里要求客戶講注冊到本服務對象的服務名稱寫成 name_commandId
    比如:getUser_01,當我調(diào)用1號指令時忍抽,會自動解析成這個函數(shù)名稱董朝。 
    """
    def mapTarget(self, target):
        """Add a target to the service."""
        self._lock.acquire()
        try:
            key = int((target.__name__).split('_')[-1]) #分割函數(shù)么鸠项,并取第二段
            if key in self._targets: # 注冊分割出來的函數(shù)ID
                exist_target = self._targets.get(key) 
                raise "target [%d] Already exists,\
                Conflict between the %s and %s"%(key,exist_target.__name__,target.__name__)
            self._targets[key] = target
        finally:
            self._lock.release()

    def unMapTarget(self, target):
        """Remove a target from the service."""
        self._lock.acquire()
        try:
            key = int((target.__name__).split('_')[-1])
            if key in self._targets:
                del self._targets[key]
        finally:
            self._lock.release()

第二步,我們看一下單例模式(singleton.py)

# 這個文件提供了python單例模式的元類
# 至于什么是單例模式子姜,什么是元類帅刊,筆者就不做詳細描述了
# 基本原則是纪蜒,單例模式一般用于配置文件
# 單例模式的特點是在一個進程中,無論被實例化幾次,都不會重新創(chuàng)建對象境蔼,而始終是第一個對象,這樣既能保證配置文件在一個程序中的唯一性畦徘,類似于全局變量
# 這一塊鸽捻,如果無法理解也沒有關(guān)系呼巴,可以直接跳過,你可以吧單例模式產(chǎn)生的類實例化的對象當成一個全局類御蒲,里面的變量當成全局變量衣赶。
class Singleton(type):
    """Singleton Metaclass"""

    def __init__(self, name, bases, dic):
        super(Singleton, self).__init__(name, bases, dic)
        self.instance = None

    def __call__(self, *args, **kwargs):
        if self.instance is None:
            self.instance = super(Singleton, self).__call__(*args, **kwargs)
        return self.instance

class test(metaclass=Singleton): # 指定創(chuàng)建Foo的type為SingletonType
    def __init__(self):
        self.json_config = None
#
# print(test().json_config)
# test().json_config = {"a":1}
# print(test().json_config)
# print(test())
# print(test())

最后,我們再來看看interface.py文件

# 這個作為一個接口類碘箍,以該類為接口的類必須要完成該類所提供的方法遵馆,否則會報錯
'''
Created on 2013-10-17

@author: lan (www.9miao.com)
'''
from __future__ import division, absolute_import
from zope.interface import Interface


class IDataPackProtoc(Interface):
    
    def getHeadlength():
        """獲取數(shù)據(jù)包的長度
        """
        pass
        
    def unpack():
        '''解包
        '''
        
    def pack():
        '''打包數(shù)據(jù)包
        '''
        
    
    


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市丰榴,隨后出現(xiàn)的幾起案子货邓,更是在濱河造成了極大的恐慌,老刑警劉巖四濒,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件换况,死亡現(xiàn)場離奇詭異职辨,居然都是意外死亡,警方通過查閱死者的電腦和手機戈二,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門舒裤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人觉吭,你說我怎么就攤上這事腾供。” “怎么了鲜滩?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵伴鳖,是天一觀的道長。 經(jīng)常有香客問我徙硅,道長黎侈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任闷游,我火速辦了婚禮峻汉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘脐往。我一直安慰自己休吠,他們只是感情好,可當我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布业簿。 她就那樣靜靜地躺著瘤礁,像睡著了一般。 火紅的嫁衣襯著肌膚如雪梅尤。 梳的紋絲不亂的頭發(fā)上柜思,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天,我揣著相機與錄音巷燥,去河邊找鬼赡盘。 笑死,一個胖子當著我的面吹牛缰揪,可吹牛的內(nèi)容都是我干的陨享。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼钝腺,長吁一口氣:“原來是場噩夢啊……” “哼抛姑!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起艳狐,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤定硝,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后毫目,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蔬啡,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡唁毒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了星爪。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡粉私,死狀恐怖顽腾,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情诺核,我是刑警寧澤抄肖,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站窖杀,受9級特大地震影響漓摩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜入客,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一管毙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧桌硫,春花似錦夭咬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至膀钠,卻和暖如春掏湾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背肿嘲。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工融击, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人雳窟。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓砚嘴,卻偏偏與公主長得像,于是被迫代替她去往敵國和親涩拙。 傳聞我的和親對象是個殘疾皇子际长,可洞房花燭夜當晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 一:java概述:1,JDK:Java Development Kit兴泥,java的開發(fā)和運行環(huán)境工育,java的開發(fā)工...
    ZaneInTheSun閱讀 2,661評論 0 11
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,111評論 1 32
  • 面向?qū)ο笾饕槍γ嫦蜻^程。 面向過程的基本單元是函數(shù)搓彻。 什么是對象:EVERYTHING IS OBJECT(萬物...
    sinpi閱讀 1,059評論 0 4
  • 小編費力收集:給你想要的面試集合 1.C++或Java中的異常處理機制的簡單原理和應用如绸。 當JAVA程序違反了JA...
    八爺君閱讀 4,596評論 1 114
  • JAVA面試題 1嘱朽、作用域public,private,protected,以及不寫時的區(qū)別答:區(qū)別如下:作用域 ...
    JA尐白閱讀 1,160評論 1 0