首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用于监控7天流量的机架中间件

用于监控7天流量的机架中间件
EN

Stack Overflow用户
提问于 2015-05-24 22:21:55
回答 1查看 56关注 0票数 0

我需要一些帮助来理解如何开始这个项目。

基本我想防止我的网站从DDOS攻击,我想写我的自定义机架应用程序。

有没有人能在这里给我指点一下。

EN

回答 1

Stack Overflow用户

发布于 2020-12-22 18:20:06

据我所知,这只是为了学习的目的,所以这里是如何实现这一点的小分类。为了在生产中使用它,我绝对推荐使用Rack Throttle,因为在这个简单的例子中有许多我们没有涵盖的角落情况和选项。

这是最小的Rack中间件,它只打印出IP

代码语言:javascript
复制
#!/usr/bin/env rackup

require "rack"

class Limiter
  attr_reader :app

  def initialize(app)
    @app = app
  end

  def call(env)
    request = Rack::Request.new(env)
    puts request.ip
    app.call(env)
  end
end

use Limiter

run lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, world!\n"]] }

中间件必须是类,因为它们需要有一个初始化器,它将被传递到链中的下一个应用程序。call方法获取请求环境,执行它需要做的任何事情,然后调用下一个应用程序。我们的中间件现在只是打印出IP地址。

https://github.com/rack/rack/blob/master/lib/rack/request.rb#L354 https://thoughtbot.com/upcase/videos/rack

现在我们可以存储每个ip地址的请求计数,并在超过限制时阻止请求:

代码语言:javascript
复制
#!/usr/bin/env rackup

require "rack"

class Limiter
  attr_reader :app, :options, :counter

  def initialize(app, options)
    @app = app
    @options = options
    @counter = {}
  end

  def call(env)
    request = Rack::Request.new(env)

    if counter[request.ip].to_i > options[:max].to_i
      [200, {'Content-Type' => 'text/plain'}, ["You are blocked, request count: #{counter[request.ip]}\n"]]
    else
      counter[request.ip] ||= 0
      counter[request.ip] += 1
      app.call(env)
    end
  end
end

use Limiter, max: 1

run lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, world!\n"]] }

如果您执行此应用程序,它将在第一次请求后阻止您。

您可以看到,我们现在使用一个选项max: 1来初始化中间件,我们可以从options在我们的中间件中访问它。我们使用它来确定何时阻止请求。

我们还初始化一个简单的散列,在其中存储每个IP地址的请求计数。请注意,只有当您只有一台web服务器时,这才能起作用。如果您有更多的服务器,则需要在服务器之间同步计数。不错的选择是Redis或Memcache。

一般来说,Rack Throttle代码的可读性很好,所以我建议通读一遍。大多数逻辑都是在Limiter class中实现的,大多数其他类都继承了它。

编辑

问题作者提出了这个问题。

通过相同的解决方案,你的意思是这些gem具有跟踪7天流量的内置功能,如果是,那么你能解释一下如何做到这一点吗?

虽然AFAIK Rack::Throttle还没有实现这个功能,但是通过继承TimeWindow可以很容易地添加它

代码语言:javascript
复制
  class Weekly < RackThrottle::TimeWindow
    ##
    # @param  [#call]                  app
    # @param  [Hash{Symbol => Object}] options
    # @option options [Integer] :max   (3600)
    def initialize(app, options = {})
      super
    end

    ##
    def max_per_week(request = nil)
      @max_per_week ||= options[:max_per_week] || options[:max] || 3_600 * 7
    end

    alias_method :max_per_window, :max_per_week

    protected

    ##
    # @param  [Rack::Request] request
    # @return [String]
    def cache_key(request)
      # %U returns the calendar week
      [super, Time.now.strftime('%U')].join(':')
    end
  end

如果你想有一个滚动跟踪器,你需要每天计数,然后获取最近7天的数据。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30424530

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档