středa 23. října 2013

Refresh DNS dat nodů WLS clusteru ve WLInitialContextFactory

Pro komunikaci mezi dvěma WLS clustery je často používáno JMS, přičemž pro identifikaci cílového clusteru je používána jeho cluster DNS adresa. Když s její pomocí získáme initial JNDI context, máme ve weblogic.jndi.WLInitialContextFactory seznam všech adres, které jsou namapované na dané DNS jméno cílového clusteru. Tento seznam je uložen v cache každé instance zdrojového clusteru. Pak obvykle rozdělujeme zátěž mezi jednotlivé cílové servery pomocí DNS load balancingu.
 Z těchto cached listů jsou pak round-robin algoritmem obsluhována všechna další čtení initial contextu. Pokud je některá z adres uložených v cached listu nedostupná, je z listu odstraněna. Address list je z DNS znovu opětovně načten jedině tehdy, když nebude dostupná žádná z adres v něm, tedy bude-li prázdný.

Tak to popisuje Oraclí dokumentace třeba zde:

"When clients obtain an initial JNDI context by supplying the cluster DNS name, weblogic.jndi.WLInitialContextFactory obtains the list of all addresses that are mapped to the DNS name. This list is cached by WebLogic Server instances, and new initial context requests are fulfilled using addresses in the cached list with a round-robin algorithm. If a server instance in the cached list is unavailable, it is removed from the list. The address list is refreshed from the DNS service only if the server instance is unable to reach any address in its cache."

To až donedávna nepředstavovalo žádný problém. Ale s příchodem cloudu/dynamických clusterů a dynamickým spouštěním instancí v clusteru jsou do něj často ad hoc přidávány a odebírány instance, a v souladu s těmito operacemi dochází ke změnám v DNS. Tyto nové adresy však zdrojový cluster nenačítá, neví o nich a používá nadále jen ty instance, které už v cílovém clusteru "znal". Když je tedy postupem času v cílovém clusteru většina serverů odstavena a časem znovu spuštěna, dochází ke koncetraci requestů na stále menší množství cílových serverů, až nakonec jdou všechny requesty jen na jediný server, tedy N/1. O ostatních cílových serverech, které byly mezitím spuštěny nebo restartovány, totiž zdrojový cluster neví, neboť o nich nemá žádné záznamy v cached listu .
Aktualizace/obnova DNS cache, která načte adresy "nových" serverů cílového clusteru, je provedena až po zastavení posledního cílového serveru, jehož adresa byla předtím v cache uložena.

Je tedy zapotřebí, abychom na zdrojovém clusteru mohli periodicky obnovovat data z DNS cache a předešli výše popsaným bottleneckům. V dokumentaci Weblogicu ale žádný takový parametr nenajdete, nicméně naštěstí existuje. Je to nedokumentovaná interní JNDI property, vytvořená před pár lety přesně k tomuto účelu.
Při vytváření initial contextu tedy přidáme tuto propertu, která se jmenuje weblogic.jndi.forceResolveDNSName, nastavenou na true.
Také je zapotřebí zakázat DNS caching na úrovni JVM.

Použití v kódu pak může vypadat třeba následovně:
Hashtable ht = new Hashtable();ht.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");ht.put(“weblogic.jndi.forceResolveDNSName”, "true");
Context ctx = new InitialContext(ht);