OwnCloud: Performance-Tuning für OwnCloud 8.x

Im folgenden habe ich die wichtigsten Tipps und Tricks zusammen getragen, die OwnCloud 8.x auch auf schwacher Hardware zum Rennen bringen. Dieser Artikel bezieht sich ausschließlich auf OwnCloud 8.x, zu OwnCloud 9.x bitte hier weiterlesen. Mein Fokus liegt dabei auf dem Cubietruck bzw. Raspberry PI2. Die Liste ist selbstverständlich unvollständig – ich freue mich immer über Ergänzungen und Korrekturen in den Kommentaren. Ich werde die Liste in den nächsten Wochen weiter pflegen und auf neuere OwnCloud-Versionen erweitern.

Beginnen wir mit den Standard-Tipps, die man selbstverständlich schon umgesetzt haben sollte. Ich führe sie hier nur kurz als „Merkzettel“ auf.

0. Standard-Tipps

  • Cron verwenden. Damit die Hintergrundaufgaben nicht bei jedem Seitenaufruf ausgeführt werden müssen, ist es extem empfehlenswert diese via Cronjob ausführen zu lassen:
    # crontab -u www-data -e
    
    */15 * * * * php -f /var/www/owncloud/cron.php > /dev/null 2>&1
    
  • Eine zu MySQL kompatible Datenbank verwenden – ich empfehle MariaDB
  • PHP-FPM >5.6 mit OpCache und einen Memory-Cache verwenden (siehe unten auch der Hinweis auf APCu)
  • Nginx verwenden

1. OwnCloud-Konfiguration config.php

Die folgenden Einstellungen sollten in der config.php der OwnCloud-Installation vorgenommen werden.

Journal der Activities-App

Falls die Activities-App eingesetzt wird, das Journal nicht endlos anwachsen lassen:

'activity_expire_days' => 90,

Wenn der Cron-Job läuft, wird das Journal der vorgenommenen Aktivitäten auf den angegebenen Zeitraum gekürzt. Bei sehr lange laufenden Installationen kann das Journal recht groß werden und so viel Speicherplatz verschwenden.

Memory-Caching aktivieren

OwnCloud stellt mehrere Backends für das Caching von Daten bereit. Aktuell sind dies:

  • \OC\Memcache\APC Alternative PHP Cache backend
  • \OC\Memcache\APCu APC user backend
  • \OC\Memcache\ArrayCache In-memory array-based backend (nicht empfohlen)
  • \OC\Memcache\Memcached Memcached backend
  • \OC\Memcache\Redis Redis backend
  • \OC\Memcache\XCache XCache backend

Ich bevorzuge und empfehle für OwnCloud wegen der einfachen Installation und Wartung das APCu-Backend. Nicht nur Gentoo, sondern so ziemlich jeden Distribution bringt APCu von Hause aus mit. APCu wird aktiviert via:

'memcache.local' => '\OC\Memcache\APCu',

Leider funktioniert selbst mit OwnCloud 8.2.3 noch nicht das zu PHP7 passende APCu-Backend (Version 5.1.2). Um dieses dennoch nutzen zu können muss di1717e Datei „lib/private/memcache/apcu.php“ durch die auf Git-Hub veröffentlichten Version ersetzt werden.

Memory-Caching Für das File-Locking aktivieren (<PHP7)

In OwnCloud 8.2 wurde die File-Locking-App entfernt und voll auf das so genannte Transactional-File-Locking umgestellt. Standardmäßig verwendet OwnCloud die Datenbank für das Sichern der File-Locks, was je nach Anbindung und Geschwindigkeit der Datenbank zu einem spührbaren Geschwindigkeitsverlust der gesamten OwnCloud-Installation führen kann. Ich empfehle ab OwnCloud 8.2, das Redis-Backend als Memory-Cache zu nutzen. Leider steht pecl-redis für PHP7 noch nicht zur Verfügung. In der config.php sind dafür die folgenden Zeilen einzufügen:

'memcache.local' => '\OC\Memcache\APCu',
'memcache.locking' => '\OC\Memcache\Redis',
'redis' => array(
     'host' => '/var/run/redis/redis.sock',
     'port' => 0,
      ),

Ich empfehle hier aus Gründen der Sicherheit und der Performance auf den Unix-Socket zu setzen und keinen weiteren Port zu exponieren. Meine /etc/redis.conf habe ich weitestgehend unmodifiziert gelassen und nur diese Zeilen eingefügt bzw. verändert:

port 0
unixsocket /var/run/redis/redis.sock                                                                                                                                                         
unixsocketperm 770

Die Socket-Datei gehört dabei dem Benutzer „redis“ und der Gruppe „nginx“ (bei mir, kann aber je nach System auch „www“ o.ä. sein). Auf meinem Gentoo-System wird dies in der Datei /etc/conf.d/redis konfiguriert:

# Redis user.                                                                                                                                                                                
REDIS_USER="redis"                                                                                                                                                                           
# Redis group.                                                                                                                                                                               
REDIS_GROUP="nginx"                                                                                                                                                                          

Asset-Pipelining aktivieren

OwnCloud kann die vielen CSS und Javascript in der OwnCloud-Installation zusammengefasst und komprimiert ausliefern, was sehr viel Zeit beim Laden der Seite spart. Dazu werden die Dateien im Vorhinein zusammengefasst und im Assets-Verzeichnis der OwnCloud-Installation abgelegt. Dazu muss der Webserver Schreibrechte für das Verzeichnis „assets“ in der OwnCloud-Installation besitzen. Diese muss ggf. zuvor noch erzeugt werden.

'asset-pipeline.enabled' => true, 

2. allgemeine Systemoptimierungen

BEI DYNDNS-DOMAINNAMEN EXTERNEN HOSTNAMEN IN HOSTS-DATEI EINTRAGEN

Für den Zugriff auf die OwnCloud über den (externen) Namen der Webseite, der z.B. bei DynDNS-Domains, wird sehr viel Zeit verbraucht, weil für die Namensauflösung der DNS des Gateways und über diesen der DNS des DynDNS-Anbieters verwendet wird. Wenn der externe Name in die /etc/hosts-Datei eingetragen wird, fällt die komplette Namensauflösung weg.

TMP-FS

Um das Erstellen und Verwalten von Session in OwnCloud zu beschleunigen, sollte das TMP-Dateisystem auf einem schnellen Medium wie einer SSD oder gar auf einer RAM-Disk liegen, was via /etc/fstab so erreicht werden kann:

tmpfs /tmp tmpfs defaults,noatime,nosuid,nodev,noexec,mode=1777 0 0

BTRFS als Dateisystem verwenden

Wenn auf dem System ein hinreichend aktueller Kernel läuft (also ein >4.x Kernel), lohnt es sich die OwnCloud-Dateien und die Datenbank auf einem BTRFS formatierten Datenträger abzulegen. In meinem System liegt die OwnCloud auf einer WD-Red 2.5″ Festplatte am SATA-Port des Cubietrucks. Der Wechsel auf BRTFS verkürzte die Antwortzeit (ohne Caching) um etwa 30%. Für den Cubietruck sollte auf jeden Fall ein Mainline-Kernel genutzt werden, denn in den von den Android-Builds portierten 3.4.x Kernels ist BTRFS noch nicht hinreichend stabil und performant. Meine Kernel-Builds für den Cubietruck stelle ich auf dieser Seite zur Verfügung.

Ein wichtiger Aspekt ist bei EXT4 noch anpassungswürdig. Das Schreiben des Zeitstempels für lesende Zugriffe auf die Datei sollte auf Servern mit Magnetfestplatte oder SD-Karte deaktiviert werden. Dazu wird in die Mount-Parameter die Option „noatime“ aufgenommen. Exemplarisch sieht das in der /etc/fstab so aus:


/dev/sda2  /  ext4  noatime  0 1

Latenzoptimierung des Ondemand-Schedulers

Der Ondemand-Scheduler des Kernels ist für die Regelung der Taktfrequenzen des Hauptprozessors zuständig. Gerade auf dem Cubietruck ist dieser jedoch für hohe Latenzen beim Laden von Webseiten verantwortlich, weil er zu spät den Takt erhöht. Bei den 3.4er-Kernels steht der wesentlich besser funktionierende „interactive“-Scheduler zur Verfügung, bei den Mainline-Kernels jedoch nicht. Die Performance lässt sich hier durch eine geeignete Parametrisierung des ondemand-Schedulers verbessern. Ich lade die Einstellungen über die (anzulegende) Datei /etc/local.d/ondemand_tuning.start:

#!/bin/sh                                                                                                                                                                                    
echo ondemand > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
echo 1008000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq
echo 408000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq
echo 25 > /sys/devices/system/cpu/cpufreq/ondemand/up_threshold
echo 10 > /sys/devices/system/cpu/cpufreq/ondemand/sampling_down_factor
echo 1 > /sys/devices/system/cpu/cpufreq/ondemand/io_is_busy

Wichtig hier ist insbesondere auch die Limitierung der minimalen Taktfrequenz auf 408MHz – wird eine geringere Frequenz gewählt, dauert das Aufwachen bzw. der Wechsel in den Idle-Zustand deutlich länger.

WEITERE LATENZOPTIMIERUNGEN

Auch die Art und Weise wie der Kernel neu erstellte Prozesse auf die Kerne verteilt, hat einen großen Einfluss auf die Responsivität des Servers. Eine auf Desktop-Systemen sehr nützliche Einstellung ist die Auto-Gruppierung des Scheduler. Hier werden normalerweise Prozesse je nach TTY gruppiert um die gefühlte Performance auf einem interaktiven System zu verbessern. Allerdings verhindert dies auch die Migration von erzeugten Kind-Prozessen auf andere CPUs, was auf einem Server mit einem sehr, sehr lange laufenden Daemon kontraproduktiv ist. Autogrouping wird in der /etc/sysctl.conf deaktiviert:

kernel.sched_autogroup_enabled = 0

NETZWERK-OPTIMIERUNGEN

Wenn die OwnCloud auf einem System mit leistungsschwacher CPU läuft, sollte man sich überlegen, SYN-Cookies zu deaktivieren. Diese sind zwar ein gutes Mittel um Denial-Of-Service-Attacken abzuwehren, jedoch gilt dies nicht für leistungsschwache Systeme, da hier viel Rechenleistung für die Berechnungen der SYN-Coockies benötigt wird. Ein SYN-Flood-Angriff würde zwar scheitern, jedoch würde dem System dennoch die Puste ausgehen, was den Angriff letztendlich doch gelingen lässt. Die Einstellung ändert man in der Datei /etc/sysctl.conf, die dann für leistungsschwache Systeme so aussieht:

net.ipv4.tcp_syncookies = 0

Auf potenterer Hardware im Sinne der CPU-Leistung sieht dies jedoch genau andersherum aus. Hier sollten SYN-Cookies aktiviert werden und sogar die Anzahl der überwachten Sockets und die Tiefe des Backlogs erhöht werden:

net.ipv4.tcp_syncookies = 1
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 2048

3. Webserver

Gerade auf leistungsschwachen Systemen wie den gängigen ARM-Boards (Raspberry-PI, Cubietruck, Banana-PI) ist die Leistung des Crypto-Subsystemes recht schwach – besonders im Vergleich mit modernen Intel-Prozessoren mit AES-NI-Erweiterungen. Eine wichtige Tuningmaßnahme ist daher, die teuren SSL-Session-Setups zu minimieren.

SSL session reuse

Im Nginx sollte auf jeden Fall die Wiederverwertung von SSL Sessions und Session-Tickets aktiviert werden. Dies führt zu einer merklich kürzeren Latenz bei Laden der OwnCloud-Webseiten und erleichtert die „tägliche“ Arbeit mit den jeweiligen OwnCloud-Apps.

ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_ticket_key /etc/ssl/ssl_session_ticket.key;
ssl_session_tickets on;

SPDY-Protokoll bzw HTTP/2 aktivieren

Das SPDY-Protokoll ist eine Ergänzung des HTTP-Protokolls und kann die Zugriffe auf die OwnCloud-Instanz teilweise erheblich beschleunigen. In älteren Versionen (7.x) gab es hier einige Einschränkungen und Fehler, mit OwnCloud 8.x sollten diese nicht mehr auftreten. SPDY wird in der nginx.conf konfiguriert. Hier muss SPDY in die „listen“-Zeile der unterstützten Protokolle aufgenommen werden und die Fähigkeit via Header annonciert werden:

listen 6443 ssl spdy default deferred;

# RSP: add google spdy support --> http://nginx.org/en/docs/http/ngx_http_spdy_module.html#spdy_headers_comp
# http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_buffer_size
add_header Alternate-Protocol  6443:npn-spdy/3;
spdy_headers_comp 6;
ssl_buffer_size 4k;

