You are here: Home Posts

Site News

nginx with built in load balancing and caching

by Nathan Van Gheem last modified Jul 31, 2010 12:11 AM
nginx can do it all. Short example to get nginx going with buildout to provide load balancing and caching.

Introduction

Why muck around with HAProxy and Varnish when you can have nginx do it all for you. The setup is easy and it's a lot easier to maintain.

Installing nginx with buildout

You can setup nginx fairly easily with buildout. The only fancy part of our setup is that we're going to include the nginx cache purge module.

  1. Add the cache purge part to your buildout
    [ngx_cache_purge]
    recipe = hexagonit.recipe.download
    url = http://labs.frickle.com/files/ngx_cache_purge-1.1.tar.gz
    strip-top-level-dir = true
  2. I needed the pcre source to compile also
    [pcre-source]
    recipe = hexagonit.recipe.download
    url = ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.00.tar.gz
    strip-top-level-dir = true
    
  3. and the nginx part
    [nginx-build]
    recipe = hexagonit.recipe.cmmi
    url = http://nginx.org/download/nginx-0.8.45.tar.gz
    configure-options =
        --with-http_stub_status_module
        --conf-path=${buildout:directory}/settings/nginx.conf
        --error-log-path=${buildout:directory}/var/log/nginx-error.log
        --pid-path=${buildout:directory}/var/nginx.pid
        --lock-path=${buildout:directory}/var/nginx.lock
        --with-pcre=${pcre-source:location}
        --with-http_ssl_module
        --add-module=${ngx_cache_purge:location}
    
  4. and finally, add it all to the parts directive
    parts =
        ...
        pcre-source
        ngx_cache_purge
        nginx-build
        ...
    
    
  5. After you re-run buildout, you'll be able to run nginx by issuing a command like this:
    ./parts/nginx/sbin/nginx -c /path/to/configuration/nginx.conf

nginx configuration

Here is a simple sample configuration for nginx configured with load balancing and caching. It can obvious get as complicated as you want it, but I definitely think this is easier than managing haproxy, varnish and nginx.

pid /path/to/buildout/var/nginx.pid;
lock_file /path/to/buildout/var/nginx.lock;

worker_processes 2;
daemon off;

events {
    worker_connections 1024;
}

error_log /path/to/buildout/var/log/nginx-error.log warn;

# HTTP server

http {
    server_names_hash_bucket_size 64;

    # this is how you do simple round robin load balancing with nginx.
	# you can define as many backup servers as you'd like here.
    upstream plone {
        server 127.0.0.1:8080;
        server 127.0.0.1:8081;
    }
    
    access_log /path/to/buildout/var/log/main-access.log;


 	# can specify multiple cache paths for different resources/paths/proxies
    # if needed..
    # the levels=1:2 just means it'll store the cache'd files 2 levels down in
    # the folder structure
    proxy_cache_path  /var/www/cache  levels=1:2 keys_zone=thecache:100m max_size=1000m inactive=600m;
    proxy_temp_path /var/www/cache/tmp;

    # Here is the caching purge handling. Purge request come in here
    server {
        listen 8089;
        server_name www.example.com;

        access_log /path/to/buildout/var/log/purge.log;

        location / {
      	  allow			127.0.0.1;
      	  deny			all;
      	  proxy_cache_purge thecache $scheme$proxy_host$request_uri;
        }
    }
    
    server {
        listen 80;
        server_name www.example.com;


		# log for cache hits.
		log_format cache '***$time_local '
		                             '$upstream_cache_status '
		                             'Cache-Control: $upstream_http_cache_control '
		                             'Expires: $upstream_http_expires '
		                             '"$request" ($status) '
		                             '"$http_user_agent" ';

		access_log /path/to/buildout/var/log/cache.log cache;

        # Enable gzip compression
        gzip             on;
        gzip_min_length  1000;
        gzip_proxied     any;
        gzip_types       text/xml text/plain application/xml;

        # Show status information on /_main-status
        location = /_main_status_ {
            stub_status on;
            allow 127.0.0.1;
            deny all;
        }

		# do not cache when users are logged in..
        proxy_cache_bypass $cookie___ac;

	    location / {
	        proxy_redirect                  off;
			proxy_set_header                Host $host;
			proxy_set_header                X-Real-IP $remote_addr;
			proxy_set_header                X-Forwarded-For $proxy_add_x_forwarded_for;
			client_max_body_size            0;
			client_body_buffer_size         128k;
			proxy_send_timeout              120;
			proxy_buffer_size               4k;
			proxy_buffers                   4 32k;
			proxy_busy_buffers_size         64k;
			proxy_temp_file_write_size      64k;
			proxy_connect_timeout           75;
			proxy_read_timeout              205;   
	        http://plone/VirtualHostBase/http/www.example.com:80/Plone	/VirtualHostRoot/;

	        proxy_cache_bypass $cookie___ac;
	        proxy_cache thecache;
	        proxy_cache_key $scheme$proxy_host$request_uri;
	    }
    }
}
Document Actions

