Rack相关知识梳理(一)

简介: 一、什么是Rack Rack是ruby应用服务器和Rack应用程序之间的接口, 这里面Ruby应用服务器可以是Webrick、thin等,Rack应用程序可以是rails、Sinatra等(其实 现在主流的ruby的Web框架都是基于Rack的)。在上图中,当用户的请求到达应用服务器时,应用服务器会

一、什么是Rack


Rack是ruby应用服务器和Rack应用程序之间的接口,



这里面Ruby应用服务器可以是Webrick、thin等,Rack应用程序可以是rails、Sinatra等(其实 现在主流的ruby的Web框架都是基于Rack的)。在上图中,当用户的请求到达应用服务器时,应用服务器会调用rack对请求进行包装,然后在 调用你的rack应用程序,rack程序可以对请求进行分析、处理,并利用rack的响应设施进行输出,rack会将用户响应作为输出返回给ruby应用服务器。

 

二、为什么要用Rack


1、提供一个广泛支持的标准接口


Rack提供了一个标准接口,便于应用程序和应用服务器进行交互,一个Rack应用可以被任何和Rack兼容的应用服务器调用,最明显的一个例子,我们开发的rails应用或者Sinatra应用可以直接使用Webrick或者thin等服务器启动,不用做什么修改,非常方便。


2、模块化、高可重用性


Rack利用中间件实现最大程度模块化,从而提高Web应用程序部件的可重用性,从而提高开发效率


Rack中间件对Ruby Web框架也有很深远的影响:


  • 不同Web框架之间可重用Rack中间件,这意味着你编写的中间件可以在所有主流框架中 使用;


  • 可以通过不同中间件的组合组装出同一Web框架的不同变种以适应不同的需求;


  • 可以组合不同Web框架为同一个更大的系统服务。


3、简单


Rack标准简单,这就很容易让用户实现一个Web服务器或者Web框架

 

三、一个简单的Rack应用程序


1、Rack尝鲜


一个Rack程序应该符合如下条件:


  • 是一个ruby对象,且具有call方法;


  • 只携带一个参数environment;


  • 返回值为一个数组,包含status、header、body三个元素。


require 'rack'
class MyApp 
  def call(env)
    [200, {}, ["this is my app"]] 
  end
end
my_app = MyApp.new
Rack::Handler::WEBrick.run my_app, :Port => 3000


运行这段代码,在浏览器中访问 http://localhost:3000


上面这段代码就是我们实现的一个最简单的Rack应用,我们实现了一个类MyApp,他只有一 个call方法,此方法接受一个参数,返回一个数组,此数据包含status、header、body,在这 里呢,我使用WEBrick来启动这个应用,同样我也可以使用thin来启动,那么最后一句话就变成:


Rack::Handler::thin.run my_app, :Port => 3000


我们在前面说了,目前主流的ruby应用服务器都是兼容Rack接口的,其实这里呢Rack使用了 一种叫Handler(句柄)的机制来实现对众多应用服务器的支持,这些句柄都是在 Rack::Handler命名空间下的,我们可以看到这些类:


Rack::Handler::CGI
Rack::Handler::FastCGI
Rack::Handler::Mongrel
Rack::Handler::EventedMongrel
Rack::Handler::SwiftipliedMongrel
Rack::Handler::WEBrick
Rack::Handler::LSWS
Rack::Handler::SCGI
Rack::Handler::Thin


也就是说Rack缺省下对上面这些服务器支持的。


2、Rack的环境


继续回到我们刚才的应用中来,刚才代码中我们call方法接受一个参数env,那么这个env到底有什么东⻄呢,我们修改下之前的代码:


require 'rack'
class MyApp
  def call(env)
    body = get_env(env)
    [200, {"Content-type" => "text/html"}, [body]]
  end
  def get_env(env) 
    env.map {|k, v| "#{k} => #{v}" }.sort.join("<br/>")
  end 
end
my_app = MyApp.new
Rack::Handler::WEBrick.run my_app, :Port => 3000