Update:Nginx ab der Version 1.9.5 im Mainline-Branch unterstützt nun HTTP/2 das als direkter Nachfolger von SPDY gesehen werden kann. Alle wichtigen Browser unterstützen nun auch HTTP/2, daher sollte dieses Protokoll vorgezogen werden. Die Vorgehensweise ist ähnlich dem vom SPDY, jedoch muss man sich hier nicht um das Anfügen von alternativ-Protokoll-Headern kümmern:

listen 6443 ssl http2 default deferred;

Statische Webseiten direkt via Nginx ausliefern (bis OwnCloud 8.1.x)

Web-Content, der sich nicht ändert, sollte so möglich nicht via PHP ausgeliefert werden, sondern direkt via Nginx verteilt werden. Wie dies zu realisieren ist, habe ich ausführlich hier beschrieben. Dies funktioniert leider mehr mit OwnCloud >=8.2, denn die Unterstützung für XSendFile wurde mit dieser Version entfernt. Darum an dieser Stelle nur die einzufügenden Code-Zeilen für die nginx.conf mit OwnCloud bis Version 8.2:

location ~ \.php(?:$|/) {
# ...
     fastcgi_param MOD_X_ACCEL_REDIRECT_ENABLED on;
     fastcgi_param MOD_X_ACCEL_REDIRECT_PREFIX /xaccel;
# ...
} 

Nach der PHP-Sektion wird eine weitere Sektion angelegt, die alle mit dem Präfix gekennzeichneten Dateien als intern auszuliefern markiert:

location ^~ /xaccel {
    internal;
    alias /;
}

Statische Inhalte bereits vorkomprimiert direkt ausliefern (bis OwnCloud 8.1.x)

HTML-Seiten und andere gut komprimierbare Inhalte in komprimierter Form auszuliefern, spart Bandbreite und erhöht die Performance… üblicherweise. Leider gilt dieser Grundsatz nicht für schwache Hardware wie Embedded-ARM-Boards wie den Cubietruck, Raspberry-PI oder Banana-PI. Hier ist es sinnvoll die auszuliefernden Dateien bereits komprimiert auf der Platte abzulegen und so die Prozessorleistung nicht für die Kompression zu verschwenden. Static-GZIP wird in der nginx.conf folgendermaßen aktiviert:

# RSP: Support serving pre-compressed static files, disallow on-demand compression to reduce CPU load
        gzip off;
        gzip_vary off;
        gzip_comp_level 1;
        gzip_static on;
        gzip_buffers 16 8k;
        gzip_http_version 1.1;
        gzip_types text/plain text/css application/json application/x-javascript text/xml text/x-js application/xml+rss text/javascript image/svg+xml application/atom+xml application/xml;
        gzip_proxied expired no-cache no-store private auth;
        gzip_disable "MSIE [1-6]\.(?!.*SV1)";

Nun muss man die entsprechenden Dateien nur noch auf der Fesplatte komprimiert ablegen. Dazu finden man so manche auf find & Co. basierende Skripte, die via Cron-Job das WWW-Verzeichnis durchstöbern und alle in Frage kommenden Dateien komprimieren. Aus meiner Sicht ist dies nicht günstig, weil die Dateien zum einen vom unkomprimierten Original abweichen können und zum anderen nicht direkt nach dem Erzeugen der Datei zur Verfügung stehen. Ich empfehle die Dateien via inotify bei der Erzeugung bzw. beim Modifizieren neu zu komprimieren. Dazu dient dieses im Hintergrund laufende BASH-Skript:

#!/bin/bash
 
inotifywait -m -q -e CREATE -e MODIFY -e MOVED_TO -e DELETE -e MOVED_FROM -r "/var/www/localhost/htdocs/" -c --excludei '\.(jpg|png|gif|ico|log|sql|zip|gz|pdf|php|swf|ttf|eot|woff|)$' |
        while read file
        do
                file=( ${file//,/ } )
                pathname=${file[0]}
                action=${file[1]}
                filename=${file[2]}
                if [[ $filename =~ \.(html|css|js|xml|json|sfw)$ ]];
                then
                        if [[ $action == @(DELETE|MOVED_FROM) ]];
                        then
                                rm -f $pathname$filename.gz
                        elif [[ $action == @(CREATE|MODIFY|MOVED_TO) ]];
                        then
                                gzip -f -c -9 $pathname$filename > $pathname$filename.gz
                        fi

                fi
        done

2 Antworten auf „OwnCloud: Performance-Tuning für OwnCloud 8.x“

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

eins × 2 =