zoukankan      html  css  js  c++  java
  • paste deploy初探

    这段时间刚着手开始研究Openstack Swift源码,为后续开发做准备。 

    Swift依据python WSGI规范。WSGI(Web Server Gateway Interface)是Python应用程序或框架与Web服务器之间的一种接口,定义了一套借口来实现服务器与应用端的通信规范。按照一套规范,应用端想要通信,很简单,只需要实现一个接受两个参数的,含有__call__方法并返回一个可遍历的含有零个或者多个string结果的python对象。 
    而paste.deploy(Paste Deployment)是用于发现和配置WSGI server和application的系统。对WSGI应用消费者而言,它提供了一个很简单的函数loadapp()从配置文件或python EGG中加载应用。两种不同的加载方式分别对应在路径前添加“config:”和“egg:”(即URI)。 
    在swift源码中,关于loadapp的调用在swift.common目录下wsgi.py文件中。

     1 ……
     2 from paste.deploy import loadwsgi
     3 ……
     4 def wrap_conf_type(f):                 #line no.93 in swift-havana#
     5     def wrapper(conf_path, *args, **kwargs):
     6         if os.path.isdir(conf_path):
     7             conf_type = 'config_dir'
     8         else:
     9             conf_type = 'config'
    10         conf_uri = '%s:%s' % (conf_type, conf_path)
    11         return f(conf_uri, *args, **kwargs)
    12     return wrapper
    13 
    14 appconfig = wrap_conf_type(loadwsgi.appconfig)
    15 loadapp = wrap_conf_type(loadwsgi.loadapp)
    16 ……
    17 
    18 def run_server(conf, logger, sock):   #line no.199 in swfit-havana#
    19     ……
    20     app = loadapp(conf['__file__'], global_conf={'log_name': log_name})
    21     max_clients = int(conf.get('max_clients', '1024'))
    22     pool = RestrictedGreenPool(size=max_clients)
    23     try:
    24         wsgi.server(sock, app, NullLogger(), custom_pool=pool)
    25     except socket.error as err:
    26         if err[0] != errno.EINVAL:
    27             raise
    28     pool.waitall()

    如此相当于对loadwsgi模块中appconfig函数和loadapp函数进行了封装,自动在conf_path参数前添加”config:”。后在run_server()函数中调用了loadapp()函数,正式载入配置文件。

    载入配置文件后,根据配置文件配置,找到相应application和middleware的入口点,加载这些应用及中间件。我们先对照着看看proxy-server的配置文件,然后在依据paste.deploy官方文档和相关资料进行详细解释。

     1  [DEFAULT]
     2 # Enter these next two values if using SSL certificationscert_file = /etc/swift/cert.crt
     3 key_file = /etc/swift/cert.key
     4 bind_port = 8080
     5 workers = 8
     6 user = swift
     7 
     8 [pipeline:main]
     9 # keep swauth in the line below if you plan to use swauth for authenticationpipeline = healthcheck cache swauth proxy-server
    10 
    11 [app:proxy-server]
    12 use = egg:swift#proxy
    13 allow_account_management = true
    14 
    15 [filter:swauth]
    16 # the line below points to swauth as a separate project from swiftuse = egg:swauth#swauth
    17 # Highly recommended to change this.super_admin_key = swauthkey
    18 
    19 [filter:healthcheck]
    20 use = egg:swift#healthcheck
    21 
    22 [filter:cache]
    23 use = egg:swift#memcache
    24 memcache_servers = <PROXY_LOCAL_NET_IP>:11211

    WSGI只关心那些带前缀的部分,即类似“pipeline:main”之类的。section为[type:name]格式,前缀表示section类型,后接section名称。常用的前缀分别有“composite”, “app”, “pipeline”, “filter-app”,“filter”几种。下面分别对其进行简单介绍。

    1.composite,组合应用。由若干WSGI应用组成,composite为这些应用提供更高一层的分配工作。下面是一个composite section的例子。它能根据接受的http请求url中对应字段将不同HTTP请求发送给不同的应用进行处理。其中egg:Paste#urlmap指定了url解析所使用的函数——为系统自带的paste.urlmap库。

    1 [composite:main]
    2 use = egg:Paste#urlmap
    3 / = home
    4 /blog = blog
    5 /wiki = wiki
    6 /cms = config:cms.ini

    2.app,声明具体的WSGI应用。应用的具体实现要在section中配置,有两种方法专门用于指出应用对应的代码:使用URI(用use标识)或 直接指向实现代码(用protocol标识)。例子如下:

     1 [app:myapp]
     2 use = config:another_config_file.ini#app_name
     3 
     4 # 或任意URI:
     5 [app:myotherapp]
     6 use = egg:MyApp
     7 
     8 # 或指明某个模块中的可调用:
     9 [app:mythirdapp]
    10 use = call:my.project:myapplication
    11 
    12 # 甚至是其他的section:
    13 [app:mylastapp]
    14 use = myotherapp

    下例的protocol paste.app_factory 是一个应用的工厂函数,指明import对象的类型;值 myapp.modulename:app_factory 指明具体加载的模块和方法。

    1 [app:myapp]
    2 paste.app_factory = myapp.modulename:app_factory

    3.filter,作用于WSGI应用上的函数或方法,以app为唯一的参数,并返回一个“过滤”后的app。 
    4.filter-app,同样是处理应用的过滤器,写法不同。如下例,filter-app标明的“blog”表示定义的filter,而其处理的应用在next字段中指明——blogapp。

    1 [filter-app:blog] 
    2 use = egg:Authentication#auth 
    3 next = blogapp 
    4 roles = admin 
    5 htpasswd = /home/me/users.htpasswd 

    5.pipeline,便于对一个应用添加多个filter(过滤器)进行处理。在proxy-server的配置文件中即是如此,pipeline = healthcheck cache swauth proxy-server这一语句表示“proxy-server”应用需要healthcheck、cache和swauth三个过滤器的处理。将app名写在最后是pipeline section约定俗成的。

    上面提到了WSGI中app和middleware。实际上wsgi 是一个 web 组件的接口规范.,wsgi将 web 组件分为三类: web服务器,web中间件(filter),web应用程序(app)。wsgi基本处理模式为 : WSGI Server -> (WSGI Middleware)* -> WSGI Application 。最开始的那一段openstack swift源码中 wsgi.server(sock, app, NullLogger(), custom_pool=pool)便是运行了一个wsgi server,它会监听指定socket接收http请求,然后根据config文件配置调用application处理并返回。

    通过对这些知识的了解,成功利用wsgi规范编写了一个server,配置文件直接指定实现代码的方式(factory函数),返回简单测试信息。接下来,深入学习paste.deploy库的细节,比如app定义的具体语法规则,几种factory函数的实现细节等等。还要学习eventlet函数库,弄懂协程,对照学习webob函数库和swift中swob,学习setuptools和相应的pbr。任重道远,继续努力!

    关于本文的更多参考资料: 
    【1】paste.deploy python文档 
    【2】网络博客–Openstack paste deploy介绍 
    【3】网络博客–paste deploy

  • 相关阅读:
    【应试】数据通信与网络
    【应试】操作系统OS
    【笔记】 卷积
    【HDU 5920】 Ugly Problem
    【笔记】位运算
    【洛谷P1378】油滴扩展
    【洛谷 P1120】 小木棍[数据加强版]
    [codeforces]Round #538 (Div. 2) F. Please, another Queries on Array?
    [BZOJ]2563: 阿狸和桃子的游戏
    [BZOJ]4668: 冷战
  • 原文地址:https://www.cnblogs.com/qiyukun/p/4256488.html
Copyright © 2011-2022 走看看