accelerate your rails site with automatic generation-based action caching

45
Accelerate Your Rails Site with Automatic Generation-Based Action Caching Rod Cope, CTO and Founder OpenLogic, Inc. Wednesday, July 29, 2009

Upload: elliando-dias

Post on 09-May-2015

2.356 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

Accelerate Your Rails Site with Automatic Generation-Based Action CachingRod Cope, CTO and FounderOpenLogic, Inc.

Wednesday, July 29, 2009

Page 2: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Goal

Built-in caching is hard:

Learn how to automate it tomake the pain go away

2

Wednesday, July 29, 2009

Page 3: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Agenda

IntroductionBuilt-in cachingAutomatic generation-based cachingBonus materialConclusion & recommendations

3

Wednesday, July 29, 2009

Page 4: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Introduction

Rod CopeCTO & Founder of OpenLogic25 years of software development experienceIBM Global Services, Anthem, Ericsson, many more

OpenLogic, Inc.Governance, SLA support, security updates, and

indemnification for over 500 Open Source packagesDozens of Fortune 500 customersOSS Census (osscensus.org)

Global, community effort to catalog use of open source

4

Wednesday, July 29, 2009

Page 5: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential 5

No Spoon Feeding

Wednesday, July 29, 2009

Page 6: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Don’t Panic

scotduke.com

6

Wednesday, July 29, 2009

Page 7: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Reasons for Caching

Lots of hits, speed is kingGoogle

7

Wednesday, July 29, 2009

Page 8: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential 8

Wednesday, July 29, 2009

Page 9: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Reasons for Caching

Lots of hits, speed is kingGoogle

Complex hits, richness is kingOpenLogic’s OLEX

9

Wednesday, July 29, 2009

Page 10: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential 10

Wednesday, July 29, 2009

Page 11: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Rails Caching Background

Page cachingUberfast, little controlHighly dynamic site? Move on.

Action cachingFast, lots of controlExpiration hell

Fragment cachingExpiration hell

11

Wednesday, July 29, 2009

Page 12: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Problems with Rails Caching

Caching is easy to implement“Site’s borked again - turn off caching.”Hard to clear (the right) caches when you’re mixing and matching different types, styles, developers, plugins, etc.

12

Wednesday, July 29, 2009

Page 13: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Automatic Generation-Based CachingGeneration-based

Partition the cache so that every state change increments the “generation”

AutomaticAny action that could possibly change state bumps the countLet memcached overwrite old generations

Very conservativeNo domain knowledgeDon’t cache errors, AJAX, redirects, flash notices, etc.

13

Wednesday, July 29, 2009

Page 14: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Overview

Yourcode

Database memcachedRender View

Cache helper

Rails plumbing

Rails plumbing

Non-cached Cached

14

Wednesday, July 29, 2009

Page 15: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Key Value

/packages/1 <html><body>Rails</body></html>

/packages/2 <html><body>Ruby</body></html>

Cache = Hash

Wednesday, July 29, 2009

Page 16: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Key Value

/gen/1/packages/1 <html>Rails</html>

/gen/1/packages/2 <html>Ruby</html>

Generational Cache

Wednesday, July 29, 2009

Page 17: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Key Value

/gen/1/packages/1 <html>Rails</html>

/gen/1/packages/2 <html>Ruby</html>

/gen/2/packages/1 <html>Ruby on Rails</html>

Generational Cache

Wednesday, July 29, 2009

Page 18: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

memcached is your friend

Very fastDon’t worry about removing old entriesmemcached will automatically drop the oldest keys when it runs low on memoryRun it on your web servers if you have the RAM

18

Wednesday, July 29, 2009

Page 19: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Cache Helper

No cache-related code sprinkled throughout every model, view, and/or controllerUse a global “around” filterAutomatically increment (scoped) generation count upon POST, PUT, or DELETEHandle event recording and playback (optional)

19

Wednesday, July 29, 2009

Page 20: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Cache Helper Code (in “around” filter)key = make_auto_cache_key(request.request_uri)output = Rails.cache.read(key)

if output render :text => output return

else yield unless response.redirected_to || flash[:notice]

Rails.cache.write(key, response.body) endend

20

Wednesday, July 29, 2009

Page 21: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Cache Key

def make_auto_cache_key(key) ol_gen = Rails.cache.fetch(OL_GEN) { "1" } "olex/#{ol_gen}"end

21

Wednesday, July 29, 2009

Page 22: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

“Clear” the Cache

POST, PUT, or DELETE “clears” the cache

def maybe_clear_auto_cache return if request.get? gen = Rails.cache.fetch(OL_GEN) { "1" } Rails.cache.write(OL_GEN, (gen.to_i + 1).to_s)end

22

Wednesday, July 29, 2009

Page 23: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Controller Customization

Some controllers may need special cache control (e.g., user-specific cache, disable cache for certain methods)

olex_auto_cache_is_specific_to_user :only => :show

Note: the cache may still need to be cleared when skipping cache usage!

skip_filter :olex_auto_cache after_filter :maybe_clear_olex_auto_cache

23

Wednesday, July 29, 2009

Page 24: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Cache Partitioning

Make it impossible for users of different corporations and permission levels to see each other’s stuff, access the same cache, clear somebody else’s cache, etc.Make sure any “global” changes clear all cachesUse a cache hierarchy

