28 Matching Annotations
  1. Jun 2018
    1. RoutesMiddleware将HTTP的URL请求应声到相应WSGI函数,并且将路由匹配结果存到environ环境变量中去

      RoutesMiddleware 主要作用:

      1. 将HTTP的URL请求映射到相应WSGI函数
      2. 讲路由匹配结果存到environ环境变量中
  2. May 2018
    1. Fanout: 相当于广播,producer 可把消息发送给多个 consumer,属于异步调用范畴,如下图

    2. Cast: 异步调用,producer 发送消息后继续执行后续步骤,consumer 接收处理消息,如下图。

    3. Call: 同步调用,但过程稍微复杂,producer 发送消息后立刻创建一个 direct consumer, 该 direct consumer 阻塞于接收返回值。对端的 consumer 接收并处理 producer 的消息后,创建一个 direct producer,它负责把处理结果发送给 direct consumer

    4. AMQP 是应用层协议,它在 client 和 server 端引入了消息中间件,解耦了 client 和 server 端,支持大规模下的消息通信

      AMQP 引入了消息中间件

      从RPC角度来看,Client端要远程调用Server端的函数

      从AMQP角度来看,Client要发起请求,产生请求消息,所以是Producer,Server端需要获取消息消费,才能进行相应的处理,所以是Consumer

    1. 你可以使用传入type=的方式来使用Opt类,或者直接使用其对应类型的子类例如StrOpt类,如果配置项值无法解析成对应类型,将会抛出一个ValueError错误
      common_opts = [
          cfg.Opt( 'bind_port',
                    type=PortType,
                    default=9292,
                    help='Port number to listen')
      ]
      ### 等价于
      common_opts = [
          cfg.PortOpt( 'bind_port',
                        default=9292,
                        help='Port number to listen')
      ]
      

    Tags

    Annotators

    1. 最后一种使用插件的方式,相当于Drivers加载和Extensions加载的结合。它允许在给定的entry points组名下有同名的entry point,这样,在给定entry points组名和entry point名的情况下,hook式加载会加载所有找到的插件。

      Hook式加载

    2. ExtensionManager和DriverManager略有不同,它不需要提前知道要加载哪个插件,它会加载所有找到的插件。          要想调用插件,需要使用map方法,需要传给map一个函数,这里就是format_data函数,针对每个扩展都会调用该函数。format_data函数有两个参数,分别是Extension实例和map的第二个参数da

      不需要知道插件的具体名字,指定namespace='xxxx',则会加载xxxx entry point group下的所有插件(扩展)

      要调用插件 ==> manager.map(func, args) ==> namespace中的每个插件都会调用该函数func ==> manager.map(func, args) return 一个序列,序列中的每个元素就是每个插件调用回调函数的返回值

    3. 定义并注册插件

      注册插件是通过 setup.py 来注册插件的

      from setuptools import setup, find_packages
      setup(
          name='test',
          version='1.0',
          packages=find_packages(),
          entry_points={
              'namespace': [
                  'name = module:importable'
              ],
          },
      )
      
    4. 在stevedore中,有三种使用插件的方式:Drivers、Hooks、Extensions
      1. Drivers:一个名字对应一个entry point

      2. Hooks:一个名字对应多个entry point

      3. Extensions:多个名字对应多个entry point

    1. 根据每个插件在entry point中名字和具体实现的数量之间的对应关系不同,stevedore提供了多种不同的类来帮助开发者发现和载入插件,如下图所示:

    2. 示例中显示了两个不同的entry points的命名空间,“ceilometer.compute.virt"和"ceilometer.hardware.inspectors",分别注册有3个和1个插件.每个插件都符合"名字=模块:可导入对象”的格式,在“ceilometer.compute.virt"命名空间里的libvirt插件,它的具体可载入的实现是ceilometer.compute.virt.libvirt.inspector模块中的LibvirtInspector类.
      ceilometer.compute.virt =   
          libvirt = ceilometer.compute.virt.libvirt.inspector:LibvirtInspector  
          hyperv = ceilometer.compute.virt.hyperv.inspector:HyperVInspector  
          vsphere = ceilometer.compute.virt.vmware.inspector:VsphereInspector  
      
      ceilometer.hardware.inspectors =  
          snmp = ceilometer.hardware.inspectors.snmp:SNMPInspector
      
      • ceilometer.compute.virt 和 ceilometer.hardware.inspectors是两个命名空间
      • ceilometer.compute.virt 有 libvirt,hyperv,vsphere 三个插件,ceilometer.hardware.inspectors 有 snmp 一个插件
      • 插件的具体可载入实现是每个插件等号后面的具体类
    1. Note Due to how Routes matches a list of URL’s, it has no inherent knowledge of a route being a resource. As such, if a route fails to match due to the method requirements not being met, a 404 will return just like any other failure to match a route.

      注意:由于路由与URL的列表相匹配,它不具有作为资源的路由的固有知识,因此,如果由于未满足方法要求而导致路由不匹配,则404将像任何其他路由失败一样返回以匹配路由。

    1. A static route is used only for generation – not matching – and it must be named. To define a static route, use the argument _static=True.

      静态路由仅用于URL生成,不会用于匹配,并且必须命名。使用参数 _static=True 来定义静态路由

    2. However, if the route defines an extra variable with the same name as a path variable, the extra variable is used as the default if that keyword is not specified.

      但是,如果路由定义了一个额外变量和 url() 的路径变量名称相同,如果未指定该关键字,那么额外变量将用 作默认值

      ### id 作为额外参数
      m.connect("archives", "/archives/{id}",
          controller="archives", action="view", id=1)
      ### id作为路径参数
      url("archives", id=123)  =>  "/archives/123"
      url("archives")  =>  "/archives/1"
      
    3. url("blog", year=2008, month=10, day=2)

      如果路由包含path variables(路径变量),则必须使用关键字参数设置这些变量值:

    4. url("home") => "/"

      要生成一个带名字的路由,指定路由名作为位置参数

    1. If the “path_info” variable is used at the end of the URL, Routes moves everything preceding it into the “SCRIPT_NAME” environment variable. This is useful when delegating to another WSGI application that does its own routing: the subapplication will route on the remainder of the URL rather than the entire URL. You still need the ”:.*” requirement to capture the following URL components into the variable.

      如果在URL的末尾使用“path_info”变量,则Routes会将其前面的所有内容移动到“SCRIPT_NAME”环境变量中。

      当委派另一个WSGI应用程序执行自己的路由时,这非常有用:子应用程序将路由剩余的URL而不是整个URL。

      您仍需要“:.*” requirement 才能将以下URL组件捕获到变量中。

      map.connect(None, "/cards/{path_info:.*}",
          controller="main", action="cards")
      # Incoming URL "/cards/diamonds/4.png"
      => {"controller": "main", action: "cards", "path_info": "/diamonds/4.png"}
      # Second WSGI application sees:
      # SCRIPT_NAME="/cards"   
      # PATH_INFO="/diamonds/4.png"
      
    2. map.connect(None, "/error/{action}/{id}", controller="error")

      Mapper在Web应用程序中处理URL生成和URL识别。

      Mapper是建立处理字典的。 假定Web应用程序将处理返回由URL识别并正确分派的字典。

      通过将关键字参数传递到生成函数来完成URL生成,然后返回一个URL。

      class Mapper(SubMapperParent):
      
          def __init__(self, 
                  controller_scan=controller_scan, 
                  directory=None,
                  always_scan=False, 
                  register=True, 
                  explicit=True):
      ### Create and connect a new 
      ### Route to the Mapper
          def connect(self, 
                      routename, 
                      path=None, 
                      **kwargs):
              ........
      
    1. app_iter = myfunc(environ, start_response) resp = myfunc(req)

      With that myfunc will be a WSGI application, callable like

      app_iter = myfunc(environ, start_response).
      

      You can also call it like normal

      resp = myfunc(req)
      

      You can also wrap methods

      def myfunc(self, req).)
      
    2. @wsgify def myfunc(req): return webob.Response('hey there')

      不添加装饰器,打印type(myfunc)

      <type 'function'>
      

      添加装饰器之后,打印type(myfunc)

      <class 'webob.dec.wsgify'>
      
    3. >>> from webob import Request >>> environ = {'wsgi.url_scheme': 'http', ...} >>> req = Request(environ)
      ### environ 是 WSGI环境变量
      req = Request(environ)
      把 environ 字典 转换成 <class 'webob.request.Request'> Request对象
      所以 webob.Request是对WSGI环境变量的一个封装
      

    Tags

    Annotators

    URL

    1. @classmethod def factory(cls, global_conf, **kwargs): return cls()
      class AnimalApplication(object):
          @classmethod
          def factory(cls, global_conf, **kwargs):
              print cls
              return cls()
      
      <class '__main__.AnimalApplication'>
      ==> cls 指的是类本身
      
    2. eventlet: python 的高并发网络库 paste.deploy: 用于发现和配置 WSGI application 和 server 的库 routes: 处理 http url mapping 的库

      WSGI框架下一些常用的 python module

      • eventlet
      • paste.deploy
      • routes
    1. Middleware 处于 server/gateway 和 application/framework 之间,对 server/gateway 来说,它相当于 application/framework;对 application/framework 来说,它相当于 server/gateway。每个 middleware 实现不同的功能,我们通常根据需求选择相应的 middleware 并组合起来,实现所需的功能

      比如,可在 middleware 中实现以下功能:

      • 根据 url 把用户请求调度到不同的 application 中。
      • 负载均衡,转发用户请求
      • 预处理 XSL 等相关数据
      • 限制请求速率,设置白名单
      middleware 介于 sever/gateway 和 application/framework 之间 该怎么理解
      • 简单考虑,没有middleware时,创建server时指定application,请求发生时,调用application
      • 那么有middleware是什么情况呢?middleware接收application作为入参,这样就把middleware和application这一端连接起来,对于application来说,middleware就像server一样,middleware把application执行结果返回给server,对于server来说,middleware就像application一样
    2. Callable object 必须满足以下两个条件:
      • 接受两个参数:字典dict (environ),回调函数(start_response,返回 HTTP status, headers 给 web server)
      • 返回一个可以迭代的值
    3. PEP 0333 – Python Web Server Gateway Interface 是一种 web server or gateway 和 python web application or framework 之间简单通用的接口,符合这种接口的 application 可运行在所有符合该接口的 server 上

      WSGI -- web server gateway interface

      是一种 web server/gateway 和 python web application/framework 之间的通用接口

      符合这种接口的application,都可以运行在符合该接口的server上

      application <==> web server gateway interface <==> server

    4. a proposed standard interface between web servers and Python web applications or frameworks

      WSGI -- a interface of python web applications or frameworks