在不考虑成本的情况下部署低流量 rails 应用程序的最佳实践

Best practice for deploying low traffic rails app without cost concerns

我的问题

部署 rails 应用程序时要避免的与成本相关的陷阱?

欢迎攻击,因为它会教会我期待什么并让自己做好准备。
但是,我宁愿避免在月底支付大额账单。

云托管服务好用吗?

我选择 AWS 是因为它看起来可扩展,而且我认为以后可以避免依赖其他服务。
我不后悔,但 AWS 是压倒性的,如果有更简单的服务,我应该使用它。

我目前关注的问题

计费警报很有用,但没有自动关机我感觉有点不舒服,休息一下,进入丛林或有人居住的岛屿,在那里我得不到 INTERNET 连接通知或关闭我的服务...

针对我的案例的明显修复

停止使用 S3 并将用户上传保存到我可以控制缩放行为的数据库。但是,大多数人似乎都在使用带有载波的S3,为什么?

我在做什么

使用以下方法制作我的第一个主页:

编辑


最后,我找不到任何真正解决 S3 无上限问题的方法。

以下是我的笔记。
我猜 S3 有一些基本的内置防御攻击,因为我没有听说过有人使用 S3 托管静态网站并收到超过 10000 美元的账单的悲惨故事,尽管亚马逊的防御能力如何,这种情况仍然可能发生是。

缓解

定期检查 s3 日志文件并在这些文件的累积大小过大时调用禁用 s3 资源服务的操作的脚本。
S3 日志有时需要一个多小时才能可用,因此这不是解决方案,但聊胜于无。

class LogObserver
  def initialize
    aws_conf = Aws.config.update({
      access_key_id: ENV['AWS_ACCESS_KEY_ID'],
      secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
      region: 'ap-northeast-1'})
    @bucket_name="bucket name that holds s3 log"

    @last_checked_log_timestamp = Time.now.utc
    log "started at: #{Time.now}"
  end

  def run
    bucket = Aws::S3::Resource.new.bucket(@bucket_name)
    while true
      prv_log_ts = @last_checked_log_timestamp
      log_size = fetch_log_size(bucket)

      log "The total size of S3 log accumulated since last time this script was executed: #{log_size}"

      time_range = @last_checked_log_timestamp - prv_log_ts # float
      log_size_per_second = log_size/time_range

      if log_size_per_second > (500.kilobyte/60)
        log "Disabling S3 access as S3 log size is greater than expected."

        `curl localhost/static_pages/disable_s3`
      end

      sleep 60*60 
    end
  end
  def log text
    puts text
    File.open('./s3_observer_log.txt','a') do |f|
      f << text
    end
  end

  def fetch_log_size(bucket)
    log_size=0
    bucket.objects(prefix: 'files').each do |o|
      time_object = o.last_modified


      if time_object < @last_checked_log_timestamp
        next
      end
      @last_checked_log_timestamp = time_object
      log_size += o.size.to_i
    end  
    return log_size
  end
end

耙任务:

namespace :s3_log do
  desc "Access S3 access log files and check their cumulative size. If the size is above the expected value, disables s3 access."
  task :start_attack_detection_loop do
    require './s3_observer.rb'
    id=Process.fork do
      o=LogObserver.new
      o.run
    end
    puts "Forked a new process that watches s3 log. Process id: #{id}"
  end
end

控制器动作:

  before_action :ensure_permited_ip, only: [:enable_s3, :disable_s3]
  def enable_s3
    # allow disabling s3 only from localhost
    CarrierWave.configure do |config|
      config.fog_authenticated_url_expiration = 3 
    end
  end
  def disable_s3
    # allow disabling s3 only from localhost
    CarrierWave.configure do |config|
      config.fog_authenticated_url_expiration = 0 
    end
  end
  private
  def ensure_permited_ip
    if request.remote_ip!= "127.0.0.1" # allow access only from localhost
      redirect_to root_path
    end
  end

宝石:

gem 'aws-sdk-rails'
gem 'aws-sdk-s3', '~> 1'

我的经验有限,但我的建议是:

Cost related pit falls to avoid when deploying rails app?

  • 如果您要使用后台作业,请使用 rufus-scheduler 而不是 sidekiqdelayed_job,因为它在您的 rails server 之上运行并且不需要额外的内存/额外的专用进程。这允许您获得 smallest/cheapest 可能的实例:t2.nano,我之前做过一次。

Easy cloud hosting services to use?

  • Heroku 将是一个不错的选择,因为它很容易设置。但是,如果您这样做是为了体验,我建议您在 3 个月前购买像 AWS EC2 or Linode. I recently migrated my server from AWS to Vpsdime 这样的非托管主机,因为它便宜且内存大;到目前为止一切顺利。

My current concern

  • 对于 carrierwave,您可以限制 S3 访问。参见 reference. This then prevents hotlinking and would then require a user to view your Rails pages first in order to download or view or show the S3 files. Now that Rails now have control over the S3 files, you can just simply use something like Rack::Attack to prevent DDOS or excessive requests. If your Rails app is configured with Apache or Nginx, you can instead set up DDOS rules there instead of using Rack::Attack. Or, if you are gonna be using AWS load balancer to manage / route the requests, then you can use AWS Shield ... 虽然还没有真正使用过它。