Swift源碼分析----swift-proxy實現請求req的轉發

感謝朋友支持本博客,歡迎共同探討交流,由於能力和時間有限,錯誤之處在所難免,歡迎指正!

如果轉載,請保留作者信息。
博客地址:http://blog.csdn.net/gaoxingnengjisuan
郵箱地址:[email protected]

PS:最近沒有登錄博客,很多朋友的留言沒有看見,這裏道歉!還有就是本人較少上QQ,可以郵件交流。


概述:

這篇博客關注的問題就是:

請求信息如何通過swift-proxy服務實現轉發;


這裏應用網上找到的一幅圖片來看看swift-proxy服務在swift系統中的作用(多謝作者);


    簡單說,請求過來之後,通過swift-proxy服務的服務入口點,調用swift-proxy服務上的相關方法,實現通過給定的請求來確定具體要獲取的控制器(ObjectController、ContainerController、AccountController),並進一步調用控制器下的具體方法,實現到相應存儲服務(Object-server、Container-server、Account-server)的連接,並具體調用相應的方法來實現請求;

下面來看看代碼的實現:

def __call__(self, env, start_response):
    """
    調用WSGI服務的入口點;
    """
    try:
        # 獲取緩存信息;
        # 在env中獲取'swift.cache'的值,如果爲none,則報錯誤提示;
        # 注:env:表示wsgi環境的字典;
            
        if self.memcache is None:
            self.memcache = cache_from_env(env)
            
        req = self.update_request(Request(env))

        return self.handle_request(req)(env, start_response)
    except UnicodeError:
        err = HTTPPreconditionFailed(request=req, body='Invalid UTF8 or contains NULL')
        return err(env, start_response)
    except (Exception, Timeout):
        start_response('500 Server Error',[('Content-Type', 'text/plain')])
        return ['Internal server error.\n']
方法handle_request實現了對HTTP傳遞過來的請求進行具體的處理和執行,來看方法handle_request的實現:


def handle_request(self, req):
    """
    代理服務的入口點;
    對HTTP請求進行具體的處理和執行等操作;
    """
    try:
        self.logger.set_statsd_prefix('proxy-server')
        if req.content_length and req.content_length < 0:
            self.logger.increment('errors')
            return HTTPBadRequest(request=req, body='Invalid Content-Length')

        try:
            if not check_utf8(req.path_info):
                self.logger.increment('errors')
                return HTTPPreconditionFailed(request=req, body='Invalid UTF8 or contains NULL')
        except UnicodeError:
            self.logger.increment('errors')
            return HTTPPreconditionFailed(request=req, body='Invalid UTF8 or contains NULL')

        try:
            # 根據給定的HTTP的請求路徑path獲取控制器來處理請求;
            # 如果account, container, object都存在,則獲取ObjectController控制器;
            # 如果account, container存在,object不存在,則獲取ContainerController控制器;
            # 如果account存在,container, object不存在,則獲取AccountController控制器;
            # 返回值:
            # path_parts:version, account, container, object等值的字典;
            # controller:具體的控制器類實例化對象;
            controller, path_parts = self.get_controller(req.path)
            # req.path = /v1/AUTH_2a8cbfbb8ad7411c8465f57311527937/testcontainer2/ceph9
            # controller = <class 'swift.proxy.controllers.obj.ObjectController'>
            # path_parts = {'object_name': 'ceph9', 'version': 'v1', 
            #               'account_name': 'AUTH_2a8cbfbb8ad7411c8465f57311527937', 
            #               'container_name': 'testcontainer2'}
                
            p = req.path_info
            if isinstance(p, unicode):
                p = p.encode('utf-8')
        except ValueError:
            self.logger.increment('errors')
            return HTTPNotFound(request=req)
            
        if not controller:
            self.logger.increment('errors')
            return HTTPPreconditionFailed(request=req, body='Bad URL')
            
        if self.deny_host_headers and req.host.split(':')[0] in self.deny_host_headers:
            return HTTPForbidden(request=req, body='Invalid host header')

            # server_type:不同的類定義了不同的server_type;
            # server_type = 'Object';
            # server_type = 'Account';
            # server_type = 'Base';
            # server_type = 'Container';          
            self.logger.set_statsd_prefix('proxy-server.' + controller.server_type.lower())
            
        # 獲取控制器類的實例化對象;
        controller = controller(self, **path_parts)
            
        if 'swift.trans_id' not in req.environ:
            # if this wasn't set by an earlier middleware, set it now
            trans_id = generate_trans_id(self.trans_id_suffix)
            req.environ['swift.trans_id'] = trans_id
            self.logger.txn_id = trans_id
        req.headers['x-trans-id'] = req.environ['swift.trans_id']
        controller.trans_id = req.environ['swift.trans_id']
        self.logger.client_ip = get_remote_client(req)
            
        try:
            # 執行具體控制器類中的指定方法;
            handler = getattr(controller, req.method)
            # req.method = DELETE
            # controller = <swift.proxy.controllers.obj.ObjectController object at 0x2acc110>
            # handler = <bound method ObjectController.DELETE of <swift.proxy.controllers.obj.ObjectController object at 0x2acc110>>             
            getattr(handler, 'publicly_accessible')
        except AttributeError:
            allowed_methods = getattr(controller, 'allowed_methods', set())
            return HTTPMethodNotAllowed(request=req, headers={'Allow': ', '.join(allowed_methods)})
            
        if 'swift.authorize' in req.environ:
            resp = req.environ['swift.authorize'](req)
            if not resp:
                del req.environ['swift.authorize']
            else:
                if not getattr(handler, 'delay_denial', None):
                    return resp

        req.environ['swift.orig_req_method'] = req.method
            
        # handler = <bound method ObjectController.DELETE of <swift.proxy.controllers.obj.ObjectController object at 0x2acc110>>
        return handler(req)

    except HTTPException as error_response:
        return error_response
    except (Exception, Timeout):
        self.logger.exception(_('ERROR Unhandled exception in request'))
        return HTTPServerError(request=req)
1.controller, path_parts = self.get_controller(req.path)
   根據給定的HTTP的請求路徑path獲取控制器(ObjectController、ContainerController、AccountController)來處理請求;
2.controller = controller(self, **path_parts)
   獲取控制器類的實例化對象;
3.handler = getattr(controller, req.method)
   執行具體控制器類中的指定方法;
4.return handler(req)
   調用相應控制器中具體的方法來對req進行處理;

   接下來將要調用的就是/swift/proxy/controllers/account.py或/swift/proxy/controllers/container.py或/swift/proxy/controllers/obj.py下面的PUT,POST,DELETE,GET,HEAD等方法;然後再在具體的方法中實現到具體存儲服務(Object-serverContainer-server、Account-server)的連接,繼而調用其下具體的PUT,POST,DELETE,GET,HEAD等方法來進行請求req的實現;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章