这段代码中我们将env的值放到body中,在浏览器中访问http://localhost:3000我们可以看到如下内容:


GATEWAY_INTERFACE => CGI/1.1
HTTP_ACCEPT => text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 HTTP_ACCEPT_ENCODING => gzip, deflate, sdch
HTTP_ACCEPT_LANGUAGE => zh-CN,zh;q=0.8
HTTP_CACHE_CONTROL => max-age=0
HTTP_CONNECTION => keep-alive
HTTP_COOKIE => remember_token=3E02V5zkb8eAmrUKckE69A
HTTP_HOST => localhost:3000
HTTP_UPGRADE_INSECURE_REQUESTS => 1
HTTP_USER_AGENT => Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36 HTTP_VERSION => HTTP/1.1
PATH_INFO => /
QUERY_STRING =>
REMOTE_ADDR => ::1
REMOTE_HOST => localhost
REQUEST_METHOD => GET
REQUEST_PATH => /
REQUEST_URI => http://localhost:3000/
SCRIPT_NAME =>
SERVER_NAME => localhost
SERVER_PORT => 3000
SERVER_PROTOCOL => HTTP/1.1
SERVER_SOFTWARE => WEBrick/1.3.1 (Ruby/2.0.0/2015-02-25)
rack.errors => #
rack.hijack => #<proc:0x007f843a9054a0@ users=”” yangye=”” .rvm=”” gems=”” ruby- 2.0.0-p643=”” rack-1.6.4=”” lib=”” rack=”” handler=”” webrick.rb:76=”” (lambda)=””> rack.hijack? => true
rack.hijack_io =>
rack.input => # rack.multiprocess => false rack.multithread => true rack.run_once => false rack.url_scheme => http rack.version => [1, 3]


我们可以看出来,env的key主要包含大写的CGI的头,以及rack自己的环境变量 修改我们的url,我们可以看到返回的env中的一些键值会有不同的变化,各位自己尝试下

从上面我们可以看出来,我们编写一个rack应用程序,可以通过env获取用户的请求的方法, 路径名,查询参数,从而调用不同的应用程序去处理,非常高效的去实现各种各样的应用,但 是如果直接存取环境参数会很麻烦,我们还得自己去解析查询参数,维护用户会话信息,不过 好在rack本身提供了丰富的API帮我们解决了这些问题,下面来看两个重要的类Request和 Response。


3、常用的类


Request


这个类的定义是在rack-1.6.4/lib/rack/request.rb 我们要创建一个Request对象很简单,只需要将env传给其构造函数即可 Rack::Request.new(env) 不难想象,Request里面的诸多方法其实就是对env的解析,感兴趣可以去阅读下源码 Response

这个类的定义是在/rack-1.6.4/lib/rack/response.rb。


创建一个Response对象也很简单:Rack::Response.new


这个类的构造函数如下:


def initialize(body=[], status=200, header={}) 
  @status = status.to_i
  @header = Utils::HeaderHash.new.merge(header)
  @chunked = CHUNKED == @header[TRANSFER_ENCODING] 
  @writer = lambda { |x| @body << x }
  @block = nil
  @length = 0
  @body = []
  if body.respond_to? :to_str 
    write body.to_str
  elsif body.respond_to?(:each) 
    body.each { |part| write part.to_s }
  else
    raise TypeError, "stringable or iterable required"
  end
  yield self if block_given? 
end


也就是说,我们在实例化对象时也可以直接传递status、header、body或者我们先实例化对象然后在修改这三个属性。

