Not signed in (Sign In)
    • CommentAuthorissya
    • CommentTimeSep 24th 2008
     permalink
    Hi, I recently started using Slicehost and I am trying to get my servers setup. I think I have everything right and I am just trying to keep the future in mind for scalability. I am trying to get some opinions on what people think may be the best setup. In a perfect world, Django would be setup on 3 or more servers. 1 for Django, 1 for the db and 1 for static content. Since I cannot afford 3 I am working with 2.

    I have 2 servers, 1 only handles Django and the other handles all static content and the db. I have the static/db server mounted on the Django server internally. When people upload static files it will go directly to the static server through the mount. When a Django page is requested and if it has static content, that content is pulled externally from the static/db server using lighttpd. I think this setup would be best memory wise on the Django server. But I am no expert on the matter.

    I have a few other people telling me that the setup would be Django/static on 1 and the db on the other. I would use Apache for serving Django and something like nginx to serve the static media. So all requests would come to nginx first then be proxied to Apache if it is something Django related. This sounds like a nice setup too.

    My goal is to be able to setup 30+ Django web sites. I want to always make sure that it is scalable. What do you think the best way is?
    • CommentAuthorartagesw
    • CommentTimeSep 25th 2008 edited
     permalink

    I find that maintenance and security are simplified by compartmentalizing functionality such that each server is responsible for as few tasks as possible. Ideally, this means 3 slices: one each for db, dynamic and static content. Each can then be scaled independently of the others as the need arises.

    If you must start with only 2 slices, the database should still be on its own slice. Combine the dynamic/static web serving onto the second slice. But don’t mess with proxying. Get a second IP on that slice, and use DNS to send all static requests to nginx (eg. static.mysite.com) and all dynamic requests to apache. This will give you better performance and make it dead simple to move the static stuff over to its own slice in the future (just update DNS).

    • CommentAuthorfactor
    • CommentTimeSep 25th 2008
     permalink

    How much traffic do you expect your sites to receive?

    I’ve had a half dozen low-traffic Django sites running on a single 256slice with Lighttpd and FastCGI with no problems. My higher-traffic Django sites run on their own slices.

    I am assuming that your “static files” component must handle user-uploaded files. You might consider implementing a file storage backend that uploads to Amazon S3 to address this component.

    • CommentAuthorissya
    • CommentTimeSep 25th 2008
     permalink
    artagesw: Thank you for your input. That would be a different way to do it and make it easier to move in the future. I think I may end up going that route.

    factor: I don't really expect too much traffic on any of them. Most of them will just be for smaller companies that will each net a few hundred visits or less a month. I tried Amazon S3 for a bit and just after I joined it they were down for half a day. At different points after that when I would go to load a page, I noticed the only things hanging or taking longer were things being served from Amazon.
    • CommentAuthorissya
    • CommentTimeSep 26th 2008 edited
     permalink
    For anyone that might be searching for this, here is what I ended up doing.

    1 server only handles the db.

    1 server handles all static content and django. I am using lighttpd on port 80 of this server. It then proxies django requests to apache on 127.0.0.1:80. You can see the config below for lighttpd.

    $HTTP["host"] =~ "^(www\.)?example.net" {

    alias.url = (
    "/admin_media/" => "/sources/svn/django1.0/django/contrib/admin/media/",
    "/media/" => "/home/example/example.net/example_media/media/",
    "/user_media/" => "/home/example/example.net/example_media/user_media/",
    )


    $HTTP["url"] !~ "^/(admin_media|media|user_media)/" {

    proxy.server = ( "" =>

    ( (

    "host" => "127.0.0.1",

    "port" => 81

    ) )

    )

    }

    }

    Make sure mod_alias is uncommented in server.modules and you have to add mod_proxy if it is not already in there. I read a lot about nginx vs lighttpd and there really wasn't much of a difference. Lighttpd came out on top while nginx in others. The above config came from a couple of different examples I found on blog posts. If the request is for a static file, lighttpd will handle it. If it is for something in django, it passes it to apache through localhost on port 81. Make sure you change your ports.conf file in apache to read Listen 127.0.0.1:81 instead of just 80. I also tested the speed at which lighttpd originally served the static files from the db server compared to this new way and there wasn't much of a difference. The new way had shorter response times but had a transfer rate of a few milliseconds of difference.

    I am using apache worker mpm with mod_wsgi. Apache worker mpm is the default install when installing mod_wsgi. I researched what the best way to serve django was for a few days. The official documentation suggests using mod_python. From what I read there could be some issues there and mod_python is not really in active development anymore. I am running mod_wsgi in daemon mode with 1 process and 10 threads. This is hoping that any apps I put on the server is thread safe. If they are not, there could be problems down the road. If I had issues, I would change over to apache prefork mpm and still run mod_wsgi in daemon mode but make 5 processes and 1 thread. This could have the potential of shooting up memory too if I understand correctly.

    Note that I intend to host as many apps as possible. Most of the sites I will be working with will be for small businesses and have minimal traffic on them. If I ever were to have a site with a lot of traffic on it, I would move it to it's own server but still probably connect it up to the db server. The best thing about slicehost is that you can change the size of your slices at any time to accomodate more traffic.

    If I need to make changes in the future to my setup I will let you know.
    • CommentAuthorrailsninja
    • CommentTimeSep 26th 2008
     permalink
    If you are running apache for python and django, why not just have it serve the static content as well? Serving static content is what apache does best, and surely any memory saving benefits of running lighttpd and void by running apache as well. No?
    Thankful People: meppum
    • CommentAuthormeppum
    • CommentTimeSep 26th 2008
     permalink
    railsninja,

    i'm sorry, this simply is not true. the overhead needed per connection on apache is far more then that needed by lighttpd or nginx. Given that fact consider that 9 out of 10 requests to a webpage are for static content (images, js files, css files). If you offload this effort to a webserver with less overhead it will allow apache to serve only dynamic requests where the memory overhead is warranted.
    • CommentAuthorartagesw
    • CommentTimeSep 26th 2008 edited
     permalink

    meppum,

    That is certainly true for apache in prefork mode, but much less so with the threaded worker mpm that he’s using. I concur with railsninja. Once you go to worker mpm + mod_wsgi, apache is already offloading django requests to the mod_wsgi daemon and static requests can be handled quickly with little overhead by an apache worker thread. Any gains for static requests from putting lighttd in front of apache for this particular config would be questionable, and it actually adds overhead to the django requests.

    • CommentAuthorrailsninja
    • CommentTimeSep 27th 2008
     permalink
    I'm a developer not a sysadmin, and with rails I use nginx anyway not apache so I don't really know for sure. I wasn't asserting my point of view as truth, it was a question that reading the thread raised for me so I thought it would help to raise the consideration. We have two points of view on this, anyone care to cast a view one way or the other?
    •  
      CommentAuthorSuperJared
    • CommentTimeSep 27th 2008
     permalink
    If you're using apache which is overloaded with lots of stuff in-memory, your processes can balloon quickly. Some Django installs I've seen are over 100MB per process. Because of RAM constraints you can only have so many of these going at once. If you serve static content through these threads, that's like delivering a single piece of paper using an earth mover. Using Nginx to serve static content offloads a significant portion of the requests from Apache, thereby reducing the amount of processes one may need for a site.
    • CommentAuthorartagesw
    • CommentTimeSep 27th 2008
     permalink

    Again, not particularly applicable to the config that started this thread. With separate WSGI deamon processes handling the django requests, there is no reason apache processes would balloon to 100MB. Yes, that could be possible with the prefork mpm and mod_python. But that is not the config we’re discussing in this case. Apache processes should stay small, and with several threads per process in worker mpm, apache can handle a very high workload with minimal memory utilization.

    I see this knee-jerk assessment quite often (“Apache is a memory hog.”) However, that assessment arises from the fact that the default apache config on many distros is prefork mpm + mod_php / mod_python / etc. It is not necessarily true in a general sense.

    In the past, I have benchmarked apache/worker against nginx and lighttpd for static file handling and it compares quite favorably both in terms of performance and memory utilization. Yes, it uses somewhat more memory. But in many cases, that is an acceptable tradeoff for the reduction in complexity you get from avoiding multiple web servers, reverse proxying, etc.

    Thankful People: meppum
    •  
      CommentAuthorSuperJared
    • CommentTimeSep 27th 2008
     permalink
    Posted By: artagesw

    Again, not particularly applicable to the config that started this thread.



    Was simply responding to RailsNinja -- I hadn't read the whole thread. Apologies.

    • CommentAuthorissya
    • CommentTimeSep 27th 2008
     permalink
    Thanks for all of your great input everyone. I will have to run some testing on it to see how it compares. I am just getting familiar with all of this worker/prefork, wsgi stuff myself.
    • CommentAuthormeppum
    • CommentTimeSep 27th 2008
     permalink
    I too apologize for me knee jerk reaction.

    It seems that more and more people are using mod-wsgi instead of mod-python. Has anyone run into any gotchas or is mod-wsgi stable enough now?
    •  
      CommentAuthorSuperJared
    • CommentTimeSep 28th 2008
     permalink
    I've used mod_wsgi since 1.3 and I don't currently use daemon mode.
    • CommentAuthormeppum
    • CommentTimeSep 28th 2008
     permalink
    SuperJared,

    You say you don't run in daemon mode, is that for performance reasons? I've read a few posts that claim that the performance difference between 'embedded' and 'daemon' mode when using django aren't significant. Do you have any insight into this?

    Also, I've read the differences between embedded and daemon mode, but is there a memory footprint difference if using worker MPM and a shared python install?
    •  
      CommentAuthorSuperJared
    • CommentTimeSep 28th 2008
     permalink
    Meppum, I believe daemon mode will achieve better performance when you have multiple wsgi applications, reason being that when a new thread is required the environment duplication is limited to the one wsgi app. When in inline mode (not sure of the terminology) and a new thread is spawned, each environment is duplicated.

    This is all conjecture based on my understanding of mod_wsgi, which I haven't paid too close attention to. I just know I like it.
    • CommentAuthormeppum
    • CommentTimeSep 28th 2008
     permalink
    So does that mean that if I only had a single django app on a single server that 'embedded' or as you said 'inline mode' would achieve better performance because the request wouldn't have to be proxied to the daemon instance, and that the memory usage would be the same as in daemon mode?

    I've read that the overhead from daemon mode is very little when using a django app, but I haven't seen any numbers on that. Can anyone confirm?
    •  
      CommentAuthorSuperJared
    • CommentTimeSep 28th 2008
     permalink
    The overhead in running in daemon mode is minor, if existant.
  1.  permalink
    I killed the Apache issue by actually using FCGI with Nginx directly for my Django deployment. The FCGI implementation seems rock solid. The only issue is that FCGI/Flup doesn't like errors and will sometimes override the Django debug pages with it's own completely un-usefull error page. But that's what tests and staging servers are for :D.

    The speed of my page loads has increased for dynamic pages, and my server memory is plentiful from ditching the huge Apache monkey from my back. Hope this intrigues others to look in this direction.