diff options
author | evanweaver <evanweaver@19e92222-5c0b-0410-8929-a290d50e31e9> | 2007-09-23 03:09:56 +0000 |
---|---|---|
committer | evanweaver <evanweaver@19e92222-5c0b-0410-8929-a290d50e31e9> | 2007-09-23 03:09:56 +0000 |
commit | de7b6232418a231c268fa88be92272e4537c75db (patch) | |
tree | 6c82acbed13477f80d95f49979df730710b0a1bd /site/src/faq.page | |
parent | 7c815583b780f0a3e772fe8422b44107e030f799 (diff) | |
download | unicorn-de7b6232418a231c268fa88be92272e4537c75db.tar.gz |
git-svn-id: svn+ssh://rubyforge.org/var/svn/mongrel/trunk@607 19e92222-5c0b-0410-8929-a290d50e31e9
Diffstat (limited to 'site/src/faq.page')
-rw-r--r-- | site/src/faq.page | 415 |
1 files changed, 415 insertions, 0 deletions
diff --git a/site/src/faq.page b/site/src/faq.page new file mode 100644 index 0000000..b98d2e0 --- /dev/null +++ b/site/src/faq.page @@ -0,0 +1,415 @@ +--- +title: FAQ +inMenu: true +directoryName: FAQ +ordering: 5 +--- + +h1. FAQ + +h2. Design + +h3. Q: How is Mongrel designed? + +The design of Mongrel most closely matches "Simple":http://simpleweb.sourceforge.net/ +which is a very nicely designed web server framework for Java. Despite being written +in Java, Simple is very clean and simple, thus the name (clever eh?). The main difference +between Mongrel and Simple is that Simple monitors returned output from handlers so that +it can modify the results. Mongrel instead uses Ruby's blocks to get the same effect. + +As for the internals of Mongrel there are a few key technologies being used: + +* A custom HTTP 1.1 parser written based on the "RFC":http://www.w3.org/Protocols/rfc2616/rfc2616.html + standard and using "an ABNF dump":http://www.cs.columbia.edu/sip/syntax/rfc2068.html thankfully + put online by someone. The parser is written using "Ragel":http://www.elude.ca/ragel/ and + is written C as a Ruby extension. +* A URIClassifier that uses a "Ternary Search Trie":http://www.octavian.org/cs/software.html + written by Peter A. Friend and modified to quickly look up handlers for a URI based on + a prefix. This makes finding any handler from any URI quick and painless and is much + faster than the alternative of parsing the path and using nested Hash structures. +* A simple server that uses the parser and URIClassifier to process requests, find the + right handlers, and then pass the results on to the handler for processing. +* Handlers are responsible for using HttpRequest and HttpResponse objects to do their + thing and then return results. + +Other than this there's not much more to it. + +h3. Q: Is it multi-threaded or can it handle concurrent requests? + +Mongrel uses one thread per request, but it will start closing connections +when it gets "overloaded". While Mongrel is processing HTTP requests and +sending responses it uses Ruby's threading system (which is more like +Java's original green threads and uses select). + +Camping and Og+Nitro are supposed to be thread safe and work with Mongrel directly. +This hasn't been heavily tested so people should let me know if they get weird +explosions under heavy load. + +Ruby on Rails is not thread safe so there is a synchronized block around the calls +to Dispatcher.dispatch. This means that everything is threaded right before and +right after Rails runs. While Rails is running there is only one controller +in operation at a time. This is why people typically have to run a small +set of Mongrel processes (a "Pack of Mongrels") to get good concurrency. + +If you have long running actions then you'll most likely have performance +problems. You should look at "BackgrounDRB":http://backgroundrb.rubyforge.org/ +as a very nice way to offload work to another process so that your Rails +app can keep working. + +h3. Q: But no, I mean how is it *exactly* locked? Because it's really really important that I know everything. + +First off, you should drink less coffee. Knowing exactly how Rails is locked +will not help you plan your deployment for the best performance, only testing +your deployment's speed will help. You should read "Tuning":/docs/how_many_mongrels.html +to get a good quick idea on how to figure out what your optimal Mongrel number +is, and then you should check out "BackgrounDRb":http://backgroundrb.rubyforge.org/ +for a good way to move long running tasks outside of Rails for better response. + +h3. Q: But, but, but, I really really need to know! It's killing me I *have* to know! + +Fine! It goes like this: + +# A request hits mongrel. +# Mongrel makes a thread and parses the HTTP request headers. +# If the body is small, then it puts the body into a StringIO. +# If the body is large then it streams the body to a temp file. +# When the request is "cooked" it call the RailsHandler. +# The RailsHandler sees if the file is possibly page cached, if so then it sends the cached page. +# Now you're *finally* ready to process the Rails request. *LOCK!* +# Still *locked*, Mongrel calls the Rails Dispatcher to handle the request, passing in the headers, and StringIO or Tempfile for body. +# When Rails is done, *UNLOCK!*. Rails has (hopefully) put all of its output into a StringIO. +# Mongrel then takes this StringIO output, any output headers, and streams them back to the client super fast. + +There's also a bit of processing with chains of Handlers, but that's a minor point. +For the most part, your goal as a Rails programmer is to make all of your Rails +actions as fast as possible, and to not do anything that takes a long time. + + +h3. Q: Can I run mongrel without rails? + +Yes, Mongrel is designed to host any framework, and already hosts Camping or Nitro +as well. If you're feeling adventurous, check out the "RDoc":/rdoc/index.html +for the latest API documentation. + +h2. Security + +h3. Q: Is Mongrel secure? + +Anyone who claims their server is "SECURE" is full of crap. You can't be +absolutely certain that any system is secure, but what you can do is put +policies and practices in place to try and make them more secure. + +As you can read in the "Iron Mongrel":/security.html documentation, I +have a policy of: + +* Extensive testing with multiple techniques, and even wrote my own HTTP fuzzing tool "RFuzz":http://rfuzz.rubyforge.org/ +* Full disclosure on any security issues found. +* Security auditing of all code before it's released. +* Design decisions such as using a parser generator and fixed limits on all HTTP. +* Simply trying to remove all defects and being proactive about it. + +Understand that I'm just one person with a few other people's help, so there's +bound to be mistakes. You use this technology (and *any* technology) at your +own risk. + +Then again, if someone is telling you their system is secure, but can't tell +you why it's secure, then maybe you should take a look at what I do to keep +Mongrel's defects low and ask if they do any of this. You might be surprised +at their response. + +h3. Q: What's this about .svn directories? + +Yeah, Capistrano doesn't use svn export to create the deployment directory so +there's a bunch of extra information in the .svn files. Without special config +changes to your web server you'll be letting people access these. Best solution +is to use svn export rather than checkout to get your code. If you're already +screwed then just do: + + find . -name ".svn" -exec rm -rf {} \; + +And that'll delete them all in a very final way. + +You should also read "the official page on that":http://subversion.tigris.org/faq.html#website-auto-update +to make sure there's nothing more you need to do. + +Finally, you can configure capistrano to do export instead of checkout +following "their instructions":http://manuals.rubyonrails.com/read/chapter/102 +instead of the ruthless delete I have above. + +h3. Q: Does Mongrel have SSL? + +No, having a Ruby web server do complex SSL cryptography is stupid when you can +get any of the major web servers to do it faster. + +h3. Q: Why are Apache & SSL - Redirects going to http:// not https://? + +Basically, you need to pass in a header so Rails knows what to do. Read +the bottom of the "Apache Documentation":/docs/apache.html for instructions +on how to do this. + + +h2. Installation + +h3. Q: I can't get Mongrel installed on Debian. + +You should read the "Debian":/docs/debian-sarge.html documentation. + +h3. Q: I can't get Mongrel installed on Fedora. + +Not sure when Fedora decided to start chopping up its packages like Debian, +but you should basically just install Ruby from source, then install Mongrel. + + +h2. Deployment + +h3. Q: What can cause Mongrel to lock up on a regular basis? + +There are several reasons Mongrel can stop functioning properly, but +most of them are related to using resources that aren't shared properly +between multiple processes. The following is just a short list of the +possible things you could be doing to cause Mongrel processes to lock: + +# Configuring Logger to rotate log files. Logger doesn't do this reliably +between processes, so use an external log rotation like logrotate. +# Using PStore to store your sessions. This isn't faster than the database +and has frequent locking and coordination issues. +# Sharing a file or similar service without proper locking. SQLite and BerkleyDB are +both culprits here. +# Not setting the MySQL timeout properly (see later in the FAQ). +# Using up too much CPU or memory on Linux will cause the oomkiller to +kill your Mongrel process. + +If you have frequent stopping and stability issues, then install "monit":http://www.tildeslash.com/monit/ +and have it restart your Mongrels when the go down or don't respond promptly. + +h3. Q: How do I deploy Mongrel in production? + +Take a look at the "documentation pages":/docs/index.html for +information on deploying and enhancing Mongrel. Feel free to +suggest documentation that you think is needed. + +h3. Q: Is there some kind of caching of session data in mongrel? + +Nope, Mongrel doesn't do anything with sessions and leaves that to the +framework. + +h3. Q: What is the best way to get mongrel servers within a cluster to always keep their sessions synced? + +For Rails the best way is either memcached or database session storage. +*Do not use PStore!* It is broken, will crash or lock your Mongrel processes, +and really isn't all that fast. + +h3. Q: What does num-procs do? + +There's two options that impact how your deployment performs +and what kind of resources it eats. + +* num-procs -- Determines how many active requests are allowed +before clients are denied and old requests are killed off. +* timeout -- Determines a short sleep time between each client +that is accepted. This acts as a kind of throttle. + +With num-procs you should think of it as the option that protects +your server from overload. Let's say you set it to 100 and you +get 100 requests coming in that are all being worked on. If +request 101 comes in then that request gets closed immediately, +and Mongrel goes through the original 100 looking for requests to +kill off. Right now it uses the timeout to come up with a reasonable +way to determine how long something is taking and will kill old +processors with an exception. + +The timeout option is what you use if you want to make sure that +a Mongrel server can't take on too much work (i.e. you need to +throttle it). What it does is sleep for N 100th/second after +each accept. This means that it will slow down the number of +incoming clients. Very handy if you have a shared hosting system +and don't want people to eat your servers. + + +h3. Q: Mongrel stops working if it's left alone for a long time. + +If you find that Mongrel stops working after a long idle time +and you're using MySQL then you're hitting a bug in the MySQL +driver that doesn't properly timeout connections. What happens +is the MySQL *server* side of the connection times out and closes, +but the MySQL *client* doesn't detect this and just sits there. + +What you have to do is set: + + ActiveRecord::Base.verification_timeout = 14400 + +Or to any value that is lower than the MySQL server's *interactive_timeout* +setting. This will make sure that ActiveRecord checks the connection +often enough to reset the connection. + + +h3. Q: Why is the first request to Mongrel really slow? + +The first request to *any* system will be slower than +the others, you are just noticing it with Mongrel because +the difference is so much larger. + +The cause of this depends on many factors, but typically it +is either Rails start-up, slow machine, no memory, or eager loading +the world. If you are on a slow box, or if you are trying to +load a huge amount of data when Rails starts, then the +first request will be nasty slow. + +This shouldn't really bug you though unless it happens periodically +rather than from a cold start. If it happens from a cold start or +after a long idle period then point your service monitor at your +application to keep it fresh. + +If you run a long performance test and you see periodic pauses +then you may have a memory leak or not enough ram. Re-run your +test while you monitor your ram with something like *top*. If +you see the ram of Mongrel increase and then drop, or just increase, +or you see the swap grow and shrink, then you've got a memory leak +or just simply need more ram. + +Debugging a leak is possible with the mongrel_rails start -B option. +It will log objects that get created to log/mongrel_debug and you can +look in there to find out what object is causing the problems. + + +h3. Why doesn't Mongrel write the .pid file like I tell it to? + +There was a change to the 0.3.13.4 release and on that makes it so Mongrel +doesn't try to "fix" invalid paths. You should change your configurations +so that they give explicit full paths to both the log and pid files. + + +h3. How do I put my Rails site at /someprefix? + +Most people use a virtual host configuration, but Mongrel now has an option +that lets you put your site at an arbitrary URI. Just start mongrel with: + + mongrel_rails start -e production --prefix=/someprefix + +Then your site will be at the same host but everything will be relative to +/someprefix. The only thing is you have to *religiously* use Rails link_to +and friends. If you don't then the links in your pages won't be written right. + + +h3. How many Mongrel processes should I run? + +First off, the type of machine you have doesn't matter, what matters is +that you measure your *deployment's* speed and tune that for optimal +performance. Then you *must* re-test after every change to your deployment +configuration to make sure that things didn't get worse or improve. + +There's a simple "document on tuning":/docs/how_many_mongrels.html that +should get you started. + +h3. What does BAD CLIENT mean? + +It means that a request came in which Mongrel rejects because it doesn't follow +the RFC grammar. Mongrel is pretty relaxed about most requests, but in order to +block the majority of security attacks for web servers it is strict about characters +used, header formats, status line formats, etc. This is also based on matching +the RFC's grammar specification to a Ragel grammar specification, so it's easy +to compare. + +If you need to know why the client is triggering this, then simply hit your +Mongrel processes with USR1 signals and they'll log the full request data +and parameters that were collected. Then, if you think the request is valid +send me this data and I'll look. If it's not valid than fix the client. + +Mongrel takes the stance that all clients are written by software developers and +that they should follow the standard. By doing this it reduces the bugs and +potential security holes found in many other web servers. It also means that +if you absolutely have to allow a bad client, then you'll need to not use Mongrel. + + +h3. Why do I get MySQL "lost connection to database" errors? + +The most common cause is that you're using mysql.rb that comes with Rails +rather than the MySQL compiled ruby driver from gems. Do this: + + sudo gem install mysql + +And pick the one for your system (don't type sudo if you're win32). + + +h3. Why does Mongrel keep dying on me? + +There are three known causes to this, and all of them are your fault. +First, there's a few symptoms to check to see if you fit in these +categories. + +* CLOSE_WAIT: Run @lsof -i -P | grep CLOSE_WAIT@ and if you see a bunch of mongrels then you've got a problem. +* 99% CPU: Check the mongrel processes and see if one or more are at 99%. +* MEMORY LEAK: We've supposedly fixed it, but you might be causing it yourself. + +In the case of CLOSE_WAIT and 99% CPU the problem is most likely you're using the +PStore for your session storage. Don't do this. Use memcached or database for your +session storage. PStore is slow anyway, but with multiple processes it's deadly. + +Another cause of CLOSE_WAIT and 99% CPU is one of your Rails actions is doing something +that "jams" Mongrel requests. Temporarily turn on USR1 debugging: + + killall -USR1 mongrel_rails + +And then watch what Mongrel says about the number of threads waiting for the various +Rails actions you have. You'll see right away which one is causing it. Usually +it's because you're using an external 3rd party library that isn't designed for +multiple process action. + +For memory leaks the most common cause is using Mutex. We found that on most systems +Mutex caused memory leaks when the Mutex was managing many Threads. Switch to using +Sync and see if the memory leak goes away. + +Other things that can cause big pauses are: + +* Using a broken or slow DNS server to resolve hosts. Ruby blocks the whole process while it resolves. +* Loading tons and tons of data over and over again. The GC will kill you if Linux doesn't. +* Locking files wrong. Multiple processes locking files is a delicate thing to do. +* Doing stuff over the network that takes a long time. Move that process to a DRb server run locally. + +If you have to do extensive DNS resolving then consider using dnsmasq run locally to cache the DNS +queries and make them faster. + +h3. How can I run some code before Rails starts? + +Simplest way is to put it in your production.rb and configure it there, but if +you need it done long before Rails starts, then you can throw it into a +mongrel.conf and run that file with the -S option (see mongrel_rails --help). +The mongrel.conf is a Ruby script that lets you configure Mongrel with special +Ruby code, but you can also put other Ruby code in it. + +h3. Why do I see my headers when Mongrel is behind Apache? + +If you see something weird like this in your browser when you're behind Apache: + + HTTP/1.1 0 Content-Length: 7636 + Connection: close + Date: Sat, 02 Sep 2006 14:10:38 GMT + Set-Cookie: device_id=; path=/; expires=Sun, 02 Sep 2007 14:10:38 GMT + Set-Cookie: _session_id=85d7a3c296268e0222cb796127da9c43; path=/ + *Status: status500* + Cache-Control: no-cache + Server: Mongrel 0.3.13.3 + Content-Type: text/html + +Then what you've done is you've mangled the *status* code inside rails with something +that is setting "status => 500". Rails is then injecting this right in, as you can +see in the above Status line. Since this is an invalid status, Apache "helpfully" +shows you the error so you can correct it. + + +h2. Mongrel Web Site + +h3. Q: How did you make this site? + +The site was actually incredibly easy to create. I simply went to "OSWD":http://openwebdesign.org/ +and found a design that fit what I wanted for the site. I then went to "Flickr":http://flickr.com/ +and found pictures of various animals that were licensed under the +"Creative Commons":http://creativecommons.org/ license. Once I chopped the images up, worked them +into the design structure, and wrote an initial set of content I was done. + +The tool I use to generate the site is called "webgen":http://webgen.rubyforge.org/ which +is a static site generator written in Ruby. I write all of the content using redcloth +mark-up and leave the generation to webgen. Finally I hooked into the Mongrel Rakefile +so that it's auto-generated and deployed to the site for me. + +Refer to the "attributions":/attributions.html page for information on the resources used. |