Rack相关知识梳理(二)

简介: 一、Rack中间件 1、什么是中间件 中间件其实就是Ruby应用服务器和Rack应用程序之间执行的代码 2、一个简单的例子 $LOAD_PATH.unshift(File.dirname(__FILE__)) require 'rack' require 'decorator' my_app = l

一、Rack中间件


1、什么是中间件


中间件其实就是Ruby应用服务器和Rack应用程序之间执行的代码


2、一个简单的例子


$LOAD_PATH.unshift(File.dirname(__FILE__)) 
require 'rack'
require 'decorator'
my_app = lambda { |env|
  request = Rack::Request.new(env)
  response = Rack::Response.new 
  response["Content-Type"] = "text/html"
  if request.path_info == "/hello"
    response.write("you say hello")
  else
    response.write("you need say something") 
  end
  response.finish 
}
Rack::Handler::WEBrick.run Decorator.new(my_app), :Port => 3000


这段代码中我们的rack应用程序是一个lambda(lambda具有call方法的) 前面几行没什么好说的,大家看最后一句:


Rack::Handler::WEBrick.run Decorator.new(my_app), :Port => 3000


我们最后传给run的是Decorator对象,这个对象在构造时接受一个rack应用为参数,这个实例既然能被Handler调用,可想而知,我们Decorator必然具备call方法,所以我们也就清楚这个类的结构如下:


class Decorator 
  def initialize(app) 
    ......
  end
  def call(env)
    ......
  end
end


ok,接下来我们编写Decorator


class Decorator 
  def initialize(app)
    @app = app
  end
  def call(env)
    status, headers, body = @app.call(env)
    new_body = "=======beader=========<br/>" 
    body.each { |str| new_body << str }
    new_body << "<br/>======footer=========" 
    headers["Content-Length"] = new_body.bytesize.to_s
    [status, headers, [new_body]]
  end 
end


启动应用,在浏览器上看看效果:


=======beader=========

you say hello

======footer=========


由上可知,Decorator运行在Ruby应用服务器和Rack应用程序之间,因此Decorator就是一个中间件,而且我们可以知道,任何Rack中间件必然是一个合法的Rack应用程序。


3、为什么要用中间件


中间件可以实现通用逻辑和业务逻辑分离,并且这些通用逻辑可以应用到各种各样的业务逻辑中。

 

二、装配中间件


前面我看到一个Rack中间件必然是一个合法的Rack应用程序,那么我们不难想到,一个中间件 外面可以在包装一个中间件,每一个中间件都是独立的,只关心自己的逻辑实现,这样我们就 可以对整个框架或系统中的中间件进行替换,我们还可以用不同的方式去组合多个中间件,从 而满足我们的需求。


1、如何装配中间件


我们往往会在一个应用程序中使用多个中间件,最直接的办法就是new出我们需要的中间件,


例如我们要用middleware1和middleware2两个中间件,那我们可以这样编写代码:


Rack::Handler::WEBrick.run middleware1.new(middleware2.new(rack_app)), :Port => 3000


当然这并不是一个好办法,如果我们要用的中间件非常多,那这段代码就会非常冗⻓,好在Rack已经想到这一点,并且提供了一个非常好的办法:


Rack::Builder


我们利用Builder修改我们之前的代码:


app = lambda { |env|
  request = Rack::Request.new(env) 
  response = Rack::Response.new 
  response["Content-Type"] = "text/html"
  if request.path_info == "/hello"
    response.write("you say hello") 
  else
    response.write("you need say something") 
  end
  response.finish 
}
my_app = Rack::Builder.new { 
  use Decorator
  run app
}.to_app
Rack::Handler::WEBrick.run my_app, :Port => 3000


如果要用多个中间件,那就写成这样:


use middleware1


use middleware2


user middleware3


......


PS:前面大家可能注意到,中间件采用了装饰器的设计模式,所以当使用多个中间件时,各个中间件之间顺序是需要注意的


我们来看看Builder中几个重要的方法


initialize


