Swift源码分析----swift-proxy实现请求req的转发

论坛 期权论坛 脚本     
匿名技术用户   2021-1-6 05:26   569   0

感谢朋友支持本博客,欢迎共同探讨交流,由于能力和时间有限,错误之处在所难免,欢迎指正!

如果转载,请保留作者信息。
博客地址:http://blog.csdn.net/gaoxingnengjisuan
邮箱地址:dong.liu@siat.ac.cn

PS:最近没有登录博客,很多朋友的留言没有看见,这里道歉!还有就是本人较少上QQ,可以邮件交流。


概述:

这篇博客关注的问题就是:

请求信息如何通过swift-proxy服务实现转发;


这里应用网上找到的一幅图片来看看swift-proxy服务在swift系统中的作用(多谢作者);


简单说,请求过来之后,通过swift-proxy服务的服务入口点,调用swift-proxy服务上的相关方法,实现通过给定的请求来确定具体要获取的控制器(ObjectController、ContainerController、AccountController),并进一步调用控制器下的具体方法,实现到相应存储服务(Object-server、Container-server、Account-server)的连接,并具体调用相应的方法来实现请求;

下面来看看代码的实现:

  1. def __call__(self, env, start_response):
  2. """
  3. 调用WSGI服务的入口点;
  4. """
  5. try:
  6. # 获取缓存信息;
  7. # 在env中获取'swift.cache'的值,如果为none,则报错误提示;
  8. # 注:env:表示wsgi环境的字典;
  9. if self.memcache is None:
  10. self.memcache = cache_from_env(env)
  11. req = self.update_request(Request(env))
  12. return self.handle_request(req)(env, start_response)
  13. except UnicodeError:
  14. err = HTTPPreconditionFailed(request=req, body='Invalid UTF8 or contains NULL')
  15. return err(env, start_response)
  16. except (Exception, Timeout):
  17. start_response('500 Server Error',[('Content-Type', 'text/plain')])
  18. return ['Internal server error.\n']
方法handle_request实现了对HTTP传递过来的请求进行具体的处理和执行,来看方法handle_request的实现:


  1. def handle_request(self, req):
  2. """
  3. 代理服务的入口点;
  4. 对HTTP请求进行具体的处理和执行等操作;
  5. """
  6. try:
  7. self.logger.set_statsd_prefix('proxy-server')
  8. if req.content_length and req.content_length < 0:
  9. self.logger.increment('errors')
  10. return HTTPBadRequest(request=req, body='Invalid Content-Length')
  11. try:
  12. if not check_utf8(req.path_info):
  13. self.logger.increment('errors')
  14. return HTTPPreconditionFailed(request=req, body='Invalid UTF8 or contains NULL')
  15. except UnicodeError:
  16. self.logger.increment('errors')
  17. return HTTPPreconditionFailed(request=req, body='Invalid UTF8 or contains NULL')
  18. try:
  19. # 根据给定的HTTP的请求路径path获取控制器来处理请求;
  20. # 如果account, container, object都存在,则获取ObjectController控制器;
  21. # 如果account, container存在,object不存在,则获取ContainerController控制器;
  22. # 如果account存在,container, object不存在,则获取AccountController控制器;
  23. # 返回值:
  24. # path_parts:version, account, container, object等值的字典;
  25. # controller:具体的控制器类实例化对象;
  26. controller, path_parts = self.get_controller(req.path)
  27. # req.path = /v1/AUTH_2a8cbfbb8ad7411c8465f57311527937/testcontainer2/ceph9
  28. # controller = <class 'swift.proxy.controllers.obj.ObjectController'>
  29. # path_parts = {'object_name': 'ceph9', 'version': 'v1',
  30. # 'account_name': 'AUTH_2a8cbfbb8ad7411c8465f57311527937',
  31. # 'container_name': 'testcontainer2'}
  32. p = req.path_info
  33. if isinstance(p, unicode):
  34. p = p.encode('utf-8')
  35. except ValueError:
  36. self.logger.increment('errors')
  37. return HTTPNotFound(request=req)
  38. if not controller:
  39. self.logger.increment('errors')
  40. return HTTPPreconditionFailed(request=req, body='Bad URL')
  41. if self.deny_host_headers and req.host.split(':')[0] in self.deny_host_headers:
  42. return HTTPForbidden(request=req, body='Invalid host header')
  43. # server_type:不同的类定义了不同的server_type;
  44. # server_type = 'Object';
  45. # server_type = 'Account';
  46. # server_type = 'Base';
  47. # server_type = 'Container';
  48. self.logger.set_statsd_prefix('proxy-server.' + controller.server_type.lower())
  49. # 获取控制器类的实例化对象;
  50. controller = controller(self, **path_parts)
  51. if 'swift.trans_id' not in req.environ:
  52. # if this wasn't set by an earlier middleware, set it now
  53. trans_id = generate_trans_id(self.trans_id_suffix)
  54. req.environ['swift.trans_id'] = trans_id
  55. self.logger.txn_id = trans_id
  56. req.headers['x-trans-id'] = req.environ['swift.trans_id']
  57. controller.trans_id = req.environ['swift.trans_id']
  58. self.logger.client_ip = get_remote_client(req)
  59. try:
  60. # 执行具体控制器类中的指定方法;
  61. handler = getattr(controller, req.method)
  62. # req.method = DELETE
  63. # controller = <swift.proxy.controllers.obj.ObjectController object at 0x2acc110>
  64. # handler = <bound method ObjectController.DELETE of <swift.proxy.controllers.obj.ObjectController object at 0x2acc110>>
  65. getattr(handler, 'publicly_accessible')
  66. except AttributeError:
  67. allowed_methods = getattr(controller, 'allowed_methods', set())
  68. return HTTPMethodNotAllowed(request=req, headers={'Allow': ', '.join(allowed_methods)})
  69. if 'swift.authorize' in req.environ:
  70. resp = req.environ['swift.authorize'](req)
  71. if not resp:
  72. del req.environ['swift.authorize']
  73. else:
  74. if not getattr(handler, 'delay_denial', None):
  75. return resp
  76. req.environ['swift.orig_req_method'] = req.method
  77. # handler = <bound method ObjectController.DELETE of <swift.proxy.controllers.obj.ObjectController object at 0x2acc110>>
  78. return handler(req)
  79. except HTTPException as error_response:
  80. return error_response
  81. except (Exception, Timeout):
  82. self.logger.exception(_('ERROR Unhandled exception in request'))
  83. 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的实现;




该请求的转发过程是这样的:

首先根据请求组成一个字符串 PREFIX+account+container+object+POPFREIX进行MD5值的运算,然后根据计算结果进行移位获得key,而该key值就是我们需要的虚节点的数值,然后根据获得的虚节点的值,进行对应表的查找,获得虚节点和节点的对应值,然后依次在这些节点中进行数据的查找,如果找到了,则重新新建请求向指定的存储节点发送请求,进行分发,最后将返回的内容返回给客户端即可

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP