PancrasL的博客

OpenStack Swift中间件的原理及编写方式

2020-09-15

img

中间件原理

中间件的数据流

OpenStack Swift的中间件采用流处理模式,如图1-1所示,最外层的中间件收到请求,并可能会对它进行修改,然后再传递给下一层中间件。随后,下一层中间件同样可能在请求向内层传递前对它进行修改。当请求到达中间件管道(pipeline)的末尾时,由 Swift 核⼼心程序进行处理,并产生一个响应。之后,响应顺着管道反向传递,管道中所有中间件都可以对响应进行修改。当然,任何一层中间件也可以选择不对请求或响应做任何更改(大多数情况下都如此)。一旦最外层的中间件对响应进行处理(或者不作任何修改)之后,最终的响应就会返回给⽤用户。

img
图1-1 中间件的数据流图

中间件的短路请求

管道的每层中间件都可以短路请求并返回一个响应或错误。例如,如果未认证用户想要执行一个 需要认证的操作,认证中间件就会返回一个错误。当收到健康检查请求时,健康检查中间件可以选择 直接返回一个成功的响应,而不会继续向内层中间件传递该健康检查请求。在这些短路的例子中,都 不会将请求传递到下游的中间件或Swift核心程序,如图1-2所示。

img
图1-2 中间件的短路请求

中间件的编写

修改请求头部信息

对头部信息的修改不会直接更改头部,而是通过一个函数完成,如果该函数被调⽤,除了完成start_response的工作,还会添加一个额外的头部。代码样例如下所示,我们将new_start_response作为app的第二个参数向下传递即可。

1
2
3
4
5
6
7
8
class HeaderAddingMiddleware(object):
def __init__(self, app):
self.app = app

def __call__(env, start_response):
def new_start_response(status, headers):
return start_response(status, headers+('X-New-Header', 'info'))
return self.app(env, new_start_response)

修改响应数据

调用self.app(env, start_response)会将数据传入到下一个中间件,并在其之后的中间件处理完毕后传回相应,因此对响应数据的修改就是对self.app(env, start_response)的返回值进行修改。需要注意的是,返回值类型是生成器类型(generator,一种特殊的迭代器),如果我们使用其进行遍历操作,需要先使用itertools.tee()方法复制生成器。下面是将响应数据转换成大写字符的例子(假设响应数据为字符串)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class ModifyDataMiddleware(object):
def __init__(self, app):
self.app = app

def __call__(env, start_response):
# 需要注意,body类型是生成器类型(generator,一种特殊的迭代器),因此如果需要遍历时,需要先进行复制
body = self.app(env, start_response)
# 复制生成器
body, body1 = itertools.tee(body, 2)
# 查看body的数据,或者修改body的数据为大写(假设为字符数据)
for chunk in body1:
pprint(chunk)
chunk.upper()
return body

Reference :