Running Plone 4b4 with Zope 2.13.0a1

by Nathan Van Gheem last modified Jun 25, 2010 03:57 PM
Just some guidelines on getting Plone 4b4 to work with the new Zope 2.13 release to save you some time.

 

Introductions

I'm not going to go into detail of the wheres and hows everything is done. This post expects you to know a bit about plone, zope and buildout. Maybe I'll be more detailed later. Use this if you want to save yourself a lot of time in getting a working setup with Plone 4 and Zope 2.13. Zope 2.13 adds native WSGI support in Zope. I tested it a bit and seems to work well but results may vary and I'm sure there will be a more supported way to do this soon.

Extends

Make sure your buildout extends the http://download.zope.org/Zope2/index/2.13.0a1/versions.cfg versions file.

Checkouts

You'll need to checkout Products.CMFCore, Products.PluggableAuthService, Products.TinyMCE and plone.locking from svn. You can use these locations right now until there is a new release,

http://svn.zope.org/repos/main/Products.CMFCore/branches/2.2/ Products.CMFCore

http://svn.zope.org/repos/main/Products.PluggableAuthService/trunk Products.PluggableAuthService

http://svn.plone.org/svn/collective/Products.TinyMCE/trunk/ Products.TinyMCE

http://svn.plone.org/svn/plone/plone.locking/trunk/ plone.locking

You'll also need to add these packages to your develop buildout section.

Extra Versions Pins

You'll need to pin these versions since Zope 2.13 doesn't pin version that plone's setup used to assume were pinned,

Add these extra version pins

Products.CMFCore = Products.PluggableAuthService = Products.TinyMCE = plone.locking = five.formlib = 1.0.2 zope.formlib = 3.7.0 zope.app.apidoc = 3.6.2 zope.app.applicationcontrol = 3.5.0 zope.app.appsetup = 3.11 zope.app.authentication = 3.6.0 zope.app.basicskin = 3.4.1 zope.app.broken = 3.5.0 zope.app.cache = 3.6.0 zope.app.catalog = 3.8.0 zope.app.component = 3.8.3 zope.app.container = 3.8.0 zope.app.content = 3.4.0 zope.app.dav = 3.5.1 zope.app.debug = 3.4.1 zope.app.dependable = 3.4.0 zope.app.dtmlpage = 3.5.0 zope.app.error = 3.5.2 zope.app.exception = 3.5.0 zope.app.file = 3.5.0 zope.app.folder = 3.5.1 zope.app.form = 3.8.1 zope.app.generations = 3.5.0 zope.app.http = 3.6.0 zope.app.i18n = 3.6.1 zope.app.interface = 3.5.0 zope.app.intid = 3.7.0 zope.app.locales = 3.6.1 zope.app.localpermission = 3.7.2 zope.app.pagetemplate = 3.7.1 zope.app.principalannotation = 3.7.0 zope.app.publication = 3.8.1 zope.app.publisher = 3.8.4 zope.app.renderer = 3.5.1 zope.app.rotterdam = 3.5.0 zope.app.schema = 3.5.0 zope.app.security = 3.7.3 zope.app.securitypolicy = 3.5.1 zope.app.server = 3.4.2 zope.app.session = 3.6.1 zope.app.testing = 3.7.3 zope.app.traversing = 3.4.0 zope.app.undo = 3.5.0 zope.app.wsgi = 3.6.0 zope.app.zapi = 3.4.1 zope.app.zcmlfiles = 3.5.5 zope.app.zopeappgenerations = 3.5.0 zope.app.zptpage = 3.5.0 plone.app.form = 2.0b6 plone.app.contentrules = 2.0b4 plone.app.portlets = 2.0b11 plone.app.users = 1.0b9 plone.app.contentmenu = 2.0b3

Extra Eggs

You'll also need to add extra add dependencies to your buildout that the Plone 4b4 egg doesn't require and should.

    zope.formlib

    five.formlib

    zope.app.schema


WSGI

You can take a look at my previous post for doing WSGI Zope2 for guidelines on how to setup the paste config and such.

Document Actions

pysourcesearch

by Nathan Van Gheem last modified Jun 09, 2010 08:44 AM
A simple repoze.bfg application for searching python packages and sets of packages utilizing repoze.catalog.

Overview

Sometimes grep or TextMate's find can take a long time so I decided to give a mini search engine a try using repoze.bfg, repoze.catalog and Pygments. The result is that it works rather well and is very fast. The catalog ends up being rather large once you add groups of packages from Plone and such so this ends up making the RAM usage be very high unfortunately.

It gives you the ability to easily search methods, classes, filenames and full text and then give allows you to view the file with pygments.

