Wraz z premierą Solr 7.2 dostaliśmy nową opcję dostępną w ramach Collections API – możliwość zmuszenia Solr do relokacji replik na podstawie ustawień autoscalingu. Solr przygląda się replikom oraz ustawieniom autoscalingu, a następnie, w miarę możliwości automatycznie przydziela repliki do zadanej instancji Solr. Brzmi bardzo fajnie w teorii, zobaczmy zatem, jak działa w praktyce.
Autoscaling API w Solr
Jeżeli nie wiesz co to jest Autoscaling API Solr pozwolę sobię na szybkie wprowadzenie. Jest to API pozwalające na ustawianie reguł dla klastra lub kolekcji, które mówią Solr jak mają być alokowane repliki w Solr. Chcemy wziąć pod uwagę wykorzystanie procesora danej instancji Solr – możemy to zrobić. Chcemy wziąć pod uwagę wyjorzystanie dysku na danej instancji – oczywiście możemy to zrobić. Najfajniejsze jest to, iż reguły mogą być definiowane zarówno dla całego klastra, jak również dla pojedynczych kolekcji w klastrze. Daje nam to całkiem dużą swobodę jeżeli chodzi o konfigurację.
Aczkolwiek, zdefiniowane reguły używane są tylko podczas przypisywania replik do instancji Solr. Oznacza to, że w momencie kiedy kolekcja została już stworzona Solr nie będzie korzystał z tych informacji podczas dodawania replik. Zmieniło się to wraz z wprowadzeniem Solr 7.2, gdzie dostaliśmy do dyspozycji komendę UTILIZENODE.
Środowisko testowe
Aby umożliwić proste odtworzenie testu zdecydowałem się na urucomienie banalnego środowiska testowego opartego o Solr 7.2 składającego się z dwóch instancji Solr. Pierwsza z nich uruchomiona została następującym poleceniem:
$ bin/solr start -c
Drugą instancję Solr uruchamiamy następującym poleceniem:
$ bin/solr start -z localhost:9983 -p 6683
Po uruchomieniu obu instancji tworzymy pojedynczą kolekcję nazwaną test zbudowaną z jednego lidera i trzech replik, wszystkie stworzone na pojedynczej instancji Solr. Nasz widok kolekcji wygląda następująco:
A sam stan opisany odpowiednim plikiem JSON wygląda następująco:
{"test":{ "pullReplicas":"0", "replicationFactor":"1", "router":{"name":"compositeId"}, "maxShardsPerNode":"1", "autoAddReplicas":"false", "nrtReplicas":"1", "tlogReplicas":"0", "shards":{"shard1":{ "range":"80000000-7fffffff", "state":"active", "replicas":{ "core_node2":{ "core":"test_shard1_replica_n1", "base_url":"http://192.168.1.15:8983/solr", "node_name":"192.168.1.15:8983_solr", "state":"active", "type":"NRT", "leader":"true"}, "core_node4":{ "core":"test_shard1_replica_n3", "base_url":"http://192.168.1.15:8983/solr", "node_name":"192.168.1.15:8983_solr", "state":"active", "type":"NRT"}, "core_node6":{ "core":"test_shard1_replica_n5", "base_url":"http://192.168.1.15:8983/solr", "node_name":"192.168.1.15:8983_solr", "state":"active", "type":"NRT"}, "core_node8":{ "core":"test_shard1_replica_n7", "base_url":"http://192.168.1.15:8983/solr", "node_name":"192.168.1.15:8983_solr", "state":"active", "type":"NRT"}}}}}}
Jak widać mamy potwierdzenie tego, iż wszystkie shardy zostały przypisane do tego samej instancji Solr – tej z base_url równą http://192.168.1.15:8983/solr.
Mamy zatem następującą sytuację:
- Mamy klaster Solr, który stowrzony jest z dwóch instancji Solr
- W ramach klastra stworzona jest pojedyncza kolekcja
- Nasza kolekcja zbudowana jest z czterech shardów – jednego lidera oraz trzech replik
- Wszystkie shardy przypisane są do pojedynczej instancji Solr
Podsumowując – nie korzystamy z wszystkich instancji Solr. Spróbujmy to zmienić korzystając z komendy UTILIZENODE wprowadzonej w Collections API w Solr 7.2.
Korzystanie z UTILIZENODE w API kolekcji
Aby zilustrować działanie Autoscaling API oraz UTILIZENODE w Collections API ustawimy pewne preferencje alokacji replik dla całego klastra. Przy pomocy następującego polecenia powiemy Solr, aby starał się minimalizować liczbę coreów na każdej instancji Solr dostępnej w klastrze:
$ curl -XPOST 'localhost:8983/api/cluster/autoscaling' -H 'Content-Type:application/json' -d '{ "set-cluster-preferences" : [ {"minimize": "cores"} ] }'
Powyższe polecenie ustawia właściwości dla klastra dotyczące preferencji umieszczania shardów. Mówi, że Solr ma minimalizować liczbę coreów na każdej instancji, a zatem dążyć do jak największego rozproszenia kolekcji. Zatem teraz, korzystając z polecenia UTILIZENODE z Collections API możemy zmusić Solr, aby druga, nieużywana instancja Solr zaczęła być wykorzystywana. Robimy to następującym poleceniem:
$ curl -XGET 'localhost:8983/solr/admin/collections?action=UTILIZENODE&node=192.168.1.15:6683_solr'
Parametr node jest konieczny ponieważ musimy powiedziec Solr, która instancja Solr powinna być brana pod uwagę podczas alokacji. Przetwarzanie polecenia, w zależności od wielkości replik może zająć dość długo, a w związku z tym, w systemie produkcyjnym sugerowane jest uruchamianie tej komendy w asynchronicznie. W naszym przypadku wykonanie będzie dość szybkie i skutkuje takimi zmianami w klastrze:
Plik JSON opisujący stan kolekcji, po zmianach, wygląda następująco:
{"test":{ "pullReplicas":"0", "replicationFactor":"1", "shards":{"shard1":{ "range":"80000000-7fffffff", "state":"active", "replicas":{ "core_node6":{ "core":"test_shard1_replica_n5", "base_url":"http://192.168.1.15:8983/solr", "node_name":"192.168.1.15:8983_solr", "state":"active", "type":"NRT", "leader":"true"}, "core_node8":{ "core":"test_shard1_replica_n7", "base_url":"http://192.168.1.15:8983/solr", "node_name":"192.168.1.15:8983_solr", "state":"active", "type":"NRT"}, "core_node10":{ "core":"test_shard1_replica_n9", "base_url":"http://192.168.1.15:6683/solr", "node_name":"192.168.1.15:6683_solr", "state":"active", "type":"NRT"}, "core_node12":{ "core":"test_shard1_replica_n11", "base_url":"http://192.168.1.15:6683/solr", "node_name":"192.168.1.15:6683_solr", "state":"active", "type":"NRT"}}}}, "router":{"name":"compositeId"}, "maxShardsPerNode":"1", "autoAddReplicas":"false", "nrtReplicas":"1", "tlogReplicas":"0"}}
Jak widać dwie repliki zostały przesunięte z instancji 192.168.1.15:8983_solr do instancji 192.168.1.15:6683_solr, czyli Solr zrobił dokładnie to co chcieliśmy.
Podsumowanie
Komenda UTILIZENODE z API kolekcji jest pewną formą automatyzacji zarządzania klastrem. Oczywiście podobny efekt uzyskamy korzystając z poleceń ADDREPLICA oraz DELETEREPLICA ale będzie to zarządzanie manualne i nie będzie brało pod uwagę ustawień klastra i kolekcji. Komenda UTILIZENODE daje nam pewność, iż wszystkie ustawienia, zarówno te dotyczące klastra, jak i te dotyczące kolekcji będą zachowane.