Kallithea Performance Tuning
Adi Kriegisch
adi at cg.tuwien.ac.at
Tue Jan 27 04:25:43 EST 2015
Hey!
> >I'm running a Kallithea instance with about 100 repositories and
> >healthy amount of CI activity across several branches on each
> >repository. I'm looking for some tips on tuning performance. I'm
> >running using waitress (at least I think I am) and see what look
> >like several knobs in the production.ini file that can be turned,
> >but I'm not really sure what I'm looking at.
[...]
> I am a relatively happy user of apache + mod_wsgi. It scales nicely
> with multiple single-threaded worker processes but might require
> more memory. (I might however investigate uwsgi.)
We're using uwsgi. Performance and management is great; there are --
however -- some caveates:
* you'll need uwsgi >=1.9 (or your git pushes will fail due to some methods
not implemented in earlier versions[1])
* you should do 'lazy' initialization; in case you're using a remote
database server you need 'lazy' initialization or you'll get SSL errors
when connecting to the database server:
'lazy' will first fork the required number of processes and then start
them. If you don't do that, the initialization of kallithea (including
establishing a database connection with SSL context) will take place and
then get forked. The error message you'll get is:
'sqlalchemy.exc.OperationalError: (OperationalError) SSL error:
decryption failed or bad record mac'
* to allow larger mercurial commits (those may contain large to huge headers),
increase the buffer size default.
* letting kallithea run as its own user is a good idea and can easily be
done in uwsgi by setting uid and gid; do not forget to allow the web
server user (www-data in most cases) to connect to the socket.
* do not forget to 'calculate' your resource requirements
(reload-on-rss * processes); also leave some RAM for celery/rabbitmq, the
web server and the linux file system cache.
The config itself is pretty simple --
/etc/uwsgi/apps-enabled/kallithea.yaml:
| uwsgi:
| plugins: python
| chdir: /venvs/kallithea
| virtualenv: /venvs/kallithea
| pythonpath: = /venvs/kallithea
| mount: /=/venvs/kallithea/dispatch.wsgi
| uid: kallithea
| gid: repos
| umask: 007
| memory-report: 1
| processes: 4
| reload-on-rss: 256
| lazy: true
| post-buffering: 4096
| # set the buffer for headers
| buffer-size: 16384
| chown-socket: www-data
| socket-timeout: 3600
I personally prefer nginx as a frontend; that may be configured like this:
/etc/nginx/sites-enabled/kallithea:
| upstream kallithea {
| server unix:///run/uwsgi/app/kallithea/socket;
| }
| server {
| (...)
| # maximum transfer size
| client_max_body_size 256m;
|
| # deliver static file from nginx
| root /srv/virtualenv/kallithea/public;
|
| location / {
|
| try_files $uri @uwsgi;
|
| }
| location @uwsgi {
| uwsgi_pass kallithea;
| uwsgi_param HTTPS on;
| uwsgi_param SCRIPT_NAME "";
| include uwsgi_params;
| uwsgi_read_timeout 3600;
| }
| }
but apache may also be able to connect to uwsgi either via socket
(mod_uwsgi) or via http.
Some random notes:
* nginx currently has an issue with post buffering[2]: a post will be kept
in memory until it is complete; then it gets forwarded. This will be
fixed in 1.7/1.8 tree at some point; for nginx 1.2 and 1.4 patches exist.
* keep in mind that Mercurial is based on python 2.7 that only has inferior
SSL support and is unable to do SNI[3]; your kallithea instance needs to be
the default virtual host for SSL. Finally, after 6 years of discussion,
python 2.7.9 might fix some of the more dangerous issues[4].
* get some guide for securing your SSL config like bettercrypto[5] or
ssllabs[6].
* for Debian, backporting uwsgi from unstable (2.0.7) is pretty simple.
* running Apache is no option to me, because the current stable version of
Apache in Debian (2.2) does not support DH params > 1024bit (and that is
no reasonable key size). Debian maintainers backported EC-Support (the
NIST curves), so you may choose for yourself. Nginx from backports
has probably the best crypto support one could get out of OpenSSL atm.
-- Adi
[1] "IOError: seeking wsgi.input without post_buffering is IMPOSSIBLE !!!"
The changelog of v1.9 list a generic implementation of seek, read and
readlines: https://github.com/unbit/uwsgi-docs/blob/master/Changelog-1.9.rst
[2] http://trac.nginx.org/nginx/ticket/251
[3] http://bugs.python.org/issue5639
[4] https://www.python.org/dev/peps/pep-0466/
[5] https://bettercrypto.org
[6] http://ssllabs.com
More information about the kallithea-general
mailing list