You can take a look at search.nathanvangheem.com to see it working with repoze.bfg and Plone 4 being indexed.

You can checkout the pypi page if you're interested in it and I also have it on bitbucket.

Document Actions

Running Plone 4 with a Zope2 WSGI

by Nathan Van Gheem last modified Jun 04, 2010 09:50 AM
Guide to running Plone 4 with the Zope2 WSGI branch

Update

Tres has managed to merge his WSGI branch into trunk and Hanno tells me the unofficial plan is to include this in a release for Zope 2.13, in time for Plone 4.1. This is not decided upon yet though.

Overview

I was planning on implementing WSGI for Zope2 during the Penn State Symposium Sprints, and I did a few things to help out; however, Tres Seaver did most of the work on his own before and during part of the Sprint :) The rest of the time I spent just testing it out and helping with the Theme Editor sprint.

Now, it's really quite trivial to get it working now and makes all of the repoze.zope2 nonsense unneeded now. This article is just here for a reference if anyone else is interested in getting it going on their setup.

Guide

This guide assumes you have an existing Plone 4 installation to work from. I don't provide any buildouts here--just modifying an existing buildout to make it work with a branch of Zope2 and creating an ini that Paste can consume to serve WSGI.

Supplying the WSGI'd Zope2

First off, go to the src directory of the installation. If you've installed using the unified installer, that will bin in instance-home/zinstance/src or if you just used straight buildout, it'll be in instance/src. Then checkout the Zope2 branch:

svn co http://svn.zope.org/repos/main/Zope/branches/tseaver-fix_wsgi/ Zope2

Stringing up buildout

Next thing you'll need to do is modify your buildout.cfg file to add the checked out Zope 2 to the develop section:

develop = 
...
Zope2
...

Still modifying your buildout.cfg, add Paste, PasteScript, repoze.tm2 and repoze.retry to your eggs section:

eggs =
Plone
Paste
PasteScript
repoze.tm2
repoze.retry 

Again, editing your buildout.cfg, add a paster part for the paster script:

parts =
...
paster
...

[paster]
recipe = repoze.recipe.egg
scripts = paster
eggs = ${instance:eggs}

Then, you'll need to add the updated Zope2 versions for the WSGI branch. To do this, basically, just add the versions.cfg file provided in the branch after every other version file listed in the extends directive. It'll look like this:

extends =
...
src/Zope2/versions.cfg

Then run your buildout like normal:

./bin/buildout

Creating a WSGI Configuration File

You'll now need to create a WSGI configuration file. Right now, we'll just server it using the Paste server and wsgi ini configuration way. You can also do this to string up Apache's WSGI implementation but that is beyond the scope of this article.

Create a file in the instance directory called, zope2.ini with the contents of:

[app:zope]
use = egg:Zope2#main
zope_conf = %(here)s/parts/instance/etc/zope.conf

[pipeline:main]
pipeline =
    egg:paste#evalerror
    egg:repoze.retry#retry
    egg:repoze.tm2#tm
    zope

[server:main]
use = egg:paste#http
host = localhost
port = 8080

The zope_conf value in the app:zope section can be the path to any zope.conf file. I'm just exampling the standard location of it and not going through the configuration of that file itself.

Fire it up!

If all went well, you should now be able to start up your Plone 4 instance on WSGI like this:

./bin/paster serve zope2.ini

Your server should now be able to visit your site on http://localhost:8080

Caveats

I did run into a snag with the Mac OS X unified installer and the version of python it has configured. Basically, it wouldn't compile the Zope2 dependencies so I had to use my own version of python that I had compiled with the python buildout found in the plone collective svn. The bug is sort of referenced in the zope bug tracker.

Future Considerations

I'm hoping to maybe get a release with this branch implementation out--maybe as an alpha or beta release since I don't think they are planning on merging this to core any time soon; although, I really have no understanding of what that whole process is.

I'd like to see the Zope2 package implement mkzope2instance and other convenience methods so it'd be possible to install Plone 4/Zope2 without buildout at all maybe using pip. I'm looking into how this might be able to happen with a pip versions file and other things. Maybe more on this later.

 

Post any comments if you run into any issues.

Document Actions

Plone 4 Upgrade

by Nathan Van Gheem last modified May 15, 2010 01:40 PM
Thoughts on moving the server to Plone 4.

Last night I decided to take some time to move this site over to Plone 4. The repoze.zope2 build I had previously was buggy and I am starting to dislike Deliverance a bit.

Snags

  • the search didn't work because of this migration issue http://dev.plone.org/plone/ticket/10360
  • old file types aren't migrated to blob http://dev.plone.org/plone/ticket/10365
  • archetypes don't want to use the new add views--should probably report this
  • If you have the jquery UI package installed, it'll mess with some of Plone's JS for some reason--I just disabled it.
  • some other control panel entries and menu items were not fully migrated, still pointing to old templates

 