/olex/<gen #>/corp/<corp #>/<corp gen #>/roles/<role #s>/URLMD5 the key (memcached has a 250 char limit)

Extra credit: Use the key as an etag

24

Wednesday, July 29, 2009

Page 25: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

/olex/13/corp/72/2/roles/2,7,19/packages/2<html>

Rails (unsupported)</html>

Partitioned Cache

Global generation

Wednesday, July 29, 2009

Page 26: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

/olex/13/corp/72/2/roles/2,7,19/packages/2<html>

Rails (unsupported)</html>

Partitioned Cache

Corporate account ID

Wednesday, July 29, 2009

Page 27: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

/olex/13/corp/72/2/roles/2,7,19/packages/2<html>

Rails (unsupported)</html>

Partitioned CacheCorporation #72’s generation

Wednesday, July 29, 2009

Page 28: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

/olex/13/corp/72/2/roles/2,7,19/packages/2<html>

Rails (unsupported)</html>

Partitioned Cache

Current user’s role IDs

Wednesday, July 29, 2009

Page 29: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

/olex/13/corp/72/2/roles/2,7,19/packages/2<html>

Rails (unsupported)</html>

Partitioned Cache

URL

Wednesday, July 29, 2009

Page 30: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

/olex/13/corp/72/2/roles/2,7,19/packages/2<html>

Rails (unsupported)</html>

/olex/13/corp/72/2/roles/2,7,19,22/packages/2<html>

Rails (manager secret!)</html>

/olex/14/corp/72/2/roles/2,7,19/packages/2<html>

Rails (supported)</html>

/olex/14/guest/packages/2 <html>Rails</html>

Partitioned Cache

Wednesday, July 29, 2009

Page 31: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Cache Key

def make_auto_cache_key(key, user = nil) ol_gen = Rails.cache.fetch(OL_GEN) { "1" } ol_prefix = "olex/#{ol_gen}" if user.nil? && self.respond_to?("current_user") user = current_user end ca = get_corporate_account(user) ...

31

Wednesday, July 29, 2009

Page 32: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Cache Key

...if user.is_corp_user? corp_gen = Rails.cache.fetch(corp_gen_key(ca)){"1"} final_key = make_corp_key(user, ca, key, corp_gen)else final_key = "guest#{key}"end

32

Wednesday, July 29, 2009

Page 33: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Corporate Cache Key

def make_corp_key(user, ca, key, corp_gen) roles = role_string(user) "/corp/#{ca.id}/#{corp_gen}/roles/#{roles}#{key}"end

def role_string(user) Rails.cache.fetch("roles/#{user.id}") do user.role_string endend

33

Wednesday, July 29, 2009

Page 34: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Benefits

Never have to explicitly expire anythingCan’t get an expired page

Generation numbers also stored in memcachedCache hierarchy is like a directory structure

Easy to grokCan’t run out of “disk space”!

34

Wednesday, July 29, 2009

Page 35: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Does it really work?

In production for over a year - a few minor issuesSee Gotchas

Huge performance improvement for us, almost no developer pain

e.g., needed cookie-based “Welcome Joe!”Great for “passive” caching

Write caching code once, enjoy it foreverLots of room for more aggressive caching

35

Wednesday, July 29, 2009

Page 36: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Gotchas

Easy to forget to make AJAX calls use RESTmethod:'get','post', 'put', or 'delete'

Test with and without caching, and test the caching itself!Caching doesn’t help the first hit

Mitigate by pre-caching when feasible

36

Wednesday, July 29, 2009

Page 37: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Recommendations

The “safety first” caching implementation - use itIt’s still action caching, so don’t expect page caching performanceMeasure the result - not all pages will benefit and there is some overhead

37

Wednesday, July 29, 2009

Page 38: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Bonus

Asynchronous pre-caching

Event recording and playback

38

Wednesday, July 29, 2009

Page 39: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Async pre-caching pages at logon

Use Workling/Starling for asyncWhen user logs on, make async callAsync call runs through list of URL’s and hits them on behalf of the currently logged on userNeed secret back-door logon in application.rb

Use big scary session key in environment.rb

39

Wednesday, July 29, 2009

Page 40: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Event Recording

Q: What if you want to record the fact that something happened even though the page was automatically cached and served?A: Watch it while being cached, record what happens in memcached, play it back later when serving cached version

40

Wednesday, July 29, 2009

Page 41: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Summary

Rails built-in caching takesa lot of on-going work

Easy to screw it up

Automatic caching can be writtenonce and enjoyed forever

Much harder to screw up

Still possible to use more aggressive techniques selectively

41

Wednesday, July 29, 2009

Page 42: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Any questions for Rod?

42

Wednesday, July 29, 2009

Page 43: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Resources

memcached: http://www.danga.com/memcached/Workling: http://github.com/purzelrakete/workling/tree/masterStarling: http://rubyforge.org/projects/starling/OLEX: http://olex.openlogic.com

43

Wednesday, July 29, 2009

Page 44: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

Credits

Unless otherwise indicated, photos were licensed from BigStockPhoto.com

44

Wednesday, July 29, 2009

Page 45: Accelerate Your Rails Site with Automatic Generation-Based Action Caching

OpenLogic Company Confidential

OpenLogic is hiring!

Rails guru?Live near Denver, Colorado?Love Open Source?

Come see me!

45

Wednesday, July 29, 2009