serving premium videos using ruby on rails

165 views Asked by At

I am stuck with a performance related issue. I have a ROR application running on VPS. I am posting my question here after having spent lot of time on internet regarding this issue and was not able to find reliable solution. My ROR application has nearly 300 premium videos and 200 pdf's, after registration user is allowed to watch Free Videos. If the user upgrades account by making payment, then he/she can watch premium videos.

Currently I am serving video file using send file method, below is the code.

  SEND_FILE_METHOD = :default

  def download

    head(:not_found) and return if (track = Video.find_by_id(params[:id])).nil?
    #head(:forbidden) and return unless track.downloadable?(current_user) 

    path = track.video.path(params[:style])

    head(:bad_request) and return unless File.exist?(path) && params[:format].to_s == File.extname(path).gsub(/^\.+/, '')
    contenttype = MIME::Types.type_for(path).first.content_type # => "image/gif"
    send_file_options = { :type =>  contenttype  }

    case SEND_FILE_METHOD
      when :apache then send_file_options[:x_sendfile] = true
      when :nginx then head(:x_accel_redirect => path.gsub(Rails.root, ''), :content_type => send_file_options[:type]) and return
    end

    send_file(path, send_file_options)
  end

My question here is,

  1. what is this right way to serve premium video's via rails application.(My Client VPS has only 1 GB RAM ) and videos are saved in FILE SYSTEM on VPS. My concern is that, if my application gets more than a 100 request at a time, ROR app may fail to server request. I also thought of placing it in public folder, but the videos are only for Paid user, so I cant put them in public videos.

Any help or link to solution is highly appreciated.. Many Thanks :)

2

There are 2 answers

3
Zach Moshe On

If you really want to support serving static content at high volumes, don't put the load on your web server, especially if it's not that strong.
Keep your server resources for stuff that are your core business logic (like managing accounts and permissions) and delegate serving static content to other dedicated services.

I'm only familiar with the AWS suite so I can recommend the following:

  • For the PDFs (and other files) - Store them on AWS S3 and have your app point to that location. You can create an address within your domain, and can generate separate links for different customers (with expiration) so you can control who accesses the files and for how long.
  • For the videos - If you serve them as regular files (e.g. download an mp4) - I'd go with the same S3 solution. If you plan to stream them to clients - look at CloudFront Streaming
  • CloudFront (AWS implementation of a CDN) in general is a good idea if you have clients from different geographies and you want to serve their content from the closest location to them.

As for prices - you can see at the products' pages. It's pretty cheap in my opinion and definitely worth the money considering the scalability it gives you. You might have some learning-curve at the beginning to start working with their APIs but it's really not that difficult and plenty of tutorials are available.

Equivalent solutions (from other vendors) do exist. I'd recommend looking around to see what fits you best.

Good luck!

0
Frederick Cheung On

If possible, you should consider using something similar to S3 or a CDN if possible. These are built to get files to customers quickly and will result in zero load on your server once you've handed the file off to them.

If you want to stick with serving files from your vps then you should look at X-Sendfile (apache) or X-Accel-Redirect (nginx). With these the file is still served by your VPS but it is handled by the web server rather than your rails code.

Rails will use generate these headers for you when you use send_file, but for this to work you need to configure your web server appropriately.

On apache this means installing the sendfile module, on nginx you have to configure which bits of the filesystem are accessible. The code for Rack::Sendfile (the mechanism rails uses) explains how to do this