Nalezení nejbližšího serveru

Školení, která pořádám

Většina MySQL serverů ve Facebooku je replikovaná do několika geograficky vzdálených lokací. Když se s nimi bavíte z webového serveru, tak obvykle chcete ten nejbližší. Pro jeho přesné nalezení by bylo potřeba mít detailní znalost o topologii sítě, pro hrubý odhad se ale stačí podívat na IP adresu. Servery ve stejném racku budou ve stejném rozsahu. Ve stejném datacentru bude stejný rozsah o něco větší. Takže stačí nalézt nejbližší IP adresu.

Pro to nemůžeme použít běžný matematický rozdíl, protože k 192.168.0.255 je blíž 192.168.0.1 než 192.168.1.1, i když po převodu na celé číslo funkcí ip2long je rozdíl větší. Potřebujeme najít nejvyšší rozdílný bit.

<?php
/** Nalezení bitově nejbližší IP adresy
* @param string
* @param array neprázdné pole IP adres předaných jako řetězce
* @return string
* @copyright Jakub Vrána, https://php.vrana.cz/
*/
function find_closest_ip($my_ip, $ips) {
    $my_ip = ip2long($my_ip);
    $distances = array();
    foreach ($ips as $ip) {
        $distances[$ip] = ceil(log(($my_ip ^ ip2long($ip)) + 1, 2));
    }
    return array_search(min($distances), $distances);
}
?>

Vlastní IP adresa se dá na webu zjistit z $_SERVER['SERVER_ADDR'], ve skriptu pomocí gethostbyname(php_uname('n')). A celé to možná závisí na tom, že je webový server za proxy serverem, takže jeho IP adresa je z vnitřní sítě, nikoliv z venkovní.

Na závěr uvedu, že tenhle jednoduchý výpočet používám jen u jedné malé aplikace a to ještě jen ve vývojovém režimu, protože to bylo snadnější než integrovat abstrakci, která vrací nejbližší server přesně.

Jakub Vrána, Řešení problému, 5.10.2012, diskuse: 5 (nové: 0)

Diskuse

Petr:

Tohle po nějaké aktualizaci používaly Windows Vista v případě že jim DNS vrátilo víc A záznamů. Přišli jsme na to ve chvíli kdy stroj s IP 192.160.něco.něco začal mít třicetinásobný traffic oproti ostatním.

Franta:

Jako teoretické cvičení fajn, ale v praxi mi to přijde dost nepoužitelné – v jedné serverovně můžou být IP adresy z různých podsítí, zatímco podle algoritmu blízká IP adresa bude úplně někde jinde. Ono dost záleží, jak čistou a učesanou strukturu IP adres člověk má k dispozici (u IPv6 by to celkem čisté být mohlo, u docházejících IPv4 to bude spíš špatné a časem čím dál horší).

Pro reálné nasazení bych to postavil buď a) na DNS (což je obecně lepší), kde si ohlídám, aby struktura doménových jmen odpovídala geografickému umístění, nebo b) na reálných měřeních – nasadit nějaký jednoduchý proxy server, který bude měřit dostupnost a dobu odezvy, rozkládat zátěž, dělat HA atd.

Jarda:

K adresám v článku: 127.cokoliv je vždycky localhost.

jj:

"K adresám v článku: 127.cokoliv je vždycky localhost"... ale no tak, je to phpkar ;)

ikona Jakub Vrána OpenID:

Díky za upozornění, ukázku jsem změnil.

Vložit komentář

Používejte diakritiku. Vstup se chápe jako čistý text, ale URL budou převedeny na odkazy a PHP kód uzavřený do <?php ?> bude zvýrazněn. Pokud máte dotaz, který nesouvisí s článkem, zkuste raději diskusi o PHP, zde se odpovědi pravděpodobně nedočkáte.

Jméno: URL:

avatar © 2005-2018 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.