poniedziałek, 18 sierpnia 2008

Replikacja mysql

Replikacja pozwala na stworzenie "lustrzanego odbicia" bazy (baz) danych, w czsie rzeczywistym (albo prawie rzeczywistym). Zreplikowaną bazę danych (slave) możemy wykorzystać jako backup (który w każdym momencie możemy wykorzystać jako podstawową bazę danych). Konfiguracja serwera slave polega na wpisaniu do pliku konfiguracyjnego hostu na którym znajduje się baza mysql działająca jako master, loginu i hasła użytkownika który ma prawo do replikacji oraz (opcjonalnie) bazwę bazy danych którą chcemy replikować.

Po stronie serwera mysql działającego jako master, należy założyć konto dla użytkownika który będzie wykorzystywany jako slave.

CREATE USER slave_user;
GRANT REPLICATION SLAVE ON *.* TO 'slave_user'@'slave_host' IDENTIFIED BY 'slave_pass';
FLUSH PRIVILEGES;

W obu serwerach trzeba róznież ustawić server-id, który jest unikalnym identyfikatorem serwera w naszej sieci (najlepiej ustawić 1 dla master i kolejn0 (2,3...n) dla serwerów slave).

Pozostała konfiguracja polega na ustawieniu punktu od którego slave ma czytać zmiany w bazie danych master.

/* pobranie informacji o nazwie pliku logów oraz ostatniej pozycji w tym pliku - uruchamiamy na bazie master */

SHOW MASTER STATUS;

/* ustawiamy z którego pliku logów, oraz której pozycji ma czytać slave */
/* jeśli binlog jest pusty to trzeba podać slave-owi pusty string '' jako plik i pozycje */
CHANGE MASTER TO MASTER_HOST='master_host_name', MASTER_USER='slave_user', MASTER_PASSWORD='slave_pass', MASTER_LOG_FILE='recorded_log_file_name', MASTER_LOG_POS=recorded_log_position;

Ostatnią czynnością jest uruchomienie slave-a:

START SLAVE;

Można również startować selektywnie wątki replikacji:

START SLAVE SQL_THREAD;
START SLAVE IO_THREAD;

Jeśli nie jesteśmy pewni czy replikacja działa możemy sprawdzić jej stan na slave-ie za pomocą polecenia:

SHOW SLAVE STATUS\G

\G na końcu poda nam wynik w czytelniejszy sposób niż bez niego.

Aby zatrzymać działającego slave-a wystarczy wydać polecenie:

STOP SLAVE;

Czasami zachodzi potrzeba uruchomienia serwera mysq, skonfigurowanego jako slave z wyłączeniem opcji replikacji. Możemy to zrobić uruchamiając serwer mysql z opcją "--skip-slave"

mysqld --skip-slave

piątek, 15 sierpnia 2008

Walka ze sprzętem - sun xfire 2200 i karty ethernetowe nvidia



Nasze ostatnie problemy z serwerami (które wymusiły na nas wyjazd do serwerowni w Warszawskim ATM) były związane z usterką kart sieciowych opartych na chipisetach nvidi. Przy zwiększonym ruchu po interfejsie sieciowym wynikłym np. przez zwiększonym ruchu pomiędzy mysql-em a apachem interfejs przestawał odbierać i wysyłać dane, a po pewnym czasie nawet zawieszał system i powodował kernel panic. Obsługa techniczna atm twierdziła oczywiście że jesteśmy pierwszymi klientami którzy raportuja takie problemy z sun xfire 2200 i linuxem (może ze względu że chyba nikt nie miał połączonych ze sobą bezpośrednio 3 serwerów bez switch-a). Problem powtarzał się ze zmienionym kernelem i nowym modułem forcedeth.
W logach przy generowaniu dużego ruchu sieciowego (przez nc lub spc) pojawiał się wpis: "eth0: too many iterations (6) in nv_nic_irq."
Rozwiązaniem problemu okazało się załadowanie modułu forcedeth z opcją max_interrupt_work=25


localhost:/# modprobe forcedeth max_interrupt_work=25

w opisach znalezionych w internecie ta liczba była mniejsza, lecz metodą prób i błędów doszliśmy to 25. Nie wiem jednak czy rozwiązanie to wystarczy na długo i czy sytuacja nie powtórzy się. Najlepszym wyjściem będzie zainstalowanie switcha i użycie pozostałego interfejsu sieciowego opartego na chipisecie broadcom-u - co niebawem uczynimy.

Problemy z amfphp i drupalem


Amfphp w połączeniu z drupalem daje całkiem duże możliwości. Niestety moduł amfphp do drupala czasami sprawia spore kłopoty.
Najczęstszym powodem kłopotów z komunikacją flasha z amfphp jest źle ustawiony gateway (dla samego amfphp jest to www.example.com/amfphp/gateway.php , a dla zintegrowanego amfphp z drupalem www.example.com/services/amfphp), lub brak dodania uprawnień do korzystania z services. Niestety w moim przypadku wszystko było skonfigurowane poprawnie a flash nadal nie odbierał danych z serwisu. W analizatorze ruchu sieciowego wireshark pakiety z informacjami dochodziły do systemu a flash ich nie odbierał (lub odbierał a nie potrafił zinterpretować). Aby ułatwić sobie przeglądanie pakietów z wireshark wystarczy wstawić filtr ip.src == ip serwera || ip.dst == ip serwera.

