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