Ausfallsichere Anwendungen mit Solr 4 aufbauen
Mit dem Release 4.0 von Solr wurde SolrCloud [1] eingeführt, das bezüglich der Skalierbarkeit und Ausfallsicherheit von Solr einige Änderungen gegenüber den früheren Releases mit sich bringt. Dieser Beitrag geht nach einem kurzen Überblick zur SolrCloud auf Möglichkeiten ein, wie eine ausfallsichere Infrastruktur aufgebaut und wie mit ihr mittels Solrj [2] kommuniziert werden kann.
SolrCloud
Unter dem Begriff SolrCloud sind ab dem Solr Release 4.0 alle Aktivitäten gebündelt, die sich mit der Nutzung von Solr über mehrere Instanzen bzw. Maschinen hinweg beschäftigen. Dies betrifft neben den Themen Ausfallsicherheit und Skalierung von Solr-Anwendungen auch die verteilte Indexierung oder das verteilte Suchen über mehrere Instanzen.
Wesentliche Bestandteile von SolrCloud sind neben den eigentlichen Solr-Instanzen die Zookeeper. Zookeeper sind in Solr für das Halten der Konfigurationsinformationen sowie das Überwachen des Solr-Clusters zuständig. Dies bedeutet, dass bspw. die Solr-Instanzen Informationen der Konfigurationsdatei schema.xml über den Zookeeper erhalten und nicht aus der lokal abgelegten Datei. Alle Solr-Server müssen sich bei jedem Zookeeper registrieren, damit diese den Cluster entsprechend verwalten können.
Infrastruktur
Welche Mindest-Infrastruktur muss nun aufgebaut werden für ein ausfallsicheres Solr-System?
Zum einen werden mindestens zwei physikalisch getrennte Solr-Instanzen benötigt, die jeweils über sämtliche Indexe verfügen. Dies bedeutet die Solr-Instanz 1 hat die gleichen Indexe wie Solr-Instanz 2. Ergeben sich Änderungen im Index, so werden diese zwischen den Instanzen ausgetauscht.
Des Weiteren werden mindestens drei Zookeeper-Instanzen benötigt, da Zookeeper nur korrekt arbeitet, wenn die Mehrheit seiner Instanzen erreichbar ist. Bei zwei Zookeeper-Instanzen ist dies nicht gewährleistet, da der Ausfall einer Instanz das Zookeeper-Ensemble lahmlegen würde.
Damit werden mindestens drei physikalisch unabhängige Server zum Aufbau einer ausfallsicheren Solr-Infrastruktur benötigt. Die untenstehende Abbildung skizziert eine entsprechende Infrastruktur.
Auf jedem der drei Server läuft eine Zookeeper-Instanz, die jeweils mit den beiden anderen Instanzen Informationen austauscht. Die beiden Solr-Instanzen werden in diesem Beispiel über einen Apache-Server angesprochen, der die Aufgabe des Load-Balancing übernimmt.
Eine mögliche Konfiguration im Apache zum Ansprechen der beiden Solr-Server ist nachfolgend dargestellt. Für ein Produktivsystem empfiehlt sich ein Hardware-Loadbalancer.
<Proxy balancer://solrcluster>
BalancerMember http://server1:8983/solr
BalancerMember http://server2:8983/solr
ProxySet lbmethod=bytraffic
</Proxy>
ProxyPass /solr balancer://solrcluster
Mit der oben aufgeführten Infrastruktur kann nun der Ausfall einer der drei Server ohne weiteres kompensiert werden. Fällt beispielsweise Server 2 aus, dann leitet der Load-Balancer alle Anfragen an die Solr-Instanz 1 weiter. Zookeeper 1 und 3 gewährleisten, dass auch das Zookeeper –Ensemble weiter fehlerfrei funktioniert.
Ist Server 2 wieder verfügbar, so gliedert sich der Zookeeper 2 wieder in das Ensemble ein und die zweite Solr-Instanz erhält von der ersten Solr-Instanz Index-Änderungen die zwischenzeitlich ggfs. erfolgt sind.
Kommunikation über Solrj
In dem vorgestellten Szenario kommuniziert der Client nur über die Load-Balancer-Adresse mit Solr. In Grails würde eine Kommunikation über Solrj wie im nachfolgenden Code skizziert ablaufen.
HttpSolrServer server = new HttpSolrServer( http://loadbalancer/solr)
// neues Dokument zum Index hinzufügen
server.add(docsToIndex)
server.commit()
Eine weitere Möglichkeit zum Aufbau einer Solr-Infrastruktur ist der Verzicht auf einen Load-Balancer wodurch sich die Infrastruktur wie nachfolgend abgebildet ändert.
In diesem Fall ist der Solrj-Client für das Load-Balancing und die Kommunkation mit dem Cluster zuständig. Dies erfolgt durch die Klasse LBHttpSolrServer, die mit den entsprechenden Server-Daten initialisiert wird. Im nachfolgenden Code-Fragment ist dieser Vorgang exemplarisch dargestellt.
LBHttpSolrServer lbServer = new LBHttpSolrServer("http://server1:8983/solr/","http://server2:8983/solr")
server = new CloudSolrServer("server1:2181,server2:2182,server3:2183", lbServer)
server.setDefaultCollection('collection1')
Fazit
Die Konfiguration einer ausfallsicheren Solr-Umgebung scheint aufgrund der Zookeeper auf den ersten Blick umständlich und kompliziert zu sein. Hat man sich allerdings ein wenig mit den Prinzipien der SolrCloud beschäftigt geht die Konfiguration recht einfach von der Hand. Insofern hat Solr mit dem Release 4 einen großen Schritt in Richtung Skalierbarkeit und Ausfallsicherheit getan.
Da zur Gewährleistung der Ausfallsicherheit mindestens drei unabhängige Server benötigt werden, lohnt sich abhängig von den Anforderungen ggfs. auch ein Blick auf ElasticSearch [4]. Hier kann mit zwei Servern eine entsprechende Ausfallsicherheit erreicht werden.
Fazit
[1] SolrCloud
[2] Solrj
[3] Zookeeper Homepage
[4] Elastic Search