Skip Ribbon Commands
Skip to main content

Ondrej Sevecek's Blog

:

Engineering and troubleshooting by Directory Master!
Ondrej Sevecek's Blog > Posts > Co to znemaná MaxPageSize a zda je vůbec potřeba tuto hodnotu měnit
květen 15
Co to znemaná MaxPageSize a zda je vůbec potřeba tuto hodnotu měnit

Čas od času se vyskytují otázky ohledně omezení na výsledky vyhledávání v Active Directory. Nejběžnějším problémem je hodnota MaxPageSize., která má výchozí hodnotu 1000. Existuje k tomu množství různých "urban stories", obvykle zmatených nebo polopravdivých.

Obvyklý požadavek od programátorů nebo skripterů zní - zvýšit. Chtěl bych tu vysvětlit, co to ve skutečnosti znamená. Abyste rozuměli tomu, že tuhle hodnotu není obvykle (neříkám že nikdy) potřeba zvyšovat. Místo toho je lepší změnit styl programování.

Vyhledávání v LDAP Active Directory

Ve Windows existuje knihovna na přístup do LDAP. Knihovna se jmenuje ADSI (Active Directory Services Interface). Používají ji všechny Windows aplikace, konzole Active Directory <Cokoliv>, PowerShell, VBScript i .NET Framework. a jeho namespace System.DirectoryServices. Takže se budeme zabývat jejími nastaveními.

Ale tahle vlastnost je obecnou LDAP vlastností (nejen) Active Directory. Takže ve skutečnosti není důležité, jestli používáte Windows implementaci klienta ve formě ADSI, nebo cokoliv jiného.

Příklad vyhledávání v jazyce PowerShell (vyhledá to všechny uživatele v organizační jednotce OU=Company):

$srch = [ADSISearcher] '(&(objectClass=user)(!objectClass=computer))'
$srch.SearchRoot = 'LDAP://OU=Company,DC=gopas,DC=virtual'
$srch.SearchScope = 'Subtree'
$srch.FindAll()

Poznámka: předchozí vyhledávání používá používá ADSISearcher type accelerator pro třídu System.DirectoryServices.DirectorySearcher.

Stránkované (paged) a nestránkované (nonpaged) vyhledávání (search)

Co nás ale zajímá je, jak se takový vyhledávací požadavek komunikuje se serverem. V předchozím příkladu jsem použil výchozí, nestránkované hledání(nonpaged search). To znamená v principu, že zašlu na DC jeden paket s požadavkem - s těmi vyhledávacími parametry. A dostanete "jeden paket" s výsledky vyhledávání.

Píšu tady "jeden paket" zaměrně v úvozovkách. Samozřejmě jich asi dostanete více, protože těch výsledků bude více a nevejdou se do jednoho TCP paketu. Ale bude to jen jeden paket ve směru do DC a několik paketů ve směru z DC ke klientovi. To podstatné zde je, že to je tedy mnohdy jen na jeden round-trip (dobře, nejspíš více roud tripů, ale jde o velikost TCP window, round-trip-time RTT a různé další optimalizace TCP stacku).

Samozřejmě to taky žere více RAM na DC i na klientovi. Na DC se celý výsledek musí připravit do paměti, potom se celý musí naložit do TCP a odeslat. Na klientovi se to musí zase celé přijmout do paměti. A přitom to stejně zpracováváte po jednom, ne?

Z tohoto důvodu existuje limit zvaný MaxPageSize. Tedy maximální počet výsledků, které je DC ochotné odeslat v jednom balíčku. Čistě proto, abyste ho nepřetěžovali debilními dotazy na všechny objekty. Výchozí je 1000. Informaci dostanete například v článku How to view and set LDAP policy in Active Directory by using Ntdsutil.exe.

Jestliže výsledek vyhledávání obsahuje více objektů, než MaxPageSize, dostanete jich jen MaxPageSize. Takže žádný error, prostě jich jenom dostanete méně.

V tom článku se dá najít info i o tom, že existuje podobný limit i pro počet hodnot v multihodnotových atributech (multivalue attribute) - MaxValRange. Stejný princip. Jestliže je v něčem více jak 1000 (Windows 2000), nebo 1500 (Windows 2003), nebo 5000 (Windows 2008) hodnot, tak se prostě nepřenesou.

Jak vyřešit problém MaxPageSize?

Logický nápad je zvýšit hodnotu MaxPageSize. Problém je, že to vyžaduje modifikaci configuration oddílu (configuration partition) v AD. To by tak nevadilo. Představte si, že programujete skript, nebo aplikaci, pro obecné prostředí. Nemůžete přece chtít po adminech, aby to všude nastavovali. Nemůžete to ani nastavit sami, protože to je docela zásah. Proč byste to také zvyšovali, ohrozíte výkon DCček, jen kvůli vašemu skriptíku.