相关文章
|
1月前
|
存储 负载均衡
高可用集群相关术语扫盲篇
关于高可用集群相关术语的扫盲篇,涵盖了集群类型、系统可用性、系统故障、提升系统高可用性的解决方案、高可用服务的组件、共享存储、网络分区、双节点集群、HA Cluster实现方案和高可用集群后端存储等多个方面的内容。
37 1
高可用集群相关术语扫盲篇
|
2月前
|
资源调度 分布式计算 算法
【揭秘Yarn调度秘籍】打破资源分配的枷锁,Hadoop Yarn权重调度全攻略!
【8月更文挑战第24天】在大数据处理领域,Hadoop Yarn 是一种关键的作业调度与集群资源管理工具。它支持多种调度器以适应不同需求,默认采用FIFO调度器,但可通过引入基于权重的调度算法来提高资源利用率。该算法根据作业或用户的权重值决定资源分配比例,权重高的可获得更多计算资源,特别适合多用户共享环境。管理员需在Yarn配置文件中启用特定调度器(如CapacityScheduler),并通过设置队列权重来实现资源的动态调整。合理配置权重有助于避免资源浪费,确保集群高效运行,满足不同用户需求。
41 3
|
4月前
|
Kubernetes 关系型数据库 网络架构
ray集群部署vllm的折磨
概括如下: 在构建一个兼容多种LLM推理框架的平台时,开发者选择了Ray分布式框架,以解决资源管理和适配问题。然而,在尝试集成vllm时遇到挑战,因为vllm内部自管理Ray集群,与原有设计冲突。经过一系列尝试,包括调整资源分配、修改vllm源码和利用Ray部署的`placement_group_bundles`特性,最终实现了兼容,但依赖于非官方支持的解决方案。在面对vllm新版本和Ray部署的`reconfigure`方法问题时,又需权衡和调整实现方式。尽管面临困难,开发者认为使用Ray作为统一底层仍具有潜力。
|
并行计算 算法 NoSQL
基于ray 多进程调度管理能力优化networks节点最短路径的并行计算
原生的networkx实现的只能在节点介数度量性任务上达到单核心100的cpu利用率。通过对源码的几行改造我们可以实现多核心的100的利用率。接下来要我们来一起看看是如何实现的多核心100的利用率。
150 0
基于ray 多进程调度管理能力优化networks节点最短路径的并行计算
ES脑裂问题解决方案
ES脑裂问题解决方案
166 0
|
资源调度
每日积累【Day 5】Yarn高可用架构重温
每日积累【Day 5】Yarn高可用架构重温
每日积累【Day 5】Yarn高可用架构重温
|
设计模式 中间件 应用服务中间件
Rack相关知识梳理(二)
一、Rack中间件 1、什么是中间件 中间件其实就是Ruby应用服务器和Rack应用程序之间执行的代码 2、一个简单的例子 $LOAD_PATH.unshift(File.dirname(__FILE__)) require 'rack' require 'decorator' my_app = l
258 0
|
中间件
Rack相关知识梳理(三)
Rack为编写Web应用以及Web框架提供了很多便利的工具,那么这一节,我们实现一个最简单的Web框架。 一、Web框架应该具备什么功能 对request和response的存取 路由:根据不同URL执行不同程序 能够处理cookies 能够存取session 能够生成日志 ...... 看上去挺麻
313 0
|
安全 程序员 项目管理
如何做好技术 Team Leader?
作为一个技术TL(Team Leader),除了自身技能,还会面临诸多团队管理上的困难和挑战。如何定义和明确团队的目标?怎样建立优秀的工程文化?让团队长期发挥战斗力和创新能力的核心是什么?本文作者基于四年的团队管理经验,分享他在招聘、目标管理、团队沟通和工程文化等方面的思考与总结,介绍相关的经验方法,并推荐几本关于体验、思考的书籍。希望对同学们有所启发。
如何做好技术 Team Leader?
|
Cloud Native 安全 Java
阿里四年技术 TL 的得失总结:如何做好技术 Team Leader
子曰:吾日三省吾身,反思是人类进化出来的一项异常宝贵的能力。我在阿里带团队也有四年多的时间,有必要总结一下此间得失;另外,前几天和一个刚开始带团队的同学聊天,他觉得角色转变对于他有不小的挑战,因此我想做一点不算成熟的总结并分享出来。
阿里四年技术 TL 的得失总结:如何做好技术 Team Leader