Problemem było to że z jakiegoś powodu drupal do każdej strony dodawał znak nowej lińji, co powodowało że dodawał znak nowej lińji również do xml-a z odpowiedzią wywołania metody amfphp. Można to najlepiej przetestować w pythonie:

#! /usr/bin/env python
import xmlrpclib, math

server = xmlrpclib.Server("http://www.example.pl/xmlrpc.php")
print server.node.load(135730,[])

jeśli ten sktrypt zwróci
xml.parsers.expat.ExpatError: xml declaration not at start of external entity: line 2, column 0
to znaczy że mamy doczynienia z uszkodzoną odpowiedzią z serwera.

Oczywiście skrypt ten komunikuje sie z drupalem za pośrednictwej xmlrpc, co wymaga włączenie serwera xmlrpc, oraz serwisu node_service w modułach.

Rozwiązanie problemu znaku nowej lińji znalazełem na stronach http://drupal.org/node/18265 i http://drupal.org/node/18265.

wystarczy dodać do includes/bootstrap.inc

function drupal_page_header() {
$clean = ob_get_contents();
ob_end_clean();

Wszystko było by fajnie gdybym wiedział dlaczego drupal zachowuje się w ten sposób. Dziwne bo ta sama instalacja drupala w innej lokalizacji (na serwerze testowym) działa w najlepsze, a na serwerze produkcyjnym znalazłem w/w błąd.

Funkcja drupal_page_header() w pliku includes/bootstrap.inc służy do generowania nagłówków.

string ob_get_contents ( void )

Gets the contents of the output buffer without clearing it.

bool ob_end_clean ( void )

This function discards the contents of the topmost output buffer and turns off this output buffering. If you want to further process the buffer's contents you have to call ob_get_contents() before ob_end_clean() as the buffer contents are discarded when ob_end_clean() is called.

niedziela, 10 sierpnia 2008

ssh-agent - czyli bezpieczne logowanie prawie bez hasła

Każdy kto pracował na zdalnych maszynach wie że ciągłe wpisywanie długich i skomplikowanych haseł nie należy do przyjemności. Jak chociaż trochę ułatwić sobie życie nie denerwując Andrzeja?
Na stronie http://susewiki.org/index.php?title=Using_SSH-agent znalazłem opis który nie pomógł mi bardzo przy procedurze tworzenia i dodawania kluczy ale zwrócił uwagę na prawa dostępu do katalogu .ssh i authorized_keys, jeśli katalog nie jest 700 a plik 600 całość po prostu nie zadziała.
miranda$ ssh-keygen -t dsa
.
.
.
miranda$ scp ~/.ssh/id_dsa.pub marian@remote.domain.net

remote$ mkdir ~/.ssh
remote$ chmod 700 ~/.ssh
remote$ cat ~/id_dsa.pub >> ~/.ssh/authorized_keys
remote$ chmod 600 ~/.ssh/authorized_keys
remote$ rm ~/id_dsa.pub

miranda$ ssh-agent

teraz należy dodać zmienne środowiskowe

miranda$ ssh-add

Warszawa Smyczkowa 9, Grochowska ATM, czyli kolejny odcinek walki z serwerami

Trochę daleko ten hotel....




Wyświetl większą mapę

mysql-proxy


Bardzo przydatny program. Generalnie jest to proxy które stoi pomiędzy serwerem mysql (mysqld) a klientem (mysql, php, python). Służy m.in. do analizy kodu sql wysyłanego do serwera, jego zmianie, filtrowaniu (gdy np. napiszemy CREAT zamiast CREATE skrypt lua może wykryć taką sytuację i poprawić kod), oraz do pisania rozmaitych macr.

http://www.oreillynet.com/pub/a/databases/2007/07/12/getting-started-with-mysql-proxy.html

Dzięki niemu możliwy jest load balancing ruchu pomiędzy klientami a nodami clustra mysql lub serwerem master/slave.

Opcje które umożliwią nam uruchomienie load-balancing-u to:

--proxy-read-only-backend-addresses= address:port of the remote slave-server (default: not set)
--proxy-backend-addresses= address:port of the remote backend-servers (default: 127.0.0.1:3306)

Szkoda tylko że nie ma prostego sposobu na załadowanie kilku takich skryptów, bo wraz z uruchomieniem demona mysql-proxy należy podać ścieżkę do skryptu który chcemy załadować.

$ mysql-proxy --proxy-lua-script=first_example.lua -D

Napisałem "prostego" bo znalazłem skrypt lua który umożliwia ładowanie kolejnych skryptów przez klienta mysql ( http://datacharmer.blogspot.com/2007/11/multiple-scripts-in-mysql-proxy.html). Wymieniony skrypt znajduje się także w katalogu /usr/share/doc/packages/mysql-proxy/examples/ ( SUSE 10.3). Czy nie powinno być opcji w uruchomieniu mysql-proxy która pozwoli na załadowanie kilku skryptów przy starcie demona?


Bardzo przydatna według mnie jest opcja wywoływania zewnętrznych programów przy pomocy skryptów lua. Przykładowy sktypt z możliwością uruchomienia dowolnej aplikacji shell-owej znajduje sie na forge.mysql.com (http://forge.mysql.com/tools/tool.php?id=79). W połączeniu z event schedulerem (http://dev.mysql.com/doc/refman/5.1/en/events.html) daje to nowe możliwości, możliwości które prawdopodobnie będę miał okazje wykorzystać.