Caching and tuning fun for high scalability Wim Godden Cu.be Solutions Conference Jan 28, 2011
Who am I ? <ul><li>Wim Godden
Owner of Cu.be Solutions (http://cu.be)
PHP developer since 1997
Developer of OpenX
Zend Certified Engineer
Zend Framework Certified Engineer
MySQL Certified Developer </li></ul>
Who are you ? <ul><li>Developers ?
System/network engineers ?
Managers ?
Caching experience ? </li></ul>
Caching and tuning fun for high scalability Wim Godden Cu.be Solutions Conference Jan 28, 2011
Goals of this tutorial <ul><li>Everything about caching and tuning
A few techniques
-> Increase reliability, performance and scalability
5 visitors/day -> 5 million visitors/day
(Don't expect miracle cure !) </li></ul>
Goals of this tutorial <ul><li>Concepts & techniques
How to do stuff
How  NOT  to do stuff </li></ul>
LAMP
LAMP
LAMP
LAMP
Architecture
Caching
What's caching ?
What is caching ? select * from article join user on article.user_id = user.id order by created desc limit 10
Caching goals - 1 st  goal <ul><li>Reduce # of request
Reduce the load </li></ul>
Caching goals - 2 nd  goal
Some figures <ul><li>Pageviews : 5000 (4000 on 10 pages)
Avg. loading time : 200ms
Cache 10 pages
Avg. loading time : 20ms
-> Total avg. loading time : 56ms
Worth it ? </li></ul>
Caching goals - 3 rd  goal <ul>Send less data across the network / Internet <li>You benefit -> lower bill from upstream pr...
Users benefit -> faster page load
Wait a second... that's mostly frontend stuff ! </li></ul>
Theory of caching DB
Theory of caching DB
Caching techniques <ul>#1 : Store entire pages <li>Company Websites
Blogs
Full pages that don't change
Render -> Store in cache -> retrieve from cache </li></ul>
Caching techniques <ul>#1 : Store entire pages </ul>
Caching techniques <ul>#2 : Store parts of a page <li>Most common technique
Usually a small block in a page
Best effect : reused on lots of pages
Can be inserted on dynamic pages </li></ul>
Caching techniques <ul>#2 : Store parts of a page </ul>
Caching techniques <ul>#3 : Store SQL queries <li>↔ SQL query cache </li><ul><ul><li>Limited in size </li></ul></ul></ul>
Caching techniques <ul>#3 : Store SQL queries <li>↔ SQL query cache </li><ul><ul><li>Limited in size
Resets on every insert/update/delete
Server and connection overhead </li></ul></ul><li>Goal : </li><ul><li>not  to get rid of DB
free up DB resources for more hits ! </li></ul><li>Better : </li><ul><li>store returned object
store group of objects </li></ul></ul>
Caching techniques <ul>#3 : Store SQL queries </ul>
Caching techniques <ul>#4 : Store complex PHP results <li>Not just calculations
CPU intensive tasks : </li><ul><li>Config file parsing
XML file parsing
Loading CSV in an array </li></ul><li>Save resources -> more resources available </li></ul>
Caching techniques <ul>#4 : Store complex PHP results </ul>
Caching techniques <ul>#xx : Your call Only limited by your imagination ! When you have data, think : <li>Creating time ?
Modification frequency ?
Retrieval frequency ? </li></ul>
How to find cacheable data <ul><li>New projects : start from 'cache anything'
Existing projects : </li><ul><li>Look at MySQL slow query log
Make a complete query log (don't forget to turn it off !)
Check page loading times </li></ul></ul>
Caching storage - MySQL query cache <ul><li>Use it
Don't rely on it
Good if you have : </li><ul><li>lots of reads
few different queries </li></ul><li>Bad if you have : </li><ul><li>lots of insert/update/delete
lots of different queries </li></ul></ul>
Caching storage - Database memory tables <ul><li>Tables stored in memory
In MySQL : memory/heap table
↔ temporary table : </li><ul><li>memory tables are persistent
temporary tables are session-specific </li></ul><li>Faster than disk-based tables
Can be joined with disk-based tables
But :  </li><ul><li>default 16MByte limit
master-slave = trouble
if you don't need join -> overhead of DB software </li></ul><li>So : don't use it unless you need to join </li></ul>
Caching storage - Opcode caching <ul>DO ! </ul>
Caching storage - Opcode caching <ul><li>APC </li><ul><li>De-facto standard
Will be in PHP core in 5.4 ? 5.5 ? 6.0 ?
PECL or packages </li></ul><li>eAccelerator
Zend Accelerator </li></ul>
Caching storage - Opcode caching <ul><li>APC </li><ul><li>De-facto standard
Will be in PHP core in 5.4 ? 5.5 ? 6.0 ?
PECL or packages </li></ul><li>eAccelerator
Zend Accelerator
X-Cache
WinCacheForPhp </li></ul>PHP PHP + APC PHP + eAccelerator 42.18 req/sec 206.20 req/sec 211.49 req/sec
Caching storage - Disk <ul><li>Data with few updates : good
Caching SQL queries : preferably not
DON'T  use NFS or other network file systems </li><ul><li>especially for sessions
high latency
locking issues ! </li></ul></ul>
Caching storage - Memory disk (ramdisk) <ul><li>Usually faster than physical disk
But : OS file caching makes difference minimal </li></ul>
Caching storage - Disk / ramdisk <ul><li>Overhead : filesystem access
Limited number of files per directory </li><ul><li>-> Subdirectories </li></ul><li>Local </li><ul><li>5 Webservers -> 5 lo...
-> Hard to scale
How will you keep them synchronized ? </li><ul><li>-> Don't say NFS or rsync ! </li></ul></ul></ul>
Caching storage - APC variable cache <ul><li>More than an opcode cache
Store user data in memory
apc_add / apc_store to add/update
apc_fetch to retrieve
apc_delete
Fast -> huge performance impact </li></ul>
Caching storage - APC variable cache <ul><li>More than an opcode cache
Store user data in memory
apc_add / apc_store to add/update
apc_fetch to retrieve
apc_delete
Fast -> huge performance impact
Session support !
Downside : </li><ul><li>local storage -> hard to scale
restart Apache -> cache = empty </li></ul></ul>
Caching storage - Memcache <ul><li>Facebook, Twitter, Slashdot, … -> need we say more ?
Distributed memory caching system
Key-value storage system </li><ul><li>Keys - max. 250bytes
Values - max. 1Mbyte </li></ul></ul>
Caching storage - Memcache <ul><li>Facebook, Twitter, Slashdot, … -> need we say more ?
Distributed memory caching system
Multiple machines ↔ 1 big memory-based hash-table
Key-value storage system </li><ul><li>Keys - max. 250bytes
Values - max. 1Mbyte </li></ul><li>Extremely fast... non-blocking, UDP (!) </li></ul>
Memcache - where to install
Memcache - where to install
Memcache - installation & running it <ul><li>Installation </li><ul><li>Distribution package
PECL
Windows : binaries </li></ul><li>Running </li><ul><li>No config-files
Upcoming SlideShare
Loading in...5
×

Caching and tuning fun for high scalability @ phpBenelux 2011

15,664

Published on

Slides for "Caching and Tuning fun for high scalability" talk, given @ phpBenelux Conference - Jan 28, 2011

Note that a lot of things were explained with each slide... that content is ofcourse not in the slides, so it might make some slides very unclear.

Published in: Technology
4 Comments
37 Likes
Statistics
Notes
  • excellent information.
    Thank you very much
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • thank you very much, offline reading isbeautiful :)
    really good information.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Check out the FrOScon version of the presentation, which is nearly identical. It has a download option : http://www.slideshare.net/wimg/caching-and-tuning-fun-for-high-scalability-froscon-2011-8977796
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • any chance to get a download option?
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
15,664
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
0
Comments
4
Likes
37
Embeds 0
No embeds

No notes for slide

Caching and tuning fun for high scalability @ phpBenelux 2011

  1. 1. Caching and tuning fun for high scalability Wim Godden Cu.be Solutions Conference Jan 28, 2011
  2. 2. Who am I ? <ul><li>Wim Godden
  3. 3. Owner of Cu.be Solutions (http://cu.be)
  4. 4. PHP developer since 1997
  5. 5. Developer of OpenX
  6. 6. Zend Certified Engineer
  7. 7. Zend Framework Certified Engineer
  8. 8. MySQL Certified Developer </li></ul>
  9. 9. Who are you ? <ul><li>Developers ?
  10. 10. System/network engineers ?
  11. 11. Managers ?
  12. 12. Caching experience ? </li></ul>
  13. 13. Caching and tuning fun for high scalability Wim Godden Cu.be Solutions Conference Jan 28, 2011
  14. 14. Goals of this tutorial <ul><li>Everything about caching and tuning
  15. 15. A few techniques
  16. 16. -> Increase reliability, performance and scalability
  17. 17. 5 visitors/day -> 5 million visitors/day
  18. 18. (Don't expect miracle cure !) </li></ul>
  19. 19. Goals of this tutorial <ul><li>Concepts & techniques
  20. 20. How to do stuff
  21. 21. How NOT to do stuff </li></ul>
  22. 22. LAMP
  23. 23. LAMP
  24. 24. LAMP
  25. 25. LAMP
  26. 26. Architecture
  27. 27. Caching
  28. 28. What's caching ?
  29. 29. What is caching ? select * from article join user on article.user_id = user.id order by created desc limit 10
  30. 30. Caching goals - 1 st goal <ul><li>Reduce # of request
  31. 31. Reduce the load </li></ul>
  32. 32. Caching goals - 2 nd goal
  33. 33. Some figures <ul><li>Pageviews : 5000 (4000 on 10 pages)
  34. 34. Avg. loading time : 200ms
  35. 35. Cache 10 pages
  36. 36. Avg. loading time : 20ms
  37. 37. -> Total avg. loading time : 56ms
  38. 38. Worth it ? </li></ul>
  39. 39. Caching goals - 3 rd goal <ul>Send less data across the network / Internet <li>You benefit -> lower bill from upstream provider
  40. 40. Users benefit -> faster page load
  41. 41. Wait a second... that's mostly frontend stuff ! </li></ul>
  42. 42. Theory of caching DB
  43. 43. Theory of caching DB
  44. 44. Caching techniques <ul>#1 : Store entire pages <li>Company Websites
  45. 45. Blogs
  46. 46. Full pages that don't change
  47. 47. Render -> Store in cache -> retrieve from cache </li></ul>
  48. 48. Caching techniques <ul>#1 : Store entire pages </ul>
  49. 49. Caching techniques <ul>#2 : Store parts of a page <li>Most common technique
  50. 50. Usually a small block in a page
  51. 51. Best effect : reused on lots of pages
  52. 52. Can be inserted on dynamic pages </li></ul>
  53. 53. Caching techniques <ul>#2 : Store parts of a page </ul>
  54. 54. Caching techniques <ul>#3 : Store SQL queries <li>↔ SQL query cache </li><ul><ul><li>Limited in size </li></ul></ul></ul>
  55. 55. Caching techniques <ul>#3 : Store SQL queries <li>↔ SQL query cache </li><ul><ul><li>Limited in size
  56. 56. Resets on every insert/update/delete
  57. 57. Server and connection overhead </li></ul></ul><li>Goal : </li><ul><li>not to get rid of DB
  58. 58. free up DB resources for more hits ! </li></ul><li>Better : </li><ul><li>store returned object
  59. 59. store group of objects </li></ul></ul>
  60. 60. Caching techniques <ul>#3 : Store SQL queries </ul>
  61. 61. Caching techniques <ul>#4 : Store complex PHP results <li>Not just calculations
  62. 62. CPU intensive tasks : </li><ul><li>Config file parsing
  63. 63. XML file parsing
  64. 64. Loading CSV in an array </li></ul><li>Save resources -> more resources available </li></ul>
  65. 65. Caching techniques <ul>#4 : Store complex PHP results </ul>
  66. 66. Caching techniques <ul>#xx : Your call Only limited by your imagination ! When you have data, think : <li>Creating time ?
  67. 67. Modification frequency ?
  68. 68. Retrieval frequency ? </li></ul>
  69. 69. How to find cacheable data <ul><li>New projects : start from 'cache anything'
  70. 70. Existing projects : </li><ul><li>Look at MySQL slow query log
  71. 71. Make a complete query log (don't forget to turn it off !)
  72. 72. Check page loading times </li></ul></ul>
  73. 73. Caching storage - MySQL query cache <ul><li>Use it
  74. 74. Don't rely on it
  75. 75. Good if you have : </li><ul><li>lots of reads
  76. 76. few different queries </li></ul><li>Bad if you have : </li><ul><li>lots of insert/update/delete
  77. 77. lots of different queries </li></ul></ul>
  78. 78. Caching storage - Database memory tables <ul><li>Tables stored in memory
  79. 79. In MySQL : memory/heap table
  80. 80. ↔ temporary table : </li><ul><li>memory tables are persistent
  81. 81. temporary tables are session-specific </li></ul><li>Faster than disk-based tables
  82. 82. Can be joined with disk-based tables
  83. 83. But : </li><ul><li>default 16MByte limit
  84. 84. master-slave = trouble
  85. 85. if you don't need join -> overhead of DB software </li></ul><li>So : don't use it unless you need to join </li></ul>
  86. 86. Caching storage - Opcode caching <ul>DO ! </ul>
  87. 87. Caching storage - Opcode caching <ul><li>APC </li><ul><li>De-facto standard
  88. 88. Will be in PHP core in 5.4 ? 5.5 ? 6.0 ?
  89. 89. PECL or packages </li></ul><li>eAccelerator
  90. 90. Zend Accelerator </li></ul>
  91. 91. Caching storage - Opcode caching <ul><li>APC </li><ul><li>De-facto standard
  92. 92. Will be in PHP core in 5.4 ? 5.5 ? 6.0 ?
  93. 93. PECL or packages </li></ul><li>eAccelerator
  94. 94. Zend Accelerator
  95. 95. X-Cache
  96. 96. WinCacheForPhp </li></ul>PHP PHP + APC PHP + eAccelerator 42.18 req/sec 206.20 req/sec 211.49 req/sec
  97. 97. Caching storage - Disk <ul><li>Data with few updates : good
  98. 98. Caching SQL queries : preferably not
  99. 99. DON'T use NFS or other network file systems </li><ul><li>especially for sessions
  100. 100. high latency
  101. 101. locking issues ! </li></ul></ul>
  102. 102. Caching storage - Memory disk (ramdisk) <ul><li>Usually faster than physical disk
  103. 103. But : OS file caching makes difference minimal </li></ul>
  104. 104. Caching storage - Disk / ramdisk <ul><li>Overhead : filesystem access
  105. 105. Limited number of files per directory </li><ul><li>-> Subdirectories </li></ul><li>Local </li><ul><li>5 Webservers -> 5 local caches
  106. 106. -> Hard to scale
  107. 107. How will you keep them synchronized ? </li><ul><li>-> Don't say NFS or rsync ! </li></ul></ul></ul>
  108. 108. Caching storage - APC variable cache <ul><li>More than an opcode cache
  109. 109. Store user data in memory
  110. 110. apc_add / apc_store to add/update
  111. 111. apc_fetch to retrieve
  112. 112. apc_delete
  113. 113. Fast -> huge performance impact </li></ul>
  114. 114. Caching storage - APC variable cache <ul><li>More than an opcode cache
  115. 115. Store user data in memory
  116. 116. apc_add / apc_store to add/update
  117. 117. apc_fetch to retrieve
  118. 118. apc_delete
  119. 119. Fast -> huge performance impact
  120. 120. Session support !
  121. 121. Downside : </li><ul><li>local storage -> hard to scale
  122. 122. restart Apache -> cache = empty </li></ul></ul>
  123. 123. Caching storage - Memcache <ul><li>Facebook, Twitter, Slashdot, … -> need we say more ?
  124. 124. Distributed memory caching system
  125. 125. Key-value storage system </li><ul><li>Keys - max. 250bytes
  126. 126. Values - max. 1Mbyte </li></ul></ul>
  127. 127. Caching storage - Memcache <ul><li>Facebook, Twitter, Slashdot, … -> need we say more ?
  128. 128. Distributed memory caching system
  129. 129. Multiple machines ↔ 1 big memory-based hash-table
  130. 130. Key-value storage system </li><ul><li>Keys - max. 250bytes
  131. 131. Values - max. 1Mbyte </li></ul><li>Extremely fast... non-blocking, UDP (!) </li></ul>
  132. 132. Memcache - where to install
  133. 133. Memcache - where to install
  134. 134. Memcache - installation & running it <ul><li>Installation </li><ul><li>Distribution package
  135. 135. PECL
  136. 136. Windows : binaries </li></ul><li>Running </li><ul><li>No config-files
  137. 137. memcached -d -m <mem> -l <ip> -p <port>
  138. 138. ex. : memcached -d -m 2048 -l 127.0.0.1 -p 11211 </li></ul></ul>
  139. 139. Caching storage - Memcache - some notes <ul><li>Not fault-tolerant </li><ul><li>Lose session data
  140. 140. Lose shopping cart data
  141. 141. ... </li></ul></ul>
  142. 142. Caching storage - Memcache - some notes <ul><li>Not fault-tolerant </li><ul><li>Lose session data
  143. 143. Lose shopping cart data
  144. 144. … </li></ul><li>Different libraries </li><ul><li>Original : libmemcache
  145. 145. New : libmemcached (consistent hashing, UDP, binary protocol, …) </li></ul><li>Firewall your Memcache port ! </li></ul>
  146. 146. Caching in PHP <?php $memcache = new Memcache(); $memcache->addServer( '172.16.0.1' , 11211); $memcache->addServer( '172.16.0.2' , 11211); $myData = $memcache->get( 'myKey' ); if ($myData === false ) { $myData = GetMyDataFromDB(); // Put it in Memcache as 'myKey', without compression, with no expiration $memcache->set( 'myKey' , $myData, false , 0); } echo $myData;
  147. 147. Where's the data ? <ul><li>Memcache client decides (!)
  148. 148. 2 hashing algorithms : </li><ul><li>Traditional </li><ul><li>Server failure -> all data must be rehashed </li></ul><li>Consistent </li><ul><li>Server failure -> 1/x of data must be rehashed (x = # of servers) </li></ul></ul><li>No replication ! </li></ul>
  149. 149. Memcache slabs <ul>(or why Memcache says it's full when it's not) <li>Multiple slabs of different sizes : </li><ul><li>Slab 1 : 400 bytes
  150. 150. Slab 2 : 480 bytes (400 * 1.2)
  151. 151. Slab 3 : 576 bytes (480 * 1.2) (and so on...) </li></ul><li>Multiplier (1.2 here) can be configured
  152. 152. Each larger slab has room for fewer items (chunks)
  153. 153. -> Store a lot of very large objects
  154. 154. -> Large slabs might be full
  155. 155. -> Rest of slabs might be free
  156. 156. -> Try to store more -> eviction of data ! </li></ul>
  157. 157. Memcache - Is it working ? <ul><li>Connect to it using telnet </li><ul><li>&quot;stats&quot; command ->
  158. 158. Use Cacti or other monitoring tools </li></ul></ul>STAT pid 2941 STAT uptime 10878 STAT time 1296074240 STAT version 1.4.5 STAT pointer_size 64 STAT rusage_user 20.089945 STAT rusage_system 58.499106 STAT curr_connections 16 STAT total_connections 276950 STAT connection_structures 96 STAT cmd_get 276931 STAT cmd_set 584148 STAT cmd_flush 0 STAT get_hits 211106 STAT get_misses 65825 STAT delete_misses 101 STAT delete_hits 276829 STAT incr_misses 0 STAT incr_hits 0 STAT decr_misses 0 STAT decr_hits 0 STAT cas_misses 0 STAT cas_hits 0 STAT cas_badval 0 STAT auth_cmds 0 STAT auth_errors 0 STAT bytes_read 613193860 STAT bytes_written 553991373 STAT limit_maxbytes 268435456 STAT accepting_conns 1 STAT listen_disabled_num 0 STAT threads 4 STAT conn_yields 0 STAT bytes 20418140 STAT curr_items 65826 STAT total_items 553856 STAT evictions 0 STAT reclaimed 0
  159. 159. Memcache - backing up
  160. 160. Memcache - deleting <?php $memcache = new Memcache(); $memcache->delete( 'myKey' ); $myData = $memcache->get( 'myKey' ); // $myData === false
  161. 161. Memcache - caching a page <?php $output = $memcache->get( 'page_' . $page_id); if ($output === false ) { ob_start(); GetMyPageInRegularWay($page_id); $output = ob_get_contents(); ob_end_clean(); $memcache->set( 'page_' . $page_id, $output, false , 600); // Cache 10 mins } echo $output;
  162. 162. Memcache - tip <ul>Page with multiple blocks ? -> use Memcached::getMulti() Warning : what if you get some hits and some misses ? </ul>
  163. 163. Naming your keys <ul><li>Key names must be unique
  164. 164. Prefix / namespace your keys !
  165. 165. Only letters, numbers and underscore
  166. 166. md5() is useful </li><ul><li>-> BUT : harder to debug </li></ul><li>Use clear names
  167. 167. Document your key names ! </li></ul>
  168. 168. Adding/updating data
  169. 169. Adding/updating data
  170. 170. Adding/updating data $memcache->delete( 'ArticleDetails__Toshiba_32C100U_32_Inch' ); $memcache->delete( 'Homepage_Popular_Product_List' );
  171. 171. Adding/updating data
  172. 172. Adding/updating data - Why it crashed
  173. 173. Adding/updating data - Why it crashed
  174. 174. Adding/updating data - Why it crashed
  175. 175. Cache stampeding
  176. 176. Cache stampeding
  177. 177. Memcache code ? DB
  178. 178. Memcache code ? DB
  179. 179. Memcache code ? DB
  180. 180. Creating cache methods static protected function getArticle ($id) { $cache = Zend_Registry:: get ( 'Zend_Cache' ); if (!$article = $cache->load( 'article_' . $id )) { $db = Zend_Registry:: get ( 'Zend_DB' ); $query = ' select article.id as art_id, article.title as art_title, article.body as art_body, date_format(article.created, &quot;%d/%m/%Y %H:%i&quot;) as art_created, user.username as use_username from article join user on article.user_id = user.id where article.id = ? ' ; $artice = $db->fetchRow($query, $id); $cache->save($articleList, 'article_' . $id ); } return $articleList; }
  181. 181. Creating cache methods static protected function getArticleUncached ($id) { $db = Zend_Registry:: get ( 'Zend_DB' ); $query = ' select article.id as art_id, article.title as art_title, article.body as art_body, date_format(article.created, &quot;%d/%m/%Y %H:%i&quot;) as art_created, user.username as use_username from article join user on article.user_id = user.id where article.id = ? ' ; return $db->fetchRow($query, $id); } static public function getArticle ($id) { if (Zend_Registry:: isRegistered ( 'Zend_Cache' )) { $cache = Zend_Registry:: get ( 'Zend_Cache' ); if (!$articleList = $cache->load( 'article_' . $id )) { $articleList = self :: getArticleUncached ($id); $cache->save($articleList, 'article_' . $id ); } } else { $articleList = self :: getArticleUncached ($id); } return $articleList; }
  182. 182. Cache stampeding - what about locking ? <ul>Seems like a nice idea, but... <li>Lock in place
  183. 183. -> lots of new connections
  184. 184. -> memory spike
  185. 185. What if the PHP process that created the lock fails ?
  186. 186. Avoids needing caching code in admin part
  187. 187. -> but what about warmup script(s) ? </li></ul>
  188. 188. Cache warmup scripts <ul><li>Used to fill your cache when it's empty
  189. 189. Run it before starting Webserver !
  190. 190. 2 ways : </li><ul><li>Visit all URLs </li><ul><li>Error-prone
  191. 191. Hard to maintain </li></ul><li>Call all cache-updating methods </li><ul><li>Means your caching code should be centralized ! </li></ul></ul><li>Make sure you have a warmup script ! </li></ul>
  192. 192. Quick word about expiration <ul><li>General rule : don't let things expire
  193. 193. Exception to the rule : things that have an end date (calendar items) </li></ul>
  194. 194. So... <ul>DON'T DELETE FROM CACHE (and don't expire unless usefull) </ul>
  195. 195. Quick-tip <ul><li>Start small -> disk or APC
  196. 196. Move to Memcache later
  197. 197. But : is your code ready ?
  198. 198. -> Use a component like Zend_Cache to switch easily ! </li></ul>
  199. 199. Time for... <ul>a break (10 min) </ul>
  200. 200. LAMP... <ul>-> LAMMP -> LANMMP </ul>
  201. 201. Nginx <ul><li>Web server
  202. 202. Reverse proxy
  203. 203. Lightweight, fast
  204. 204. 7.5% of all Websites </li></ul>
  205. 205. Nginx <ul><li>No threads, event-driven
  206. 206. Uses epoll / kqueue
  207. 207. Low memory footprint
  208. 208. 10000 active connections = normal </li></ul>
  209. 209. Nginx - a true alternative to Apache ? <ul><li>Not all Apache modules </li><ul><li>mod_auth_*
  210. 210. mod_dav*
  211. 211. … </li></ul><li>Basic modules are available
  212. 212. Some 3 rd party modules (needs recompilation !) </li></ul>
  213. 213. Nginx - Installation <ul><li>Packages
  214. 214. Win32 binaries
  215. 215. Build from source (./configure; make; make install) </li></ul>
  216. 216. Nginx - Configuration server { listen 80; server_name www.phpbenelux.eu *.phpbenelux.eu; index index.html; root /home/phpbenelux.eu/www; } server { listen 80; server_name conference.phpbenelux.eu; index index.html; root /home/phpbenelux.eu/conference; }
  217. 217. Nginx - Configuration server { listen 80; server_name www.phpbenelux.eu; root /home/phpbenelux.eu/www; location /conference { # We capture the URI and redirect it to the subdomain. rewrite conference(.*) http://conference.phpbenelux.eu$1 permanent; } }
  218. 218. Nginx - phase 1 <ul><li>Move Apache to a different port (8080)
  219. 219. Put Nginx at port 80
  220. 220. Nginx serves all statics (images, css, js, …)
  221. 221. Forward dynamic requests to Apache </li></ul>
  222. 222. Nginx - phase 1 <ul><li>Move Apache to a different port (8080)
  223. 223. Put Nginx at port 80
  224. 224. Nginx serves all statics (images, css, js, …)
  225. 225. Forward dynamic requests to Apache </li></ul>
  226. 226. Nginx for static files only server { listen 80; server_name www.phpbenelux.eu; location ~* ^.*.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|pdf|ppt|txt|tar|rtf|js)$ { expires 30d; root /home/www.phpbenelux.eu; } location / { proxy_pass http://www.phpbenelux.eu:8080; proxy_pass_header Set-Cookie; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
  227. 227. Nginx for PHP ? <ul><li>Bottleneck = PHP ? Keep it in Apache
  228. 228. Bottleneck = memory ? Go for it !
  229. 229. LANMMP to... LNMPP
  230. 230. (ok, this is getting ridiculous) </li></ul>
  231. 231. Nginx with PHP <ul><li>In the past : spawn-fcgi (from Lighttpd)
  232. 232. Now : PHP-FPM (in PHP 5.3.3 !)
  233. 233. Runs on port 9000
  234. 234. Nginx connects using fastcgi method </li></ul>location / { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param SCRIPT_FILENAME /home/www.phpbenelux.eu/$fastcgi_script_name; fastcgi_param SERVER_NAME $host; fastcgi_intercept_errors on; }
  235. 235. Nginx with PHP <ul><li>In the past : spawn-fcgi (from Lighttpd)
  236. 236. Now : PHP-FPM (in PHP 5.3.3 !)
  237. 237. Runs on port 9000
  238. 238. Nginx connects using fastcgi method </li></ul>location / { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param SCRIPT_FILENAME /home/www.phpbenelux.eu/$fastcgi_script_name; fastcgi_param SERVER_NAME $host; fastcgi_intercept_errors on; }
  239. 239. Nginx + PHP-FPM features <ul><li>Graceful upgrade
  240. 240. Spawn new processes under high load
  241. 241. Chroot
  242. 242. Slow request log ! </li></ul>
  243. 243. Nginx + PHP-FPM features <ul><li>Graceful upgrade
  244. 244. Spawn new processed under high load
  245. 245. Chroot
  246. 246. Slow request log !
  247. 247. fastcgi_finish_request() -> offline processing </li></ul>
  248. 248. Nginx + PHP-FPM - Downside <ul><li>PHP vs PHP-FPM = no performance difference
  249. 249. But : Apache + mod_php = faster
  250. 250. Why ? fastcgi connection overhead
  251. 251. Difference : 10-15%
  252. 252. Balance : Apache's memory overhead vs. fastcgi performance </li></ul>
  253. 253. LAMP
  254. 254. LAMP
  255. 255. Varnish <ul><li>Not just a load balancer
  256. 256. Reverse proxy cache / http accelerator / …
  257. 257. Caches (parts of) pages in memory
  258. 258. Careful : </li><ul><li>uses threads
  259. 259. Nginx might be faster (but doesn't have VCL) </li></ul></ul>
  260. 260. Varnish - Installation & configuration <ul><li>Installation </li><ul><li>Packages
  261. 261. Source : ./configure && make && make install </li></ul><li>Configuration </li><ul><li>/etc/default/varnish
  262. 262. /etc/varnish/*.vcl </li></ul></ul>
  263. 263. Varnish - backends + load balancing backend server1 { .host = &quot;192.168.0.10&quot;; } backend server2{ .host = &quot;192.168.0.11&quot;; } director example_director round-robin { { .backend = server1; } { .backend = server2; } }
  264. 264. Varnish - backends + load balancing backend server1 { .host = &quot;192.168.0.10&quot;; .probe = { .url = &quot;/&quot;; .interval = 5s; .timeout = 1 s; .window = 5; .threshold = 3; } }
  265. 265. Varnish - VCL <ul><li>Varnish Configuration Language
  266. 266. DSL (Domain Specific Language) </li><ul><li>-> compiled to C </li></ul><li>Hooks into each request
  267. 267. Defines : </li><ul><li>Backends (web servers)
  268. 268. ACLs
  269. 269. Load balancing strategy </li></ul><li>Can be reloaded while running </li></ul>
  270. 270. Varnish - whatever you want <ul><li>Extremely flexible through VCL </li><ul><li>Manipulate headers, request, response, ...
  271. 271. Introduce ACL
  272. 272. Detect flooding (& ban visitors)
  273. 273. Lots of hooks you can plug code onto </li></ul><li>Real-time statistics (varnishtop, varnishhist, ...)
  274. 274. ESI </li></ul>
  275. 275. Varnish - ESI <ul>Perfect for caching pages </ul>In your article page output : <esi:include src=&quot;/latest-news&quot;/>
  276. 276. Varnish - what can/can't be cached ? <ul><li>Can : </li><ul><li>Static pages
  277. 277. Images, js, css
  278. 278. Pages or parts of pages that don't change often (ESI) </li></ul><li>Can't : </li><ul><li>POST requests
  279. 279. Requests with Set-Cookie
  280. 280. Very large files (it's not a file server !)
  281. 281. User-specific content </li></ul></ul>
  282. 282. Varnish - want more ? <ul>-> &quot;Varnish, the high performance valhalla ?&quot; <ul>by Jeroen Van Dijck Tomorrow @ 13h40 </ul></ul>
  283. 283. Apache - tuning tips <ul><li>Disable unused modules -> fixes 10% of performance issues
  284. 284. Set AllowOverride to None . Enable only where needed !
  285. 285. Disable SymLinksIfOwnerMatch . Enable only where needed !
  286. 286. MinSpareServers, MaxSpareServers, StartServers, MaxClients, MPM selection -> a whole session of its own ;-)
  287. 287. Don't mod_proxy -> use Nginx or Varnish !
  288. 288. High load on an SSL-site ? -> put SSL on a reverse proxy </li></ul>
  289. 289. PHP speed - some tips <ul><li>Upgrade PHP - every minor release has 5-15% speed gain !
  290. 290. Profile your code </li><ul><li>XHProf
  291. 291. Xdebug </li></ul><li>But : turn off profilers on acceptance/production platforms ! </li></ul>
  292. 292. KCachegrind is your friend
  293. 293. PHP speed - some tips <ul><li>Most performance issues are in DB queries -> look there first !
  294. 294. Log PHP errors and review those logs !
  295. 295. Shorter code != faster code -> keep your code readable !
  296. 296. Hardware cost < Manpower cost </li><ul><li>-> 1 more server < 30 mandays of labor </li></ul><li>Keep micro-optimizations in code = last thing on list </li></ul>
  297. 297. DB speed - some tips <ul><li>Avoid NOW() -> use PHP date(&quot;Y-m-d&quot;) as a parameter </li><ul><li>Why ? Query cache ! </li></ul><li>Index, index, index ! (where needed only)
  298. 298. Use same types for joins </li><ul><li>i.e. don't join decimal with int </li></ul><li>RAND() is evil !
  299. 299. Select the right storage engine
  300. 300. Don't use mysql_pconnect()
  301. 301. Other tips -> see slides &quot;MySQL performance tuning&quot;
  302. 302. by Geert Vanderkelen </li></ul>
  303. 303. One more for the backend... HipHop <ul><li>Developed @ Facebook (runs 95% of servers)
  304. 304. Source code transformer
  305. 305. Converts PHP to C++
  306. 306. Compiles C++ (using g++) into binary code
  307. 307. Has a built-in Webserver
  308. 308. Not for you, unless > 1.000.000 views/day
  309. 309. Want more ? </li><ul><li>-> &quot;HipHop for PHP&quot; - Tomorrow @ 10h10 (Scott McVicar) </li></ul></ul>
  310. 310. Caching & Tuning @ frontend http://www.websiteoptimization.com/speed/tweak/average-web-page/
  311. 311. Caching in the browser <ul><li>HTTP 304 (Not modified)
  312. 312. Expires/Cache-Control header
  313. 313. 2 notes : </li><ul><li>Don't use POST if you want to cache
  314. 314. Don't cache user-specific pages in browser (security !) </li></ul></ul>
  315. 315. HTTP 304 First request Next requests
  316. 316. HTTP 304 with ETag First request Next requests
  317. 317. Expires/Cache-control header <ul>Cache-Control <ul><li>HTTP/1.1
  318. 318. Seconds to expiry
  319. 319. Used by browsers </li></ul></ul>First request Next requests No requests until item expires <ul>Expires <ul><li>HTTP/1.0
  320. 320. Date to expire on
  321. 321. Used by old proxies
  322. 322. Requires clock to be accurate ! </li></ul></ul>
  323. 323. Pragma: no-cache = evil <ul><li>&quot;Pragma: no cache&quot; doesn't make it uncacheable
  324. 324. Don't want caching on a page ? </li><ul><li>HTTP/1.0 : &quot;Expires : Fri, 30 Oct 1998 00:00:00 GMT&quot; (in the past)
  325. 325. HTTP/1.1 : &quot;Cache-Control: no-store&quot; </li></ul></ul>
  326. 326. Frontend tuning <ul>1. You optimize backend 2. Frontend engineers messes up -> havoc on backend 3. Don't forget : frontend sends requests to backend ! </ul>
  327. 327. Frontend tuning <ul>All frontend code impacts backend ! <li>Care about frontend
  328. 328. Test frontend
  329. 329. Check what requests frontend sends to backend </li></ul>
  330. 330. Tuning frontend <ul><li>Minimize requests </li><ul><li>Combine CSS/JavaScript files
  331. 331. Use inline images in CSS/XHTML (not supported on all browsers yet) </li></ul></ul>
  332. 332. Frontend tuning - inline CSS/XHTML images #navbar span { width: 31px; height: 31px; display: inline; float: left; margin-right: 4px; } .home { background-image: url(data:image/gif;base64,R0lGODlhHwAfAPcAAAAAAIxKAKVjCLW1tb29tcbGvc7OxtZ7ANbWztbW1tbe1t7e1uelMefn1ufn3ufn5+fv3u+MAO/v5+/v7/fGCPf35/f37//nY////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////........MEl0nGVUC6tObNnPceSFBaQVMJAxC4lo3gNOrUaFnTHoAxNm3XVxPfRq139e8BEGAjWD5bgIALw287T8AcAXLly2kjOACdc17higXSIKDO/Lpv7Qq4bw7APgBq8eOzX69InrZ6xe3dbxZffyTGkb8tdx8F+b0Xn2sFsCSBAgTM5lp63RHYnoHUudZgRgkGOGCB+43nGk4OGcQTabKx5dyJKJ7ImoUNCaRRAZYN1ppsrT3Y2gIwyjSQBAtUpABml/0IJGYd6VjQUDH9uBFkGxGm5I8dPQaRUAQUMBdhhBV25ZYUJZBcSAtSJBddWZZ5UAGPOTXlgkNVOSZdBxEwIkYu7VhYnAol5GaadRqF0Uaz0TgXnX2umVFyGakJUUAAADs=); margin-left: 4px; } <img border=0 src=&quot;data:image/gif;base64,R0lGODlhHwAfAPcAAAAAAIxKAKVjCLW1tb29tcbGvc7OxtZ7ANbWztbW1tbe1t7e1uelMefn1ufn3ufn5+fv3u+MAO/v5+/v7/fGCPf35/f37//nY/......Uaz0TgXnX2umVFyGakJUUAAADs=&quot;>
  333. 333. Tuning frontend <ul><li>Minimize requests </li><ul><li>Combine CSS/JavaScript files
  334. 334. Use inline images in CSS (not supported on all browsers yet)
  335. 335. Use CSS Sprites </li></ul></ul>
  336. 336. Tuning content - CSS sprites 11 images 11 HTTP requests 24KByte 1 images 1 HTTP requests 14KByte
  337. 337. Tuning content - CSS sprites
  338. 338. Tuning frontend <ul><li>Minimize requests </li><ul><li>Combine CSS/JavaScript files
  339. 339. Use inline images in CSS (not supported on all browsers yet)
  340. 340. Use CSS Sprites (horizontally if possible) </li></ul><li>Put CSS at top
  341. 341. Put JavaScript at bottom </li><ul><li>Max. no connections
  342. 342. Especially if JavaScript does Ajax (advertising-scripts, …) ! </li></ul><li>Avoid iFrames </li><ul><li>Again : max no. of connections
  343. 343. JavaScript onLoad() won't be triggered until loaded ! </li></ul><li>Don't scale images in HTML
  344. 344. Have a favicon.ico and cache it (don't 404 it !) </li></ul>
  345. 345. Tuning frontend <ul><li>Don't use inline CSS/JavaScript </li><ul><li>CSS/JavaScript need to be external files (minified, merged)
  346. 346. Why ? -> Cacheable by browser / reverse proxy </li></ul><li>Use GET for Ajax retrieval requests (and cache them !)
  347. 347. Optimize images (average 50-60% !)
  348. 348. Split requests across subdomains
  349. 349. Put statics on a separate subdomain (without cookies !) </li></ul>www.phpbenelux.eu www.phpbenelux.eu images.phpbenelux.eu
  350. 350. Tuning miscellaneous <ul><li>Avoid DNS lookups </li><ul><li>Frontend : don't use too many subdomains (2 = ideal)
  351. 351. Backend : </li><ul><li>Turn off DNS resolution in Apache : HostnameLookups Off
  352. 352. If your app uses external data </li><ul><li>Run a local DNS cache (timeout danger !)
  353. 353. Make sure you can trust DNS servers (preferable run your own) </li></ul></ul></ul><li>Compress non-binary content (GZIP) </li><ul><li>mod_deflate in Apache
  354. 354. HttpGzipModule in Nginx (HttpGzipStaticModule for pre-zipped statics !)
  355. 355. No native support in Varnish </li></ul></ul>
  356. 356. What else can kill your site ? <ul><li>Redirect loops </li><ul><li>Multiple requests </li><ul><li>More load on Webserver
  357. 357. More PHP to process </li></ul><li>Additional latency for visitor
  358. 358. Try to avoid redirects anyway
  359. 359. -> In ZF : use $this->_forward instead of $this->_redirect </li></ul><li>Watch your logs, but equally important...
  360. 360. Watch the logging process ->
  361. 361. Logging = disk I/O -> can kill your site !
  362. 362. Slashdot effect </li></ul>
  363. 363. Above all else... be prepared ! <ul><li>Have a monitoring system
  364. 364. Use a cache abstraction layer (disk -> APC -> Memcache)
  365. 365. Don't install for the worst -> prepare for the worst </li><ul><li>Code abstraction
  366. 366. Code separation
  367. 367. Have a plan
  368. 368. Have a test-setup
  369. 369. Be ready to go cloud (experiment !)
  370. 370. Look at business critical level </li></ul><li>Have fallbacks </li><ul><li>Turn off non-critical functionality
  371. 371. Turn on queueing for non-critical updates </li></ul></ul>
  372. 372. Interested in actual benchmark results ? <ul><li>Join me for a Webcast with : </li><ul><li>Benchmark of an actual site
  373. 373. Step-by-step implementation of caching, Nginx and lots of tuning
  374. 374. See results for yourself </li></ul><li>Date : first half of March
  375. 375. Follow me : </li><ul><li>Twitter : @wimgtr
  376. 376. Blog : http://techblog.wimgodden.be </li></ul></ul>
  377. 377. <ul>Questions ? </ul>
  378. 378. Cu.be Solutions <ul><li>Founded in 2010
  379. 379. Spinoff of FirstLink Networks (founded in 2000)
  380. 380. High-quality open source solutions
  381. 381. Centered around PHP
  382. 382. Contribute to open source projects
  383. 383. (ZF, PHPUnit, PHP_CodeSniffer, OpenX, ...) </li></ul>
  384. 384. Cu.be Solutions - we're hiring ! <ul><li>PHP developers
  385. 385. Go beyond just PHP -> entire PHP ecosystem
  386. 386. Work with latest tools
  387. 387. Exciting projects (Webservices, mobile, high-traffic, ...)
  388. 388. Focus on highest possible quality !
  389. 389. Interested ?
  390. 390. -> http://cu.be/jobs
  391. 391. -> info@cu.be </li></ul>
  392. 392. Contact <ul><li>Web http://techblog.wimgodden.be
  393. 393. Slides http://www.slideshare.net/wimg
  394. 394. Twitter @wimgtr
  395. 395. E-mail [email_address] </li></ul>
  396. 396. Please... <ul><li>Rate my talk (evaluation forms)
  397. 397. Rate my talk : http://joind.in/talk/view/2491 </li></ul>
  398. 398. <ul>Thanks ! </ul>

×