Stačí upravit program. Stačí použít stránkované hledání (paged search) - jediná změna je políčko PageSize:

$srch = [ADSISearcher] '(&(objectClass=user)(!objectClass=computer))'
$srch.SearchRoot = 'LDAP://OU=Company,DC=gopas,DC=virtual'
$srch.SearchScope = 'Subtree'
$srch.PageSize = 1
$srch.FindAll()

Co to znamená, ten paged search? Řeknete, že chcete výsledky dostávat od DC po kouskách. Klient zašle požadavek ("jeden" TCP paket) a dostane jen několik výsledků ("na jeden" TCP paket). Až chce další výsledky, pošle další požadavek a dostane zase jich jen několik. V mém případě mám PageSize = 1, což znamená, že dostávám výsledky po jednom.

API je uděláno tak, že programátora to vůbec nezajímá. V obou případech, ať používáte nonpaged search, nebo paged search, je vám to úplně jedno. Jediná změna v programu je ta hodnota PageSize.

A je to?

Proč to teda není výchozí? Proč se výsledky nepřenáší po jednom by default?

To je kvůli rychlosti. Bavili jsme se tu o round tripu. Tedy o tom, že musíte zaslat jeden paket a dostanete zpátky celý výsledek (nonpaged search). V případě paged search, posíláte vždycky požadavky po jednom, čekáte na výsledek a zase posíláte další požadavek a tak pořád dokola.

To může ale celkem dost trvat. Příklad?

Řekněme, že výsledkem vyhledávání je 60 000 objektů. Řekněme, že paket tam a zpět mezi klientem a DC cestuje 2 ms na LAN. (tzv. round trip time RTT je tedy 2 ms). Řekněme, že objem celého přenosu je 20 MB. A vaše síť má rychlost 1 Gbps. Zanedbáme čas zpracování na DC a dodatečné RTT, které jsou potřeba pro TCP acknowledgement podle velikosti TCP window.

  1. použijeme nonpaged search. Zašlu jeden požadavek a za 2 ms začnu dostávat odpověď velkou 20 MB. Přenos 20 MB dat trvá 160 ms. Celá odpověď je u mě za 162 ms.
  2. použijeme paged search při PageSize = 1. Musím poslat 60 000 požadavků a dostat tedy 60 000 odpovědí. Každé kolečko trvá 2 ms. Celkem, i při zanedbání času potřebného na přenos 20+ MB, to bude trvat alespoň 120 sekund. Bude to ještě více, protože přenášíte data, při režijích tedy samozřejmě více, než těch původních 20 MB.
  3. když zvětšíte velikost PageSize, ušetříte čas poměrně. Ale zase se musíte vejít do limitu pro dané ADčko a jeho aktuální hodnotu MaxPageSize.

Paged search je tedy pomalejší. Výrazně. Ovšem při menší paměťové náročnosti, zátěži procesoru DC i klienta a celkově hladším průběhu. Bez limitů.

Závěr

Jestliže programujete něco, co stahuje z ADčka 60 000 objektů, tak je vám jedno, jestli to bude trvat v řádu sekund, nebo minut. Obvykle.

Comments

Re: Co to znemaná MaxPageSize a zda je vůbec potřeba tuto hodnotu měnit

co se týče hodnoty MaxValRange, pokud máte více hodnot v jednom atributu, než je tento limit, potřebujete tzv. "range retieval". Googlujte něco jako:

$srch.PropertiesToLoad.Clear()
$srch.PropertiesToLoad.Add('telephoneNumber;Range=0-100")

viz. například:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa772308(v=vs.85).aspx

a

http://msdn.microsoft.com/en-us/library/windows/desktop/aa746518(v=vs.85).aspx
ondass on 15.5.2013 14:06

Super

Super popis, díky.
RaT on 15.5.2013 14:42

Add Comment

Title


Pole Title nemusíte vyplňovat, doplní se to samo na stejnou hodnotu jako je nadpis článku.

Author *


Pole Author nesmí být stejné jako pole Title! Mám to tu jako ochranu proti spamu. Roboti to nevyplní dobře :-)

Body *


Type number two as digit *


Semhle vyplňte číslici dvě. Předchozí antispemové pole nefunguje úplně dokonale, zdá se, že jsou i spamery, které pochopily, že je občas potřeba vyplnit autora :-)

Email


Emailová adresa, pokud na ni chcete ode mě dostat odpověď. Nikdo jiný než já vaši emailovou adresu neuvidí.

Attachments