Chinaunix首页 | 论坛 | 博客
  • 博客访问: 592610
  • 博文数量: 207
  • 博客积分: 10128
  • 博客等级: 上将
  • 技术积分: 2440
  • 用 户 组: 普通用户
  • 注册时间: 2004-10-10 21:40
文章分类

全部博文(207)

文章存档

2009年(200)

2008年(7)

我的朋友

分类: 系统运维

2009-04-23 11:02:03

Fix That Slow Site!

Here’s a rundown on some ways to dramatically improve the speed of your web site without going broke or compromising the content. Some examples are in the context of a Ruby on Rails site on a PostgreSQL database backend, but really apply to most technologies. I’ll try to keep this short and sweet, so here we go:

1. Hardware Upgrade

Sometimes overlooked is the hardware your site is running on. A simple $50 stick of 1GB RAM can go a long way for example. Also, beware of shared environments which tout impressive specs but get the resources eaten up by less efficient or heavy trafficked sites. Also make sure you have a good network connection from your server to the world.

If you can dictate your hardware environment/budget, try to avoid the tendency to split the site out on to several servers (e.g. a caching proxy, database server(s), web server(s), etc.).

Instead, build ‘up’ instead of ‘out’ where possible. What I mean by that is to beef up a single server instead of spreading work out to multiple servers. You’ll save money, you’ll have less hardware to fail on you, less configuration nightmares, and avoid the performance hit of increased latency due to network interconnects.

2. Apache Configuration Optimization

Don’t overextend the Apache configuration. For example, don’t crank up the max # of possible concurrent connections unless you really know the server can handle it. It’s better to have a few users get a ‘try again later’ than everyone getting extremely slow page loads (or worse, nothing at all). “ab” (Apache Bench) is your friend here to test.

Turn on persistent connections. In Apache, this is the “KeepAlive On” directive. For sites that have lots of assets (lots of images, css files, etc.) it can give dramatic speedups!

Use ETags. ETags are one way to tell the browser what has gone out of date and needs refreshing. In Apache, you can simply put “FileETag All” in the appropriate Directory config to enable ETag headers for all your static files. Again, for sites which use lots of common elements for lots of pages (css, js, nav images, etc.) it can really give dramatic improvements and should be a no-brainer to implement.

Compress on the fly. Use Apache’s mod_deflate to compress things on the fly. An example config for this is:


AddOutputFilterByType DEFLATE text/html text/plain text/xml text/x-js text/css application/x-javascript

I would avoid trying to wedge in a caching server or something like that. It’s really the browser’s job (or remote proxy) to handle that. Instead, fix your app to handle caching directives when appropriate (more on this below).

3. Database Backend Optimization

Make sure you index all Primay and Foreign keys! This is huge. Index any other columns which are looked up often, like ’sessid’ in the sessions table if it isn’t already.

Vacuum your database periodically. I like to have a script that both does a full vacuum and then backup nightly.

Give your database backend lots of RAM. The defaults are usually very low in the idea that the database backend is just one of many services running, but on a web server it may be the only service running that could benefit from lots of ram. For example, I usually tell the kernel to allow for higher limits on shared memory:

echo 134217728 >/proc/sys/kernel/shmmax
echo 2097152 >/proc/sys/kernel/shmall

And then tell PostgreSQL (I don’t use MySQL if I can help it, but that’s a topic for another blog) to take advantage of that memory:

PGOPTS=" -i -B 10000 -N 200"

There are more PostgreSQL specific performance configuration tweaks but I won’t get into that here.

4. Application Based Optimization

I won’t get into the basics of good coding practices (again, that’s for another blog), but here are some ways to improve an already decently written web app.

I use the exception_notification plugin to email me when an exception happens. It’s a great way to find bugs you might not normally know about, and have a sort of paper trail when somebody calls saying “at 1:05PM I got an error trying to do xyz!”. More often than not, though, exceptions will happen from random search engines indexing odd things, or services or haxors trying to probe the site for vulnerabilities. When an exception happens, a series of not very efficient things happen. When possible, try to prevent useless exceptions by catching them in the code.

Just like how ETags were used for static files, using ETags or LastModified can be used for dynamic content. For example, here’s a simple function for Rails that checks the If-Modified-Since header from a browser:

def cache_check(last_modified)
 response.headers['Last-modified'] = last_modified.httpdate
 if (request.env["HTTP_IF_MODIFIED_SINCE"] && (Time.rfc2822(request.env["HTTP_IF_MODIFIED_SINCE"]) >= Time.rfc2822(last_modified.httpdate)))
 render :inline => '', :status => 304
  return false
 else
  return true
 end
end

Simply pass this function the timestamp that reflects when the result was effectively last changed, and it will produce the appropriate 304 response.

For example, if your page only changes when data in your products table has changed, you can put this near the beginning of the method:

return false unless cache_check(Product.find(:first, :order => 'updated_on desc', :conditions => 'updated_on is NOT NULL').updated_on)

btw- You remembered to index the updated_on column if you do this, right?

5. Optimize Static Content

I’m assuming that we’re at the mercy of the web designer and we’re compressing images when possible and keeping the number of images as low as we can.

Remember that PNG’s can look pretty but are lossless and so compress very badly in most cases.

Use tools like Safari’s Develop menu and Firefox’s Webdev toolbar to check for the weights and transfer times of pages. As I mentioned, Apache’s ‘ab’ is also very good at testing the rendering times of dynamic content when run from the server that’s producing the content, removing the element of network transfer time.

Isolate the useless weight of a page and compress or remove. And try to narrow down the backend latency bottlenecks and optimize where possible.

阅读(343) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~