Benefits

  • FAST--running this on a linode with 512MB of ram. 2 zeo clients and with CacheSetup, this thing is very fast. Much faster than Plone 3.
  • Just more polished than Plone 3--with usability enhancements and a new theme, it's great.
  • I haven't found a product that wasn't compatible with Plone 4 yet--although, sometimes I needed to do some digging or use an svn checkout to get the compatible version

 

Document Actions

repoze.zope2 with Deliverance locking up

by Nathan Van Gheem last modified Mar 20, 2010 09:52 PM
How to make sure your repoze.zope2 wsgi setup with Deliverance will not lock up on you.

I was having issues with my repoze.zope2 and Deliverance setup locking up on me. Turns out, since I had some of sub-requests in my Deliverance rules, it was occasionally causing a race condition where all the wsgi server threads were taken up and an existing thread was making a sub-request.

The fix is to remove all sub-requests in the deliverance rules file if possible, add more threads threads in the repoze.zope2 wsgi server configuration, or use a different wsgi server that doesn't restrict the amount of threads--so it'll add a new thread if needed. A better solution, IMO, would be to just have a different server, serve the theme files. Anything to make it not make sub-requests against the same wsgi server.

Document Actions

Add Eject Button To Boxee

by admin last modified Feb 15, 2010 02:27 PM
Boxee is great, but how could they have forgotten the eject button?

For some very odd reason, boxee did not include an eject button in their version of the app. Luckily it is pretty easy to add your own eject button. Well, looking back it is easy; however, it took me a while to figure it out...

First off, find a nice fancy eject button and place it into boxee's skin images folder, "skin/boxee/media/icons/". I used this one and found it on google image search.

Next insert these lines after line number 231 of the file skin/boxee/720p/boxee_main_menu.xml

<item>
    <visible>System.HasMediadvd</visible>
    <controlid>1300</controlid>
    <thumb>icons/eject.png</thumb>
    <label>Eject DVD</label>
    <onclick>XBMC.EjectTray()</onclick>
</item>

And you're set. You should now have an eject button for your DVDs.

Document Actions

Buildout to compile and install Apache, MySQL and PHP

by Nathan Van Gheem last modified Feb 16, 2010 02:25 PM
I created a buildout that will compile and install Apache2, MySQL5 and PHP5 together.

I like to make my work environments contained and repeatable. Buildout is tool that can help you do that. While buildout is a python tool, with buildout recipes you can compile and install other types of applications relatively easily. 

You can download my buildout here. It also contains patches for it to work on Mac OS X. You'll need python installed for this to work.

If you're not familiar with buildout, these are the steps to get it working after you've extracted it...

python bootstrap.py
./bin/buildout

Then wait for a long time. Then read the README.txt for instructions on how to configure and start apache

Document Actions

Installing PIL on Mac OS X Leopard virtualenv with easy_install

by Nathan Van Gheem last modified Feb 11, 2010 07:30 AM
What do you do when you need to install PIL in a virtualenv on Mac OS X and it won't build for you? I'll walk through getting it to work.

First off

If when you try installing PIL, you get an error like this
collect2: ld returned 1 exit status
lipo: can't open input file: /var/folders/nO/nOf0lGB+GlGrFGnhcyaFPE+++TI/-Tmp-//ccqHwR4o.out (No such file or directory)
error: Setup script exited with error: command 'gcc' failed with exit status 1

Then it's failing because it doesn't have the universal versions of some packages installed. 

You'll first need to install MacPorts. You can download the dmg install file or just go to the MacPorts installation page for instructions on how to get it setup on your system.

Installing Universal Packages

 
Open up a terminal window and run these commands,
sudo port install libiconv +universal
sudo port upgrade --enforce-variants zlib +universal
sudo port install jpeg +universal
sudo port install freetype2	 +universal

Now Install PIL 

 
Now you should be able to run
./bin/easy_install http://dist.repoze.org/PIL-1.1.6.tar.gz

 This is a version of PIL that plays nice with setuptools.

Document Actions

Moving to Picasa Update

by Nathan Van Gheem last modified Feb 15, 2010 08:22 AM
Everything didn't go as well as I hoped, but I fixed all the problems I was coming across...

While moving all my photos from flickr over to Picasa Web Albums I ran into some problems. The original post explained how the whole process works. 

  • Picasa albums have 1000 photos limits
  • the python gdata api didn't support video uploads
  • Picasa trimmed whitespace from Album names
  • other small things
 
The new script includes creates a new InsertVideo method to support video uploads, moves multiple photos at a time, automatically creates multiple albums if there are more than 1000 photos in a set and fixes other small issues. You'll need to install the flickrapi, gdata and ThreadPool packages.
 
It completely works and is done now though. :)
Document Actions