Trochę tła
Od lat używam klejnotu Apartamentu do prowadzenia aplikacji wielodostępnej. Niedawno pojawiła się potrzeba skalowania bazy danych na osobne hosty, serwer db po prostu nie może już dłużej nadążać (zarówno odczyty, jak i zapisy stają się zbyt duże) - i tak, skalowałem sprzęt do maksimum (dedykowany sprzęt, 64 rdzenie, 12 napędów Nvm-e w RAID 10, 384 Gb RAM itp.).
Zastanawiałem się nad zrobieniem tego na dzierżawę (1 dzierżawca = 1 konfiguracja / pula połączenia z bazą danych), ponieważ byłby to „prosty” i skuteczny sposób na uzyskanie do- number-of-tenants
razy większej pojemności bez wprowadzania dużych zmian kodu aplikacji.
Teraz używam szyn 4.2 atm., Wkrótce aktualizuję do 5.2. Widzę, że szyny 6 dodają obsługę definicji połączeń dla poszczególnych modeli, ale to nie jest tak naprawdę potrzebne, ponieważ mam całkowicie dublowany schemat bazy danych dla każdego z moich 20 dzierżawców. Zazwyczaj przełączam „bazę danych” na żądanie (w oprogramowaniu pośrednim) lub na zadanie w tle (oprogramowanie pośrednie sidekiq), jednak jest to obecnie trywialne i obsługiwane jako klejnot mieszkania, ponieważ ustawia tylko search_path
Postgresql i tak naprawdę nie zmienia faktycznego połączenia. Podczas przełączania się na strategię hostingową dla każdego najemcy będę musiał zmienić całe połączenie na żądanie.
Pytania:
- Rozumiem, że mógłbym wykonać
ActiveRecord::Base.establish_connection(config)
zadanie na żądanie / w tle - jednak, jak rozumiem, to powoduje zupełnie nowy uścisk połączenia z bazą danych i nową pulę db odradza się w szynach - prawda? Sądzę, że byłoby to samobójstwem związanym z wydajnością, które spowodowałoby taki narzut przy każdym pojedynczym żądaniu mojej aplikacji. - Zastanawiam się więc, czy ktoś może zobaczyć opcję z szynami np. Wstępnego ustanawiania wielu (łącznie 20) połączeń / pul bazy danych od samego początku (np. Podczas uruchamiania aplikacji), a następnie po prostu przełączać się między tymi pulami na żądanie? Tak więc połączenia db są już wykonane i gotowe do użycia.
- Czy to wszystko jest kiepskim złym pomysłem i czy zamiast tego powinienem szukać innego podejścia? Np. 1 instancja aplikacji = jedno określone połączenie z jednym konkretnym najemcą. Albo coś innego.
źródło
master
gałęzi Rails . Czy uruchomienie Rails Egde byłoby opcją lub działaniem wstecznym dla tej wersji Rails?ActiveRecord::Base.connected_to(shard: :shard_one) do ... end
oznacza, że pula zostanie (ponownie) użyta, zamiast tworzyć nowe połączenie za każdym razem?Odpowiedzi:
Jak rozumiem, istnieją 4 wzorce aplikacji dla wielu najemców:
1. Model dedykowany / wiele środowisk produkcyjnych
Każda instancja lub instancja bazy danych całkowicie obsługuje inną aplikację dzierżawcy i nic nie jest współużytkowane przez dzierżawców.
Jest to aplikacja 1 instancja i 1 baza danych dla 1 najemcy. Rozwój byłby łatwy, jakbyś obsługiwał tylko 1 najemcę. Ale będzie koszmarem dla deweloperów, jeśli masz, powiedzmy, 100 lokatorów.
2. Fizyczna segregacja najemców
1 aplikacja instancji dla wszystkich najemców, ale 1 baza danych dla 1 najemcy. To jest to, czego szukasz. Możesz używać
ActiveRecord::Base.establish_connection(config)
lub używać klejnotów, lub aktualizować do Rails 6, jak sugerują inne. Zobacz odpowiedź na (2) poniżej.3. Model izolowanego schematu / Segregacje logiczne
W schemacie izolowanym tabele dzierżawy lub komponenty bazy danych są grupowane w ramach schematu logicznego lub przestrzeni nazw i oddzielone od innych schematów dzierżawy, jednak schemat jest hostowany w tej samej instancji bazy danych.
1 instancja aplikacji i 1 baza danych dla wszystkich najemców, tak jak w przypadku klejnotu do mieszkania.
4. Częściowo izolowany komponent
W tym modelu komponenty o wspólnych funkcjach są współużytkowane przez dzierżawców, a komponenty o unikalnych lub niepowiązanych funkcjach są izolowane. W warstwie danych wspólne dane, takie jak dane identyfikujące najemców, są grupowane lub przechowywane w pojedynczej tabeli, podczas gdy dane specyficzne dla najemcy są izolowane w warstwie tabeli lub instancji.
Jeśli chodzi o (1),
ActiveRecord::Base.establish_connection(config)
nie uzgadnianie z db na żądanie, jeśli używasz go poprawnie. Możesz sprawdzić tutaj i przeczytać cały komentarz tutaj .Jeśli chodzi o (2), jeśli nie chcesz używać
establish_connection
, możesz użyć klejnotu multiverse (działa dla szyn 4.2) lub innych klejnotów. Lub, jak sugerują inni, możesz zaktualizować do wersji Rails 6.Edycja: używa klejnotu Multiverse
establish_connection
. Dołączadatabase.yml
i utworzy klasę podstawową, tak aby każda podklasa dzieliła to samo połączenie / pulę. Zasadniczo zmniejsza to nasz wysiłek w użyciuestablish_connection
.Jeśli chodzi o (3), odpowiedź:
Jeśli nie masz tak wielu dzierżawców, a Twoja aplikacja jest dość złożona, sugeruję użycie wzorca modelu dedykowanego. Tak więc wybierasz 1 instancję aplikacji = jedno określone połączenie z jednym konkretnym najemcą. Nie musisz komplikować aplikacji, dodając wiele połączeń z bazą danych.
Ale jeśli masz wielu najemców, sugeruję, abyś stosował fizyczną segregację najemców lub częściowo izolowany komponent, w zależności od procesu biznesowego.
Tak czy inaczej, musisz zaktualizować / przepisać aplikację, aby była zgodna z nową architekturą.
źródło
establish_connection
w modelu takim jak ten:class SecondTenantUser < ActiveRecord::Base; establish_connection(DB_SECOND_TENANT); end
i powiesz, że masz 5 modeli, utworzysz 5 puli połączeń z DB_SECOND_TENANT. I każda pula jest traktowana jednakowo. Tak więc nie tworzysz puli na żądanie, ale naestablish_connection
.Z tego co rozumiem (2) powinno być możliwe ręczne przełączanie połączenia w Railsach 6.
źródło
Zaledwie kilka dni temu do Ruby on Rails na GitHub dodano poziomy sharding
master
. Obecnie ta funkcja nie jest oficjalnie wydana, ale w zależności od wersji Railsowej aplikacji możesz rozważyć użycie Railsówmaster
, dodając to doGemfile
:Dzięki tej nowej funkcji możesz skorzystać z puli połączeń z bazą danych Rails i przełączać bazę danych w zależności od warunków.
Nie korzystałem z tej nowej funkcji, ale wydaje się dość prosta:
Nie dodałeś zbyt wielu szczegółów na temat sposobu określania numeru najemcy ani sposobu przeprowadzania autoryzacji w aplikacji. Ale postaram się ustalić numer najemcy jak najszybciej
application_controller
waround_action
. Coś takiego może być punktem wyjścia:źródło
ActiveRecord::Base.connected_to ... do
bloku ponownie użyje domyślnego połączenia.master
oddziale Rails .