Shariff: Schneller Schießen

Das vom heise Zeitschriftenverlag gestartete Projekt Shariff ist großartig, um Sharing funktionsreich und datenschutzfreundlich zu gestalten. Doch ohne spezielle Einrichtung nimmt es viel Serverleistung in Anspruch, außerdem brauchen die Counter-Requests recht lange. Hier soll es darum gehen, wie man dies löst und einen Shariff-Service für mehrere Websites aufbaut.

Shariff: Sharing, Datenschutz inklusive

Shariff baut im Browser erst dann eine Verbindung zu einem Social Media Dienst auf, wenn der Nutzer dies explizit wünscht. So wird verhindert, dass Facebook und Co umfangreiche Profile über das Surfanhalten von Nutzern anlegen können.

Shariff: das Projekt der ct ermöglicht datenschutzfreundliches Sharing. Bild © ct.
Shariff: das Projekt der ct ermöglicht datenschutzfreundliches Sharing. Bild © ct.
Gleichzeitig bietet Shariff aber auch einen Zähler, wie häufig ein Post geteilt wurde. Dies wird mit Hilfe des Shariff Backends realisiert: das Backend fragt für den User beim Sozialen Netzwerk den Zählerstand ab und reicht die Information dann via JSON-API an den Nutzer weiter. Dieses Backend kann falsch eingerichtet den Server stark belasten. Um das Shariff Backend zu beschleunigen, wird auf zwei Techniken gesetzt. Beide Techniken erfordern einen Root-Server.

  1. Shariff-internes Caching
  2. Schnellerer PHP-Interpreter (HHVM)

Shariff auf Speed: Caching

Eingerichtet werden kann das Shariff-interne Caching über die die Konfigurationsdatei shariff.json. Dies sieht dann wie folgt aus, wenn man Memcached nutzen will. Aber Achtung: das geht nur, wenn man die unten erwähnte Infrastruktur-Instanz von Shariff verwendet. Das WordPress Plugin verwendet das WordPress-Interne Caching und ist damit nur sehr mäßig effektiv. Es unterstützt nicht das Zend Caching Backend.

{
  "cache": {
    "adapter": "Memcache",
    "adapterOptions": {
      "servers": [
        {
          "host": "localhost",
          "port": 11211
        }
      ]
    },
    "ttl": 60
  },
  [...]
}

Erlaubt sind alle Caching-Backends, welche Zend_Cache ermöglicht. In meinem Fall bot sich Memcached an, weil ich dies auch für etliche andere Webapplikationen nutze. Je nach Backend muss man natürlich auch die adapterOptions anpassen. Mit aktiviertem Caching speichert Shariff den Zähler für die Zeit ttl (in Sekunden) zwischen. Damit vermeidet man eine Überlastung der APIs der jeweiligen Netzwerke und erhöht die Geschwindigkeit ganz erheblich.

Shariff auf Speed: HHVM

Die zweite äußerst wirkungsvolle Maßnahme, um Shariff zu beschleunigen, ist der alternative PHP-Interpreter HHVM. Dieser macht z.B. auch bei Piwik eine großartige Arbeit, setzt aber sauberen Code voraus. Glücklicherweise wird heise seinem guten Ruf gerecht und liefert sauberen Code ab, so dass man HHVM für Shariff nutzen kann. Ähnlich wie bei Piwik nutzt man HHVM am Besten via Nginx und FCGI. Die vHost Config sähe dann in etwa so aus:

server {
        listen 443;
        listen [::]:443;

        root /mein/pfad/zu/shariff;
        index index.php;

        server_name shariff.meine-seite.de;

        [...]

        # Die Konfigurationsdatei sollte nicht abrufbar sein.
        location /shariff.json {
                deny all;
        }

        # Wir wollen, dass auch von anderen Domains Daten abgerufen werden können
        add_header Access-Control-Allow-Origin "*";

        location ~ \.php$ {
                try_files $uri = 404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                # Die Weiterleitung an HHVM. Der Port muss natürlich an die eigene HHVM-Instanz angepasst werden.
                fastcgi_pass 127.0.0.1:12345;
                fastcgi_index index.php;
                include fastcgi_params;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_param SCRIPT_NAME $fastcgi_script_name;
        }
}

