Skip to content

gotcha with rack cache

Ivan Osadchii edited this page Jul 4, 2011 · 1 revision

(draft) Gotcha with Rack::Cache

А всегда ли добавление Rack::Cache увеличивает (или хотя бы не портит) производительность?

Рассмотрим такой случай:

  • есть сайт с картинками в обычных .jpg файликах

  • эти .jpg отдаются рельсами (нам это нужно из соображений красивых урлов или из-за авторизации - не столь важно)

  • догадываясь, что напрягать рельсо-сервер отдачей статики не есть хорошо, мы используем send_file

    expires_in 1.year
    if stale? :last_modified => File.mtime(path), :public => true
      send_file path, :type => File.mime_type(path), :disposition => 'inline'
    end

Все работает неплохо, картинки отдаются ngnix'ом через X-Accel-Redirect, кэшируются в браузере - девелопер почти счастлив.

Но теперь добавим сюда Rack::Cache (он нам нужен для каких-то других страниц). Так как наши респонсы с картинками проходят через rack-cache и имеют заголовок Cache-Control: max-age=..., public, он их пытается сохранять и использовать.

Проблема возникает, когда юзер, не имеющий копии картинки в кэше бразуера, обращается за сохраненным в rack-cache образцом. В этом случае действия библиотеки, в конце концов, сведутся к

        File.open(path, 'rb') { |io| Marshal.load(io) }

path в данном случае - путь к сохраненной в tmp/cache/ копии

Marshal.load - вызов СИшной библиотеки, занимающейся сериализацией

То есть, вместо того, чтобы просто сказать фронтенду "отдай-ка юзеру вооон тот файлик" (X-Accel-Redirect), rack-cache открывает файл, читает его, десериализует и радостно отдает через рельсо-сервер.

OK, rack-cache оказался несколько умнее

Clone this wiki locally