def initialize(default_app = nil,&block)
  @use, @map, @run, @warmup = [], nil, default_app, nil 
  instance_eval(&block) if block_given?
end


initialize:构造方法,能够接受语句块

 

use


def use(middleware, *args, &block) 
  if @map
    mapping, @map = @map, nil
    @use << proc { |app| generate_map app, mapping } 
  end
  @use << proc { |app| middleware.new(app, *args, &block) } 
end


use:记录要创建的中间件及其顺序。

 

run


def run(app) 
  @run = app
end


run:记录原始的应用程序

 

to_app


def to_app
  app = @map ? generate_map(@run, @map) : @run 
  fail "missing run or map statement" unless app
  app = @use.reverse.inject(app) { |a,e| e[a] } 
  @warmup.call(app) if @warmup
  app
end


to_app:根据use和run中的纪录组合最终的应用程序

相关文章
|
3月前
|
Kubernetes Docker Python
dockercompose与k8s的pod文件的爱恨情仇
dockercompose与k8s的pod文件的爱恨情仇
|
4月前
|
Kubernetes Linux 网络虚拟化
15张图超硬核讲解 Kubernetes 网络,我不信网工不会看!
15张图超硬核讲解 Kubernetes 网络,我不信网工不会看!
|
网络协议
HCIP第三天ospf星型和全连实验
R1/4/5 使用全连所有接口工作方式为broadcast;DR/BDR将默认自动选举成功 R1
58 0
|
存储 Go 调度
计及调度经济性的光热电站储热容量配置方法【IEEE30节点】(Matlab代码实现)
计及调度经济性的光热电站储热容量配置方法【IEEE30节点】(Matlab代码实现)
|
存储 Go 调度
计及调度经济性的光热电站储热微网模型容量配置方法【IEEE30节点】(Matlab代码实现)
计及调度经济性的光热电站储热微网模型容量配置方法【IEEE30节点】(Matlab代码实现)
|
中间件 应用服务中间件 API
Rack相关知识梳理(一)
一、什么是Rack Rack是ruby应用服务器和Rack应用程序之间的接口, 这里面Ruby应用服务器可以是Webrick、thin等,Rack应用程序可以是rails、Sinatra等(其实 现在主流的ruby的Web框架都是基于Rack的)。在上图中,当用户的请求到达应用服务器时,应用服务器会
576 0
|
弹性计算 运维 Kubernetes
如何才能不被Kubernetes按在地上摩擦?
如何才能不被Kubernetes按在地上摩擦?
如何才能不被Kubernetes按在地上摩擦?
|
Kubernetes 安全 对象存储
大佬愤怒喊话:在大厂做 Kubernetes 开源工作难以晋升
近日,Kubernetes(简称 K8s)圈内大佬 Noah Kantrowitz 连发多条推文抨击“FAANG”科技巨头内部晋升机制对 K8s 全职员工不友好,他指出,“科技大厂们的激励措施正阻止人们全职参与开源贡献,大家的贡献积极性正在放缓。”
189 0
大佬愤怒喊话:在大厂做 Kubernetes 开源工作难以晋升
|
中间件
Rack相关知识梳理(三)
Rack为编写Web应用以及Web框架提供了很多便利的工具,那么这一节,我们实现一个最简单的Web框架。 一、Web框架应该具备什么功能 对request和response的存取 路由:根据不同URL执行不同程序 能够处理cookies 能够存取session 能够生成日志 ...... 看上去挺麻
323 0
|
Kubernetes 负载均衡 监控
OpenKruise 2021 规划曝光:More than workloads
OpenKruise 是什么?它是阿里云开源的云原生应用自动化管理引擎,也是当前托管在 Cloud Native Computing Foundation (CNCF) 下的 Sandbox 项目。它来自阿里巴巴多年来容器化、云原生的技术沉淀,是阿里内部生产环境大规模应用的基于 Kubernetes 之上的标准扩展组件,一套紧贴上游社区标准、适应互联网规模化场景的技术理念与最佳实践。
OpenKruise 2021 规划曝光:More than workloads