Besonders wichtig ist der Schutz der shariff.json: dort steht das Facebook App-Secret drin, welches man sicherlich nicht öffentlich haben mag. Mit der Ergänzung des Headers ermöglichen wir, dass jede Domain von unserer Shariff-Instanz Daten abrufen kann. Dies wird v.a. für den Punkt „Shariff for everyone“ benötigt. Außerdem muss man natürlich HHVM einrichten und dann auf den verwendeten Port verweisen. Hierzu lohnt sich ein Blick in das Piwik-Tutorial.

Shariff for everyone

Wenn man eine Vielzahl von Websites hat, auf denen man Shariff einsetzen möchte, so macht es Sinn, eine besonders optimierte Shariff-Installation zu pflegen. Hierfür holt man sich Shariff-Frontend und -Backend von Github und baut sich seine Shariff-Instanz auf:

adduser shariff
mkdir /var/www/shariff
chown -R shariff:shariff /var/www/shariff
sudo -i -u shariff
mkdir /var/www/shariff/backend
cd /var/www/shariff/backend
git clone https://github.com/heiseonline/shariff-backend-php.git .
mkdir /var/www/shariff/frontend
cd /var/www/shariff/frontend
git clone https://github.com/heiseonline/shariff.git .
mkdir /var/www/shariff/httpdocs
mkdir /var/www/shariff/httpdocs/backend
mkdir /var/www/shariff/httpdocs/js
mkdir /var/www/shariff/httpdocs/css
cd /var/www/shariff/httpdocs
ln -s ../backend/build/shariff.json ./backend/
ln -s ../backend/build/index.php  ./backend/
ln -s ../backend/build/src  ./backend/
ln -s ../backend/build/vendor  ./backend/
ln -s /pfad/zum/wordpress/plugin/css/shariff.min.css ./css/
ln -s /pfad/zum/wordpress/plugin/js/shariff.min.js ./js/

Der Webserver muss dann als root /var/www/shariff/httpdocs nutzen. Nun müssen noch die Domains definiert werden, für den wir den Service anbieten. Es wäre nicht gut, Shariff für beliebige Domains anzubieten. Da Shariff aber von Haus aus nur die Definition einer Domain erlaubt, müssen wir einen kleinen Patch schreiben. Hierzu ergänzen wir die settings.json zunächst um ein Array von Domains:

{
  [...]
  "domain": [
    "sectio-aurea.org",
    "ruhrmobil-e.de"
  ],
  [...]
}

Außerdem müssen wir noch die Funktion isValidDomain in der Datei src/Backend/BackendManager.php ändern, damit Shariff in Zukunft schaut, ob die abgefragte Domain im Array ist:

    private function isValidDomain($url)
    {
        if ($this->domain) {
            $parsed = parse_url($url);
            if (!in_array($parsed["host"], $this->domain)) {
                return false;
            }
        }
        return true;
    }

Nun hat man eine fertige Infrastruktur-Installation von Shariff.

Shariff für WordPresss

Möchte man nun die oben installierte Shariff-Instanz in WordPress einbinden, eignet sich das Shariff Wrapper Plugin. Nach meinem Vorschlag im Support-Forum unterstützt es externe Server. Perfekt! Also: einfach eintragen.

Fazit

Mit der neuen beschleunigten Shariff-Instanz kann ich für all meine Blogs Shariff anbieten, ohne eine nennenswerte Last auf meinen Server zu legen. Bei einem kurzen Test waren problemlos über 100 Requests / Sekunde auf einen Instanz auf diesem vServer möglich, Werte, von denen ich zuvor nur träumen konnte. Die Aktivierung ist so einfach, dass das in Zukunft zu meinen Standard-Plugins gehören wird. Ich freue mich über Nachfragen und Nachmacher!

10 Antworten zu “Shariff: Schneller Schießen”

  1. Hi Ernesto,

    Respekt! Was mich Shariff stört ist das es nach 1000 aufwärts keine ,1 etc. anzeigt sondern bei 1k und das bis 2k also nicht 1.1k, 1.2k etc. Oder habe ich hier was falsch gemacht bzw. eingestellt?

    Grüße Mika

  2. Hallo und Danke für den interessanten Beitrag. Im Shariff Wrapper gibt es ja die Einstellungsmöglichkeit für den Cache. Muss dann trotzdem der oben genannte Code in der Konfigurationsdatei shariff.json eingefügt werden oder erübrigt sich das?

    Beste Grüße

    Hansjörg Leichsenring

    • Ich diskutiere da oben ja eine zentralisierte und mit HHVM beschleunigte Installation von Shariff. Da haben die Einstellungen im Shariff Wrapper keinen Einfluss drauf, diese werden dann z.T. nutzlos.
      Allerdings sehe ich auch nur, dass man die Cache-Lebenszeit einstellen kann. Das Standard-Caching ist allerdings recht langsam, deswegen möchte man das nicht wirklich nutzen. Bei Webspace bleibt einem nichts anderes übrig, aber die ganze Anleitung ist ja auch nicht für Webspace gedacht.

  3. Dann muss ich noch mal (vermutlich doof) nachfragen: Worin unterscheidet sich der erste Teil „Eingerichtet werden kann das Shariff-interne Caching über die die Konfigurationsdatei shariff.json“ vom Standard Caching im Wrapper Plugin?

    VG

    Hansjörg Leichsenring

    • Ja. Du kannst in der shariff.json erheblich mehr machen. Normalerweise verwendet Shariff per default HDD-Caching. Das ist relativ ineffizient. Da man aber als Pluginautor nicht davon ausgehen kann, dass auf dem Webspace mehr vorliegt, ist das eben der kleinste gemeinsame Nenner. Wenn man mehr Geschwindigkeit will, sollte man eine der schnelleren Caching-Methoden wie eben Memcached nehmen.

  4. Ich hab mich nun mal probiert, den ersten Teil umzusetzen und dabei festgestellt, dass beim Wrapper Plugin keine shariff.json Datei vorhanden ist. Kann ich die einfach mit dem oben genannten Code erstellen und im Ordner Backend abspeichern?

    • Die shariff.json gibt es ja auch nur, wenn du eine eigene zentralisierte Shariff-Instanz machst. Und: kann es sein, dass du diesen Part: „Um das Shariff Backend zu beschleunigen, wird auf zwei Techniken gesetzt. Beide Techniken erfordern einen Root-Server.“ nicht gelesen hast? 😉

  5. Gelesen schon, aber vielleicht nicht richtig verstanden 🙂

    Ich hab zwar keinen Root Server, aber Memcached wird unterstützt. Von daher war ich der Meinung, dass ich den ersten Teil auch ohne die zentralisierte Instanz nutzen kann

    • Dann hast du zwei Möglichkeiten:
      1) du baust dir eine zentralisierte Instanz, indem du das Paket manuell von Github herunterlädst und auf eine Subdomain installierst. Das Updaten wird ohne Shell-Zugang ein wenig nervig, weil es kein git pull gibt, aber da kommst du dann nicht drumrum.
      2) du baust die Caching-Konfiguration in das Plugin ein. Das dürfte hier geschehen müssen: https://github.com/3UU/wordpress-shariff-wrapper/blob/master/shariff/backend/index.php . Das Plugin speichert die Werte zur Zeit in die Datenbank und nutzt den Shariff-internen Caching-Mechanismus nicht, was durchaus Sinn ergibt, wenn es universell funktionieren soll – aber das macht es eben auch langsam, weil jedes mal ein Haufen SQL Querys abgefeuert werden müssen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.