|
|
Chorobovýplody
-
Čas od času není špatné změnit rytmus a prostředí. V letošním roce jsem se odhodlal pro takovýto krok. Po témeř šesti letech jsem se rozhodl přestěhovat zpět do České Republiky. S tím také souvisí to, že od tohoto pátku přestávám být zaměstnancem velkého a moudrého Billa. Irsko je nádherná země která mi přirostla k srdci. Je to země, kde lze velmi snadno žít, pracovat a užívat si svobody. Země, kde proběhly obrovské změny ve společenských hodnotách bez jakýchkoliv větších konfliktů. Jaképak že to jsou změny? Irsko je tradičně země velmi konzervativních poměrů. Před dvaceti lety bylo nemyslitelné aby svobodná matka vychovávala své děti jen tak bez problémů(sousloví "svobodná matka" bylo nemyslitelné samo o sobě). Dnes více jak třetina dětí v Irsku vyrůstá v neúplné rodině. To je jen jeden příklad za všechny. Irsko je stále zemí s nejpřísnějším potratovým zákonem v Evropě a stále existuje mnoho mladých párů, kteří spolu začínají bydlet pod jednou střechou až po svatbě. A rozvod zde trvá pět let (nejdříve musí být splněny podmínky odloučení a pak je teprve možný legální rozvod). Takže stále je co pilovat :-). Po celou dobu zde jsem měl tu čest pracovat pro Microsoft. Tato firma se dá dnes přetřásat v jakémkoliv kontextu ale pro mně osobne zůstává práce pro tuto firmu nezapomenutelnou zkušeností. Jedná se o můj čtvrtý pracovní poměr (a také z přehledem nejdelší) a těžko bych hledal porovnání s tím, kde jsem pracoval před tím. Koncentrace velmi talentovaných lidí naprosto zapálených pro věc, tradiční Vánoční "Charity week", výlety do zahraničí a vůbec velmi přátelské pracovní prostředí. Něco z toho znít určitě jako cliché ale něco takového jsem viděl a zažil až zde v Microsoftu. Nu, čas uzrál. Office 12 je hotov a tak jsem se rozhodl k návratu do vlasti České. Tato skutečnost nijak nemění mou snahu o publikování článků na tomto portále či mou snahu přizpívat svými moudry a kidy do diskusních skupin. Spíše naopak. Odchodem z Microsoftu jsem získal větší svobodu podílet se na projektech mimo firmu Microsoft. A myslím si, že jsem na tuto novou zkušenost připraven a vcelku se těším. Snad mi to také pomůže i k tomu abych poznal tváře za některými emailovými adresami :-). To říkám proto, že s mnoha lidmi jsem si po emailu potykal (obecně s tím nemám žádný problém) i přesto, že jsem tyto lidi nikdy neviděl. Takže snad někdy u sklenky rezaveho moku!
|
-
Během posledních tří let jsem se v našem teamu
vypracoval na jednoho z hlavních náborčích. Za tu dobu jsem se účastnil okolo stovky příjímacích pohovorů. Feedback, který jsem dostal od úspěšných kandidátů
mi dodal odvahy napsat tento článek.
Prvně je třeba říci, že provést přijímací pohovor tak, aby byl co nejvíce objektivní
je nesmírně těžká věc. Na přijímací pohovor jsem se musel vždy připravit. Přípravu
na přijímací pohovor vidím dle svých zkušeností ve třech bodech:
- Seznámení se kandidátem. Především výpis klíčových
či zajímavých údajů z životopisu kandidáta. Za povšimnutí rozhodně stojí web aplikace, na kterých
kandidát v minulosti pracoval.
- Seznámení se s rolí, na kterou bude úspěšný kandidát přijat. V tomto případě je vhodné naplánovat schůzku s vedoucím, který bude kandidáta přijímat (pokud to zní zvláštně, tak čtěte dále). Důležité je
mít jasno ve vstupních očekáváních (s čím by měl kandidát přijít do firmy, s jakými
znalostmi, zkušenostmi, vzděláním apod.), s náplní práce úspěšného kandidáta a s
kariérním růstem, který je s danou pozicí spojen.
- Strategie otázek při pohovoru.
Příjímací pohovory ve firmě Microsoft
Pokud byste měli zájem pracovat ve firmě Microsoft, tak zde je šablona přijímacího
pohovoru, kterou budete muset projít. Vlastní příjímací pohovor se skládá ze tří,
popřípadě čtyř samostatných pohovorů. U každého pohovoru jsou za firmu Microsoft
dva přísedící.
Celého procesu se za firmu Microsoft účastní šest, popřípadě osm různých lidí. Tito
lidé jsou vybrání tak, aby pokryli různé role ve firmě.
První pohovor je zaměřen na technické znalosti (hard skills) a základní komunikační
vlastnosti kandidáta (soft skills). Právě těchto pohovorů jsem se účastnil. Pokud
je kandidát ze zahraničí, tak jsou technické pohovory dva, telefonický a další
poté, co je kandidát přizván k osobnímu pohovoru. Následuje
pohovor ze zástupci personálního oddělení. Tito lidé se především zaměřují na komunikační
schopnosti klienta. Výsledkem těchto dvou pohovorů je doporučení pro vedoucího,
který je odpovědný za danou otevřenou pozici. Pokud personální oddělení a účastníci
technického pohovoru doporučí daného kandidáta, je kandidát pozván k pohovoru,
kterého se účastní samotný vedoucí a jím
zvolený přísedící. Na základě tohoto pohovoru
je kandidát přijat či poslán na další doplňující pohovor, který obvykle provádí
osoba na úrovni řízení vedoucího. Každý takovýto pohovor trvá zhruba hodinu až hodinu a půl.
Ze strany firmy Microsoft se můžete spolehnout na naprostou korektnost vlastního
přijímacího řízení. Existují otázky, na které se vás nikdo nikdy nezeptá.
Otázky typu kolik je vám let, odkud jste, zda máte rodinu a podobně jsou naprostým
tabu. Na školení, které jsem kdysi absolvoval, nám dokonce říkali, že i tak nevinná
otázka jako "Jak dlouho jste sem jel?" může být vnímána jako diskriminační a žalovatelná.
Radši si s kadidátem při cestě ve výtahu povídám o fotbale nebo o nějakém novém
filmu,
zkrátka o něčem naprosto neutrálním.
Grif technického pohovoru
Jedna z nejtěžších věcí na příjímacím pohovoru je multitasking. Zde je seznam, který
musíte mít jako zkoušející souběžně na zřeteli:
- Dovídám se danou otázkou něco nového o kandidátovi? Každá otázka by měla nějakým způsobem vést k jednoznačnému závěru pro přijetí či nepřijetí kandidáta.
- Jaká bude další otázka? Jak budu v pohovoru pokračovat?
- Odpovídá kandidát na otázku? Odpovídá správně?
Na pohovor je obvykle vyhrazen daný čas a vše
probíhá poměrně rychle. To, že musíte při pohovoru poslouchat, co vám kandidát odpovídá,
a zároveň si musíte připravovat další smysluplnou otázku, je opravdu velmi
náročné.
Nejlepší obranou proti multitaskingu je pohovor ve formě dialogu. V tomto případě
se snažíte kandidáta "nastavit" tak, aby vás poučil. Otázka je pak postavena v tomto
tónu: "Zajímavé. To jsem nevěděl. Nesetkal jste se tím, jak by se to dalo vyřešit
pomocí více vláken?" Kandidát, pokud ví, získá sevěvědomí a odvahu se s vámi pustit
do debaty. Pak pokračujete: "A řešil jste někdy přístup více vláken
aplikace do databáze?"
Dostat se do atmosféry debaty je ale nesmírně těžké a zdaleka ne vždy se mi to povedlo.
Prvním problémem je, že kandidát musí spolupracovat :-). A tedy něco vědět. Druhým
problémem je to, že jako zkoušející jste přece jen vnímán jako boss, ten kdo má
vždycky pravdu a všechno ví a všechno zná. Postavení kandidáta a zkoušejícího při
pohovoru není rovné. Třetím problémem je cvik. Tím,
jak rostou vaše zkušenosti z
minulých pohovorů, se dle mých zkušeností mění způsob vedení
celého pohovoru. Představuji si to takto:

Na počátku cesty je důraz kladen na seznam otázek. Každý si tím musí projít. Mé první
pohovory byly především o tom, abych měl zásobu "správných" otázek. Otázky jsem
kladl v daném pořadí a jednoduše jsem si dělal fajfky na co mi kandidát odpověděl
a na co ne. To bylo mé stádium "Vyptávání" - jinak řečeno, otázky jsou nadevše,
otázky jsou Bůh. Postupně jsem došel k tomu, že některé otázky jsou těžší než jiné
a nemá smysl je klást tehdy, pokud kandidát neznal odpověď na nějakou jednodušší
otázku. Tento filtr "težší" a "lehčí" je zcela určitě subjektivní, ale s tím, jak
zkoušíte více a více kandidátů získáte přehled o tom, na co jsou schopni kandidáti
odpovědět. "Težší" a "lehčí" se tedy časem stává spíše "Méně pravděpodobné, že kandidát
bude znát odpovět" a "Vice pravděpodobné, že kandidát bude znát odpověť".
S rostoucími zkušenostmi se posouváte z fáze "Vyptávání" do fáze "Naslouchání".
Čím více jste schopni naslouchat, tím více je pohovor interaktivní. Otázky zde nehrají
až tak
klíčovou roli. Důležité je spíše schopnost poslouchat a přímo reagovat na to, co kadidát říká. Otázky
přestávají mít absolutní formu typu: "Co je to deadlock?".
Místo toho jsou otázky více
neurčité: "Proč si to myslíte? Co se stane v případě,
když budete mít vlákna dvě?"
Dalším problémem z pohledu zkoušejícího je "syndrom svalové horečky".
Pokud jste někdy chodili do posilovny tak víte, jaké to je, když si po pravidelném
cvičení dáte i sebemenší, několikadenní přestávku. Pak musíte počítat
s tím, že vás při prvním následném tréningu bude všechno bolet. S pohory je to dle mých zkušeností
podobné. V jednu dobu jsme měli otevřeno pět pozic a to v praxi znamenalo tak třicet
pohovorů. Dva denně, několik týdnů za sebou. Po určité době je to rutina. Pak ale
nastane hladové obdoví. Přeci jen, nové spolupracovníky nepřijímáte zase až tak často. Pak
příjde nová vlna. Během období půstu však odezní automatika, grif schopnosti naslouchání
se oslabí. Naštěstí to není tak, že byste úplně ztratítili vaše předchozí zkušenosti. Spíše je
to něco podobného, jako když přestanete na delší dobu řídit auto. Nezapomenete řídit,
ale na určitou dobu ztratíte jistotu, cit pro situaci.
Struktura pohovoru
Možná čekáte na to, jaké jsou mé oblíbené otázky a jaká je struktura mého pohovoru.
Díky pohovorům, kterých jsem se zůčastnil mám sice jisté seběvědomí, ale rozhodně
se necítím na to, abych o sobě tvrdil, že jsem v tomto borec. Naopak, výše uvedené
myšlenky měly být spíše o tom, že udělat dobrý pohovor, a to především znamená rozpoznat
talent, potenciál, je nesmírně těžké. Zde je tedy několik mých oblíbených témat.
Náš team je složen z několika pracovních skupin, které vyžadují různou kvalifikaci.
Na jedné škále se jedná o stážisty. Ti u nás obvykle pracují jeden rok. Firma Microsoft
je sponzorem programu, jehož snahou je umožnit studentům IT získat praxi v oboru.
Další skupinou jsou kolegové, kteří maji na starosti automatizaci testování produktu
Office. Od těchto lidí se očekává aspoň dvouletá praxe. Třetí skupinou jsou kolegové,
kteří buďto vyvíjí interní nástroje pro testování a lokalizaci, a nebo vyvíjí Office
Add-iny specifické pro daný trh. Od těchto lidí se očekává aspoň pět let praxe,
znalost C++ je v tomto případě častou podmínkou (tito lidé obvykle pracují s kódem
Office).
V mém repertoáru otázek jsou zásadně otázky koncepční. Otázky typu "Vyjmenujte mi
třídy, které můžete použít k nastavení formátu pro serializaci" či "Namalujte
mi UML diagram návrhového vzoru Strategy" považuji za nic neříkající
a nefér. A to hlavně proto, že tyto otázky nesimulují problémy, se kterými se vývojář
v praxi zabývá. Na obě otázky existuje snadná odpověď - první odpověď je MSDN\Reflector
a druhá odpověď je kniha GoF. Smysluplnější otázka by pak mohla být: "Kde můžu najít
seznam tříd, které mohou použít k nastavení formátu pro serializaci?" Sami
cítíte, že takto položená otázka nemá žádný smysl, protože nic neřekne o kvalitě
kandidáta. Z tohoto důvodu považuji "encyklopediční" otázky za nic neříkající.
Jaké otázky tedy považuji za smysluplné? Zde je příklad, jak by mohl vypadat můj
pohovor. "Můžete mi řict, jaký je rozdíl mezi statickou virtuální metodou?"
Pokud nemá kandidát problém s odpovědí, pokračuji. "Dobrá, a může být statická metoda
zároveň metodou virtuální?" Pokud nemá kandidát problém s odpovědí, pokračuji.
"Proč ne, můžete mi to vysvětlit?" Tím se dostanu až do bodu, kdy kadidát
ví, jak fungují virtuální metody. Pak mohu pokračovat dále, podle kontextu: "Jaká
virtuální funkce v hierarchii tříd se zavolá, pokud provedu volání této virtualní
funkce z destruktoru v jazyce C++?"
Jiný příklad. "Můžete mi říci, k čemu slouží v .NET idiom Dispose()?" Pokud
kandidát ví, tak pokračuji. "Co je to tedy garbage collector?" Pokud kandidát
ví, tak pokračuji: "A víte, jak funguje garbage collector v .NET?"
Pokud kandidát ví, pokračuji "Může být finalizator volán vícekrát?", "Ano,
v jakém případě?" Error handling je další oblast, ve které lze nalézt celou
řadu otázek, od jednodušších až po záludnější.
Další mé oblíbené otázky jsou otázky srovnávací: "Jaké rozdíly vidíte mezi programovacími
jazyky Java a C#?" (kontext: mnoho uchazečů uvádí znalost C# a Java), "Znáte
nové funkce jazyka C# (verze 2.0). O kterých jste slyšel?", "Jaké rozdíly vidíte
mezi šablonou v C++ a generic v CLR?", "V jaké situaci byste použil návrhový
vzor Strategy a v jaké situaci byste použil Decorator?", "HTTP je bezstavový protokol.
Řekněte mi všechny způsoby, které znáte, pro uchování stavu mezi klientem a serverem."
(kontext: uchazeč deklaruje zkušenost s ASP\ASP.NET).
Další skupinou otázek jsou otázky praktické. "Potřebujete krokovat kód v určité
iteraci cyklu. Jakým způsobem můžete zastavit program tak, aby došlo k "záseku"
přesně v požadované iteraci?", "Jakým způsobem byste ladil vyjímku Access Denied?"
Oblíbené otázky jsou otázky s otevřeným koncem, otázky, na které v podstatě
neexistuje jednoznačná odpověď. Nejlepší otázky tohoto typu jsou otázky kontroverzní.
Ano všichni je známe: "Je lepší uložit data do databáze jako binární BLOB nebo jako
referenci na zkutečná data?", "Co si myslite o použítí bloku catch {}. Použil byste
ho někdy?"
Nakonec je to kód. Uchazeč je postaven před určitý rozumně složitý problém.
Například setřídit pole, rozpoznat palidrom apod. Nebo je uchazeči předložena ukázka
existujícího kódu s cílem najít v kódu chybu. Například "Co
je špatně na tomto kódu?"
|
-
Předchozím článkem se mi konečně povedlo prolomit magickou hranici sta příspěvků na Vývojáři. Myslím si, že to stojí za takové malé ohlédnutí.
Podle statistiky, kterou mám k dispozici z tohoto blogovacího systému, je nejčtenějším článkem Jak jsem objevil Windows. Je zajímavé, a vcelku pikantní, že dodnes dostávám odezvu na tento článek. Nejčastější reakce je ještě zajímavější - čtenáři mě žádají o instalační diskety pro systém Windows 3.11. Pokud jste dočetli tento blog až sem, tak vězte, že jako zaměstnanec firmy Microsoft vám těžko mohu poskytnout nelegální kopie software firmy Microsoft. Sorry. Každopádně je zajímavé, že je o tento software stále zájem (pokud se nejedná o spam :-)). Proč zrovna Windows 3.11? Možná bych měl tuto informaci předat dále. Třeba by Microsoft mohl jednoho dne vydat jakýsi "Windows revival".
Druhým nejčtenějším článkem, velmi těsně za prvním (rozdíl je pouze 28 přístupů) je C++\CLI – Seznamte se z velikánem (1). To je pro mě trošku překvapením. Poté, co jsem napsal články o C++\CLI, které dle statistiky patří k nejčtenějším článkům, jsem dostal trošku za uši v tom smyslu, že "zde se programuje v C#". Zdá se, že programovací jazyk C++\CLI by si na tomto blogu zasloužil více pozornosti.
Jak na to - Zabezpečení MS Access databáze byl také velmi čteným článkem. Pravděpodobně díky tomu, že jsem svého času psal příspěvky do diskusní skupiny MS Access na Pandoře. V posledních několika měsících jsem se tam odmlčel, ale předpokládám, že se zase vrátím. A možná se zde objeví i nějaký ten článek o MS Access či Visual Basicu.
Dalším populárním článkem byl Proč píšeme o tom, co děláme nejmíň?. To je velmi zajímavé. Tento článek jsem "spíchnul" během méně než jedné hodiny. S některými texty jsem strávil řádově mnohem více času...
V dohledné době bych se zde rád věnoval znovu vzkříšení seriálu Bezpečnostní Toulky, který byl podle statistiky dost populární. Rád bych pokračoval v seriálu o ladění, zejména v kontextu WinDbg extenze SOS a ladění IIS problémů. Články o produktu BizTalk si mezi vámi zatím nezískaly takovou oblibu. Snad je příliš brzo (zatím jsem se pohyboval jen na povrchu tohoto produktu. Ale nerad bych to vzdal, tento produkt si dle mého názoru pozornost zaslouží.
Vcelku by mě zajímal váš názor na tento blog. Jeden z důvodů, proč jsem začal psát tyto články, byla snaha se naučit psát lépe česky. Na střední škole byl český jazyk mým nejméně oblíbeným předmětem. Diktáty jsem měl téměř vždy za čtyři. Svou maturitní slohovou práci jsem téměř nezvládl. Dodnes si pamatuji, jak mi to tehdy češtinářka oznámila před celou třídou: "Vysloveně mě z celé třídy zklamaly pouze dvě práce. Dlouho, opravdu dlouho, jsem přemýšlela, zda mám nechat oba studenty opakovat maturitu. Nakonec jsem jim dala za čtyři. Tito dva jsou XXX a Lazecký." Na svou obranu musím říci, že jsem tomu výsledku dodnes neporozuměl. Zvolil jsem si tenkrát velmi lehký (aspoň jsem si to myslel!) slohový útvar - v podstatě jsem převyprávěl Čapkův životopis a jeho tvorbu. Ale údajně "jsem plácal nepřesné, až nesmyslné věci". Nakonec jsem odmaturoval z češtiny za dvě. Pikantní je, že u ústní zkoušky, do které jsem šel s citelným handicapem, jsem si vytáhnul - no přesně tak, Čapka!
S bývalou paní profesorkou češtiny mám dodnes spojenu příhodu, která dle mého názoru vystihuje náš vztah. Dotyčná paní profesorka se o tomto triku nikdy nedověděla, ale několikrát jsem s ním zaujal. Tuším, že někdy ve třetím ročníku jsme probírali slohový útvar, který se jmenoval "umělecky zabarvený popis přírody". Možná se to jmenovalo trošku jinak, ale pamatuji si to pod tímto názvem. Určitě tušíte, oč šlo. Probíraný slohový útvar byl, jako obvykle, ukončen závěrečnou čtvrtletní písemnou prací. Mým oblíbeným autorem je Erich Maria Remarque. A co čert nechtěl, v jedné z jeho knížek (je to knížka "Cesta zpátky") je dokonalý popis podzimní přírody. Že by? No netrvalo to dlouho. Opsal jsem to doslova. Doufal jsem v jedna mínus, přeci jen, je to Remarque. Tím bych si zneutralizoval nějakou ty čtyřku z předchozího diktátu. Nu, nebudu vás napínat. Dostal jsem (tedy spíše Remarque) dvě mínus za "slohově nevyzrálou" práci s červeným mořem zpřeházeného slovosledu.
Co vy na můj písemný projev? Odmaturoval bych u vás z češtiny a nebo jsem jen ostuda?
|
-
Zajímali jste se někdy o to, jakým způsobem je organizován
GC heap v CLR? Zde je výsledek mého bádání. GC objekty jsou alokovány
z vyhrazeného souvislého bloku paměti. Čím jsou objekty starší, tím se
nacházejí na vyšších adresách tohoto souvislého bloku paměti. Speciální
ukazatel směřuje na místo, kde bude alokován další objekt. Čas od času dojde k
úklidu nepoužitých objektů. Tím se uvolní na heapu nový prostor ale zároveň se
vytvoří ostrůvky volného prostoru na heapu. Dále, čas od času dojde ke
"smrštění" těchto volných ostrůvků (defragmentation). Defragmentace se
neprovádí při každém úklidu haldy z výkonnostních důvodů. Objekty, zůstávají
uloženy na zásobníku v pořadí, v jakém byly alokovány, a to i po defragmentaci.
To zajišťuje dobrou lokalitu dat (v tom smyslu, že data, která spolu souvisí
mohou být nahrána do souvislých bloků procesorové cache).
GC halda je organizována do dvou základních částí. Halda pro
velké objekty (objekty větší než 85KB) a halda pro malé objekty. Dále je halda
organizována to tří generací podle stáří objektu. Všechny objekty začínají svůj
životní cyklus v generaci 0. Pokud objekt "přežije" úklidový cyklus (garbage
collection) na haldě dojde k přesunutí objektu do vyšší generace. Maximální
stáří, a tedy generace objektu je 2. Smyslem generací je frekvence úklidu
objektů na GC haldě. Generace 0 je čištěna častěji než generace 1 a ta je zase
čištěna častěji než generace 2. Halda pro velké objekty je čištěna
společně s úklidem generace 2.
ROTOR kód obsahuje pouze dvě generace. Na základě tohoto
kódu si lze udělat obrázek o struktuře haldy pro malé objekty (objekty menší
než 85KB):

GC halda je rozdělena do segmentů. Segment je souvislý blok
virtuálního adresového prostoru procesu. Velikost tohoto bloku je 16 MB (tato
velikost se ovšem liší pro jednotlivé edice CLR (workstation, workstation 64
bit, server, server 64 bit). Celý souvislý blok paměti pro každý nový
segment je prvně pouze rezervován (reserve). Současně je první 4KB stránka
z tohoto bloku paměti označena jako "commited".
Operační systém Windows rozlišuje mezi těmito dvěma
operacemi. Rezervovaná paměť (reserved) má pouze formu zápisu do patřičných
systémových tabulek daného procesu. Teprve v okamžiku, kdy je paměťový
blok označen jako "commited" memory je tato paměť spravována pomocí
mechanismu virtuální paměti (pokud znáte pojmy jako page directory entry, page
table entry či page direcoty tak máte představu, co mám na mysli).
Jeden ze segmentů je označen jako "prchavý" (emphemeral).
Tento "prchavý" segment hostuje všechny objekty z nulté generace. Tak je tomu v
kódu ROTOR. V případě "ostré" verze emphemeral segment hostuje jak objekty
nulté generace, tak objekty generace 1 jak je vidět na výše uvedeném schématu.
Segment je rozdělen na hlavičku a tělo. Tělo obsahuje
vlastní alokované objekty. Hlavička se skládá ze sady ukazatelů, které popisují
jednotlivé části těla segmentu. "reserved" ukazuje na poslední platnou adresu
segmentu. "reserved" je tedy sentinel, který je v kódu CLR použit pro detekci
toho, zda je daný segment zaplněn. "commited" je poslední
platná "commited"
adresa. Adresy za tímto ukazatelem jsou označeny jako "reserved" a nejsou
platné dokud je systém neoznačí jako "commited". "allocated" je za
ideálních podmínek poslední adresa obsahující platný objekt. Tato hodnota
souvisí s ukazatelem "plan_allocated". V případě, že živé objekty v daném
segmentu tvoří souvislý blok (no fragmentation) obsahují
ukazatelé "allocated" a "plan_allocated" stejnou hodnotu. Pokud při úklidu
segmentu vzniknou mezi živými objekty "díry" volného prostoru, tak
"plan_allocated" ukazuje na první volnou "díru". "next" ukazuje na další
segment, jak je naznačeno na obrázku.
gc_heap je datová struktura definována v souboru Gcsmpriv.h.
Tato struktura obsahuje velké množství ukazatelů, s
nichž nejzajímavější je
ukazatel na "finalizator" frontu, ukazatel na emphemeral segment a ukazatel na
dvě optimalizační tabulky zvané "brick table" a "card table".
Card a brick tabulky tvoří tělo datové struktury
card_table_info. Tyto tabulky definují mapu použití GC haldy. Každá
struktura card_table_info popisuje daný blok paměti jehož počátek je
dán hodnotou pole "lowest_address".
Card Table
Card table je pole DWORD prvků. Každý DWORD mapuje
použití 4KB bloku paměti. To znamená, že jeden bit odpovídá 128 byte
paměti. Kdykoliv dojde k změně reference na daný objekt, JITter emituje kód,
který nastaví patřičný bit v daném DWORD prvku. To je tak vše, co se dá říci k
této tabulce.
Brick Table
Card table mapuje použití paměti. "card table" umožňuje GC
rychle najít místa v paměti, která se změnila od poslední GC. To je sice fajn,
ale GC potřebuje mít nějaký mechanismus překladu mezi lineární adresou a daným
bitem v card table. K tomuto účelu slouží brick table. Brick table je opět
tvořena 16-bitovými hodnotami. Každá z těchto hodnot pokrývá 2KB z haldy. Pokud
je hodnota v dané brick položce větší než nula, pak tato hodnota
reprezentuje
offset .NET objektu v daném 2KB segmentu. Pokud je tato hodnota záporná, pak
tato hodnota udává počet brick položek, o které se je třeba vrátit zpět. Po
tomto přesunu bychom se měli nacházet na brick položce s kladnou hodnotu a tedy
s offsetem nového objektu. Tento mechanismus pokrývá situace, kdy daný .NET
objekt pokrývá paměťový prostor několika 2KB bloků. Graficky jsem se pokusil
znázornit tento mechanismus takto:

Červeně je vyznačen daný .NET objekt. Tento objekt je
rozprostřen přes několik brick prvků. Počátek daného card prvku odpovídá
jistému 4KB bloku paměti. Tento počátek také odpovídá počátku daného brick
prvku. Po nalezení brick prvku pro 2KB v něm najdeme hodnotu -2. To znamená
vrať se o dva brick bloky zpět. V tomto zpětném brick prvku najdeme kladnou
hodnotu, které obsahuje offset počátku .NET objektu.
Optimalizace CLR 2.0
Správa GC paměti prošla v CLR 2.0 třemi
zásadními změnami.
Obě změny mají za cíl snížit fragmentování paměti. První změnou je tzv.
"demotion". Tato situace pomůže tehdy, máme-li v nulté generaci nějaké
"pinned" objekty. Pak se může stát, že mezi těmito "pinned" objekty je dost
volného prostoru pro alokaci dalších objektů. V .NET 1.x "pinned" objekty
přežily GC cyklus a počátek bloku pro generaci 0 byl posunut za
poslední
"pinned" objekt. To mělo za následek nevyužitý prostor mezi "pinned"
objekty. Pokud byly toto objekty "pinned" dostatečně dlouhou dobu, byly
postupně přesunuty do ještě vyšší generace spolu s "dírou" uvnitř.
Situace byla horší o to více tehdy, pokud se spolu
s "promotion" "pinned" objektů do vyšších generací objevily další,
nové "pinned" objekty. Výsledkem byla fragmentovaná paměť.
"Demotion" se snaží tomuto procesu zabránit. Pokud je mezi
"pinned" objekty v nulté generaci dostatek místa, tak GC neprovede
přesun "pinned" objektů do vyšší generace, ale nechá je v původní nulté
generaci. A to i přesto, že tyto objekty přežily úklid. Prostor mezi "pinned"
objekty je pak použit pro alokaci nových objektů.
Druhým mechanismem snižující fragmentaci paměti je lepší
správa segmentů. V předchozích verzích CLR platilo, že pokud nebylo v aktuálním
ephemeral segmentu (segment, který hostuje objekty 1 a 0 generace) dostatek
místa, byl vytvořen nový ephemeral segment a původní ephemeral segment se stal
segmentem hostujícím 2 generaci objektu (první a druhá generace v
aktuální implementaci nikdy nepřesahuje jeden segment). CLR 2.0 se snaží
vylepšit správu segmentů tak, že pokud je nutné alokovat nový segment pro
generaci 1 a 0, GC se nejdříve pokusí najít existující segment hostující
generaci 2, který má dostatek místa (je téměř prázdný). Místo alokace nové
paměti se v takovémto případě provede záměna několika ukazatelů.
Posledním mechanismem správy paměti je funkce zvaná
recyklace segmentů (VM hoarding). Tato funkce udržuje "stand-by" list uvolněných
segmentů. Pokud GC potřebuje alokovat nový segment, zkontroluje nejdříve tento
"stand-by" list a pokud je v tomto seznamu nějaký dostupný segment, použije
jej. Tato funkce má ošetřit scénář, kdy se aplikace dostane do bodu, kdy
dochází k častému vytváření a zároveň uvolňování segmentů. Například pokud
aplikace nahrává a uvolňuje mnoho malých assembly.
|
-
Přibližně před dvěma měsíci jsem musel řešit
instalaci nové verze systému pro správu naší automatizace (automation harness).
Systém byl vyvinut teamem v Redmondu. Jelikož je tento systém určen pouze
pro interní potřebu, instalace je vždy spojena s téměř detektivním vyhledáváním
všech možných závislostí a zadrátovaných (hardcoded) předpokladů, které
prostředí naší pracovní skupiny neplatí.
Jednou z nových závislostí, kterou jsem nedávno objevil byla
MSMQ fronta, do které systém posílá velké množství zpráv. Jakmile počet zpráv v
této frontě přesáhl jistou mez, celý server, na kterém je systém nainstalován,
se neúměrně zpomalil. PerfMon mi pomohl najít úzke hrdlo - velké množství I\O
operací v procesu MqSvc.exe. V jedné z MSMQ front se nahromadilo několik
miliónů MSMQ zpráv.
Tyto zprávy nebyly z fronty vybírány proto, protože
komponenta, která tyto zprávy konzumuje, není v našem prostředí nainstalována
(není potřebná). Jelikož je produkt MS Office těsně před dokončením, tak si
nemohu, a hlavně nechci, dovolit provádět nějaké skopičiny v klíčové
infrastruktuře našeho vývojového prostředí. Instalace této dodatečné
komponenty, která pro nás nepřináší žádnou přidanou hodnotu, a spíše
představuje potencionální destabilizaci infrastruktury v klíčové částí
projektu, jsem zamítnul poměrně rychle.
Rozhodl jsem se tedy najít takové řešení
problému (odborně známé pod názvem "hack"), které by stálo minimální usílí na
implementaci. Myslím si, že jsem ho našel.
Zde je malá rekapitulace problému. Mám MSMQ frontu, do
které je posíláno velké množství MSMQ zpráv. To po čase vede k degradaci
výkonu celého serveru.
Řešení, které jsem zvolil, používá technologii
MSMQ Triggers v kombinaci s technologií scriptlets. Jediným kódem,
který jsem musel v tomto případě napsat, byl kód COM komponenty.
Ta byla posléze nastavena jako výkonná komponenta k
nastavené MSMQ spoušti (trigger). Posláním COM komponenty je
zahození MSMQ zprávy. MSMQ spoušť tedy vyzvedne zprávu z dané fronty a
předá ji COM komponentě, která v ji zprávu zahodí. Tím dojde k automatickému
vyprázdnění fronty kdykoliv se objeví nová zpráva ve této frontě.
Scriptlets - COM s příchutí VBScriptu
Nejrychlejší způsob, jak napsat COM objekt, je IMHO napsat
ho jako skript. Žádná kompilace, jednoduché ladění, pohoda. Zde je kód:
<?XML version="1.0"?>
<?component error="true" debug="true"?>
<component>
<registration description = "Manage MSMQ Queues used by harness"
progid = "MyApp.QueueManager"
version = "1.00"
classid = "{9386AE41-3A2B-4672-963A-61AD1EC32946}" >
<script language="VBScript">
Function register()
End Function
Function unregister()
End Function
</script>
</registration>
<comment>
This component is used to manage MSMQ queues used by automation harness.
</comment>
<public>
<method name="DropMessage" >
<parameter name="body" />
</method>
</public>
<script id="dd" language="VBScript">
<![CDATA[
' This method is empty on purpose. The main reason is to consume
' message from the queue and throw it away. This method is called
' from MSMQ trigger and for this reason no MSMQ code is required
' here.
Public Function DropMessage(body)
End Function
]]>
</script>
</component>
Tento kód jsem uložil jako soubor s koncovkou .sct. Jedná se
o plně funkční COM objekt implementující rozhraní IDispatch. Soubor s koncovkou
.sct jsem pak zaregistroval pomocí REGSVR32.EXE. Explorer dokonce rozpozná
soubor s koncovkou .sct jako platný COM objekt a ve svém kontextovém menu
nabízí možnosti Register\UnRegister. Jakmile je tento skript zaregistrován jako
COM objekt, lze ho použít v kterémoliv vývojovém prostředí jako jakýkoliv
jiný COM objekt. Dokonce lze v tomto skriptletu provádět změny, které jsou
okamžitě viditelné při dalším volání metody objektu. Změny lze provádět bez
jakékoliv kompilace, instalace či registrace. Samozřejmě pouze dokud nezměníte
rozhraní objektu. IMHO ideální pro prototypy COM objektů!
Konfigurace MSMQ spouští.
Zbytek už je jen snadná procházka růžovou zahradou v
přítomností několika průvodců. Administrativní konzoli pro MSMQ Triggers
zobrazíte pomocí Start -> My Computer -> Manage -> Services And
Applications -> Message Queuing -> Triggers.
Nejdříve je třeba vytvořit nové pravidlo (rule). Pravidlo
určuje kritéria, která musí zpráva splnit, aby bylo zpracována podle potřeby:
Další nastavení pravidla (rule) je to, jakou akci je
třeba vykonat poté, co je zpráva, která vyhovuje zadaným kritériím,
nalezena ve frontě:
Zde říkáme, že poté, co je vhodná zpráva nalezena, MSMQ
engine zavolá námi určenou metodu daného COM objektu. Po kliknutí na tlačítko
Parameters... lze definovat vstupní parametry pro danou metodu COM objektu.
Hodnoty pro tyto parametry pak MSMQ engine předá na vstupu do dané metody
objektu. Tím je konfigurace pravidla hotova.
Posledním krokem de konfigurace vlastní spouště:
Tento konfigurační dialog spojí (bind) pravidlo (rule) s
danou frontou. Tím je konfigurace hotova.
Třeba se vám to bude hodit.
|
-
Implementace obsluhy výjimek v běhovém prostředí BizTalk nabízí několik zajímavých možností, jak se vyrovnat s výskytem neočekávaných situací během vykonávání choreografie procesu. V choreografii procesu lze k prvku "Scope Shape" přiřadit blok ošetření vyjímek (exception handler) . "Scope Shape" si lze představit stejně jako blok v jazyce C# či C++, který je definován pomocí tokenů {}. "Scope Shape" má navíc několik dalších vlastností, které mají vliv na to, jakým způsobem je kód uvnitř bloku vykonáván. Pro účely tohoto článku je zajímavá vlastnost "Transaction Type", která definuje typ transakce daného bloku. Vlastnost "Transaction Type" může být nastavená na jednu z následujících hodnot: Typ transakce, který je přiřazen danému bloku, určuje způsob, jakým lze reagovat na výskyt vyjímek v tomto bloku. Choreografie procesu podporuje dva typy transakcí - atomické transakce a transakce s dlouhým trváním (long running transactions). Atomické transakce se především vyznačují krátkou dobou trvání transakce, protože během vykonávání transakce jsou uvalovány zámky na jednotlivé zdroje. Atomické transakce také splňují vlastnosti Atomicity, Consistency, Isolation, a Durability. Transakce s dlouhým trváním se liší nejen délkou trvání, ale především tím, že tyto transakce nepodporují všechny ACID vlastnosti tak, jako atomické transakce. Transakce s dlouhým trváním poskytují garance pro Consistency a Durability ale nikoliv garance pro Atomicity a Isolation. K danému bloku může být přiřazen buďto blok obsluhy vyjímek (exception block) a nebo kompenzační blok (compensation block). Zatímco blok obsluhy vyjímek pro daný blok je vykonán pouze v případě výskytu výjimky uvnitř přidruženého bloku, kompenzační blok je vykonán pouze v případě úspěšného dokončení všech operací v souvisejícím bloku. Blok obsluhy vyjímek funguje stejně jako catch {} blok v jazyce C#. Compensation block nemá v jazyce C# ekvivalent. Typ transakce daného bloku určuje, zda je možné k tomuto bloku přiřadit blok obsluhy vyjímek, kompenzační blok a nebo obojí: if ("Transaction Type" == "Long Running")
{
[Exception handler] je povolen
[Compensation block] je povolen
}
else if ("Transaction Type" == "Atomic)
{
[Compensation block] je povolen
}
else if ("Transaction Type" == "None")
{
[Exception handler] je povolen
}Cílem kompenzačního bloku je provést rollback transakce, která proběhla úspěšně, tehdy, pokud nadřazená (outer) transakce selhala. Představte si program, který vystřelí balistickou raketu. Samotné odpálení rakety je řízeno transakcí. Pokud tato transakce proběhla úspěšně, dojde k odpálení rakety. Nyní ale přijde rozkaz z generálního štábu, že raketa neměla být odpálena, protože ochranný systém byl napaden virem a omítl naběhnout. Transakci pro odpálení rakety nelze vrátit zpět (rollback); raketa je již ve vzduchu a letí k cíli. Jedinou možností je kompenzovat předchozí, úspěšně dokončenou transakci akcí, která provede zneplatnění předchozí transakce. V tomto případě je nutné raketu sestřelit. Podobný příklad je odeslání emailu. Jakmile je jednou email odeslán, nelze tuto akci vrátit zpět. Jednou z možností, jak kompenzovat odeslání emailu, je poslat nový email, který anuluje email předchozí. Důležitou podmínkou pro vykonání kompenzačního bloku je úspěšné dokončení bloku, ke kterému je kompenzační blok připojen. Další zajímavou vlastností kompenzačního bloku je skutečnost, že kód uvnitř kompenzačního bloku má k dispozici stav, který existoval v době ukončení přidruženého bloku. Mějme následující choreografii:
Uvnitř bloku "Atomic Shape" nastavíme hodnotu globální proměnné Value. Blok je úspěšně dokončen a choreografie pokračuje kódem, který přiřadí novou hodnotu do globální proměnné Value. Nyní dojde k výjimce. Implicitní chování BizTalk engine způsobí zavolání kompenzačního bloku. Blok "Recover" uvidí hodnotu proměnné Value tak, jak existovala v době ukončení přidruženého bloku, tj. Value = 1. Kompenzační bloky se volají v opačném pořadí než pořadí, ve kterém byly vykonány jednotlivé přidružené bloky. To platí i v případě cyklů. Pokud je blok s kompenzačním blokem opakovaně prováděn uvnitř cyklu a cyklus skončí výjimkou ve čtvrté iteraci, dojde k volání kompenzačního bloku uvnitř cyklu celkem třikrát, a to pokaždé s takovým stavem proměnných, jaký existoval v patřičné iteraci cyklu. Situace se maličko změní v případě, kdy má nadřazená transakce definován blok obsluhy vyjímek, jako v tomto případě: 
Tento kód se od předchozí verze liší pouze tím, že jsem přidal Catch blok k bloku "Outer Scope". Jak bude kód vykonán v tomto případě? Stejně jako prvně, "Atomic Scope" proběhne úspěšně a nastaví Value = 1. Pak proběhne přiřazení Value = 2. Následně dojde k výjimce. Tato výjimka způsobí předání řízení do bloku obsluhy vyjímek pro nadřazený blok "Outer Scope". Vykoná se kód uvnitř prvku "Global Handler" a program se ukončí. Kompenzační blok se v tomto případě nezavolá. Pokud si přejete provést kód kompenzačního bloku, tak musíte zavolat kompenzační blok explicitně uvnitř bloku Catch. BizTalk k tomuto účelu nabízí "Compensate Shape", kterému stačí nastavit jako vlastnost jméno vnořeného bloku, který má přiřazen kompenzační blok. Sémantika je v tomto případě trošku jiná, jelikož pořadí, ve kterém se budou volat kompenzační bloky definujete sami explicitně uvnitř bloku obsluhy vyjímek. Tento článek je pouze úvodem do problematiky vyjímek. More to come :-).
|
-
"Parallel Shape" má zajímavé chování. Na první pohled se tento prvek
choreografie jeví jako velmi přímočarý nástroj. Dvě či více větví tohoto prvku
se vykonávají současně, co má být? Problém je v tom, že tomu tak není. Mějme
následující orchestration:

Každý "Expression Shape" obsahuje tento kód:
System.Diagnostics.Trace.WriteLine("Action X.Y");
kde X.Y odpovídá popisce každého "Expression Shape". Výstup
této choreografie procesu lze vidět v DebugView:
[2888] Action A.1
[2888] Action A.2
[2888] Action A.3
[2888] Action B.1
[2888] Action B.2
[2888] Action B.3
[2888] Action C.1
[2888] Action C.2
[2888] Action C.3
[2888] Done
To nevypadá jako paralelní zpracovávání, viďte?
"Parallel Shape" neprovádí zpracovávání jednotlivých větví v samostatných
vláknech operačního systému (threads). Problém je totiž v tom, že sémantika
paralelního zpracovávání v nezávislých vláknech je velmi náročná na
implementaci jak pro engine, tak pro konečného uživatele.
Zde je několik problémů. Představme si na chvíli, že se
zpracovávání jednotlivých větví provádí naprosto paralelně v nezávislých
vláknech operačního systému. Jak se má BizTalk engine zachovat v případě
výskytu výjimky v jedné z větví? Má provést násilné ukončení ostatních větví?
Pokud ano, tak v jakém pořadí (aby nedošlo k deadlocku)? Má mít každá
větev možnost provést uvolnění zdrojů, jakýsi ekvivalent Dispose (to stále
neřeší problém pořadí volání jednotlivých Dispose aby se zabránilo vzniku
deadlocku)? Pokud engine nechá ostatní větve provádět svůj kód při vzniku
výjimky v jedné z větví, jak může engine zabránit deadlocku v případech, kdy
větev, ve které došlo k výjimce, vytváří produkt, na který čeká jiná větev?
Dalším problémem je tzv. násilná serializace. BizTalk engine
musí mít možnost provést násilnou serializaci v případech jako je například
restart operačního systému. Pokud by byly jednotlivé větve
zpracovávány
paralelně v nezávislých vláknech, musel by existovat nějaký mechanismus pro
definovaní pořadí, v jakém je třeba větve serializovat a deserializovat. Snadno
by se totiž mohlo stát, že by při deserializaci došlo k obnově stavu
jednotlivých větví v chybném pořadí a tak ke vzniku deadlocku.
Vývojáři firmy Microsoft došli k závěru, že paralelismus pomocí
nezávislých vláken operačního systému přináší více problémů než užitku a
rozhodli se pro jednodušší implementaci paralelismu.
Revize "Parallel Shape"
"Parallel Shape" funguje takto. BizTalk engine začne vykonávat danou větev.
Pokud při vykonávání této větve narazí na operaci, na jejíž výsledek je třeba
čekat, přepne engine vykonávání do další větve. Pokud každá
větev obsahuje
nějakou "wait" operaci, dojde k iluzornímu paralelnímu zpracovávání operací v
jednotlivých větvích.
Následující choreografie simuluje "wait" operaci pomocí
"Delay Shape":

Čekací stav vynikne pomocí dalších podporovaných operací, jako je
například volání web service nebo čekání na novou zprávu pomocí "Receive
Shape". Výstup z výše uvedené choreografie bude vypadat takto:
[2888] Action A.1
[2888] Action B.1
[2888] Action C.1
[2888] Action A.2
[2888] Action B.2
[2888] Action C.2
[2888] Action A.3
[2888] Action B.3
[2888] Action C.3
Mimochodem, ve WF (Workflow Foundation) to funguje stejně.
|
-
Úvod
Snahou tohoto seriálu je představit technologii Microsoft BizTalk i těm, kteří s tímto produktem neměli možnost přijít do styku. Tracing jsem tedy zvolil jako téma, kde bych mohl prezentovat deployment jednoduché choreografie procesu. V následujících dílech už budu předpokládat, že víte, jak se provádí instalace orchestration či portů běhovém prostředí BizTalk.
Konfigurace portů
Nejdříve je třeba vytvořit fyzické porty, na kterých bude BizTalk engine detekovat nové zprávy. Použijeme File adapter, protože ten je jednoduchý na nastavení a proto také ideální pro ladění. Konfiguraci vstupního adaptéru lze ve verzi BizTalk 2004 provést uvnitř samotného Visual Studia. Ve verzi BizTalk 2006 došlo k přesunutí této funkcionality do administratiovní konzole produktu BizTalk. Nastavení jednotlivých adapterů se ovšem mezi těmito verzemi neliší.
BizTalk 2006 představil koncept zvaný "aplikace". Pomocí aplikace lze seskupit všechny spolu související vstupní porty, výstupní porty a další BizTalk artefakty pod jednu logickou jednotku. Tím získáte výborný přehled o tom, co patří k sobě. BizTalk 2004 neměl tuto funkcionalitu. Podobného výsledku lze však dosáhnout jednoduchou jmenou konvencí. Všechny porty, které spolu souvisí pojmenujte tak, aby jméno začínalo názvem aplikace. Všechny porty pak budou seřazeny podle tohoto jména a snadno uvidíte, co k čemu patří. Zde je ukázka konfigurace na mém BizTalk 2004 systému:

V BizTalk 2004 zobrazíte BizTalk Explorer pomocí volby View -> BizTalk Explorer uvnitř Visual Studia . Pod položkou "Receive Ports" přidejte nový port. Typ portu bude v tomto případě "One-Way port" a jako jméno zadejte "Concepts". Ostatní volby jsou v tuto chvíli nepodstatné. Všimněte si, že právě v tomto bodě konfiguračního procesu máte možnost zadat mapu, která bude aplikována na příchozí zprávu detekovanou na tomto vstupním portě (mapa je pouze XSLT tranformace, jak jsem popsal v předchozím díle).
Poté je třeba nadefinovat adresy, které jsou daný "Receive port" relevantní. Jak můžete vysledovat, jeden "receive port" může přijímat zprávy z několika různých adres současně. Přidejte novou adresu pomocí "Add Receive Location ..." a nastavte port na požadovaný vstupní adresář:

Podobně nakonfigurujte "Send Port":

Hello world
Zde je implementace "Hello World!" v prostředí Microsoft Biztalk:

Tato choreografie procesu obsahuje na levé straně definici logického vstupního portu. Při definici logického vstupního portu máte možnost určit typ dokumentu, který na tomto portu očekáváte. Zároveň tímto definujete kritéria pro subscription. BizTalk pak bude vědět, kde má směrovat dokument daného typu. Důležité je to, že definice logického vstupního portu choreografie je zároveň definicí kritérií pro danou subscription (jako je typ dokumentu v tomto případě).
První element choreografie se nazývá "Receive Shape". Tento element má důležitou property Activate. Orchestration může obsahovat více jak jeden "Receive Shape" ale pouze jeden z nich může mít tuto vlastnost nastavenou na true. Activate způsobí, jak asi tušíte, vytvoření nové instance choreografie procesu. "Receive Shape" s vlastností Activate nastavenou na false se používá pro korelaci zpráv (correlation), kdy si přejete poslat nově přijatou zprávu do již existující instance procesu. V tomto případě je třeba vytvořit tzv. "correlation set" což není nic jiného než množina vlastností, které definují parametry pro subscription.
Následuje "Expression Shape", což je univerzální blok, do kterého lze zadat kód v jazyce BPEL. Na první pohled se může zdát, že kód, který můžete zadat do "Expression Shape" je C# kód, ale není tomu tak. "Expression Shape" ve výše uvedeném příkladu obsahuje tento kód: System.Diagnostics.Trace.WriteLine("Order Received");
Následuje "Send Shape", který odešle zprávu do "Send Portu", který je v tomto případě nadefinován na pravé straně schématu. Dříve jsem zmínil, že "Receive Port" je definicí kritérií pro subscription. Send Port je definicí kritérií pro publication. "Send Port" odešle zprávu do Message Boxu, kde se provede vlastní směrování zprávy do subscribers, kteří splňují subscription kritéria dané obsahem zprávy odeslané zprávy. Všimněte si, že zprávy se nikdy neposílají přímo z jedné komponenty BizTalku do druhé. Zpráva vždy putuje nejdříve do Message Boxu a teprve tam je zpráva směrována na patříčné místo určení.
Logické porty definované uvnitř orchestration slouží jako plášť, obal (shell) pro skutečný, fyzický port. Tento plášť je napojen na skutečný fyzický port pomocí operace "Bind". Binding obvykle provádíte až v okamžiku instalace choreografie procesu. Definice portu na úrovni choreografie procesu pouze rozšiřuje definici kritérií pro konečné subscription. Jakmile provedete "binding" dojde k napojení logického portu na skutečný fyzický port a k sjednocení subscription kritérií fyzického portu a logického portu pomocí logického operátoru OR.
V části "Konfigurace portů" výše v tomto článku jsme měli možnost vidět, jak lze nakonfigurovat fyzické porty. Zajímavý je případ "Send Portu". "Send Port" je subscriber z pohledu běhového prostředí BizTalk. Cílem konfigurace pro každý subscriber je definice kritérií, jejichž kladné vyhodnocení způsobí příjem zprávy do tohoto předplatitele. Všimněte si, že v případě konfigurace "Send Portu" máte na záložce "Filters & Maps" možnost definovat kritéria pro subscription (tato volba není k dipozici u "Receive Portu", protože "Receive Port" je publisher). Pokud nadefinujete kritéria pro daný "Send Port" a tento port poté připojíte k logickému portu, definovaném v dané choreografii procesu, dojde ke sloučení kritérií obou portů pomocí operátoru OR.
Deklarace zpráv
Na tomto obrázku je definici zprávy PurchaseOrderTypes10:

Receive Port" či "Send Port" mají typ, který je určen XSD schématem. Tento typ musí odpovídat typu zprávy, kterou se snažíte přes daný port přijmout či odeslat. Každou zprávu, kterou si přejete přijmout či odeslat musíte explicitně deklarovat a určit její typ. Typem zprávy může být XSD Schema, .NET objekt podporující XML serializaci či instance třídy XMLDocument reprezentující netypovou zprávu (libovolná binární data).
Instalace
Ve verzi Microsoft BizTalk 2004 lze instalaci choreografie procesu provést přímo z prostředí Visual Studio.NET. Z menu Build vyberte volbu Deploy. Pokud je vše v pořádku, zejména pokud má assembly jedinečné jméno (strong name), dojde k registraci zkompilované assembly do běhového prostředí BizTalk. Zároveň dojde k instalaci této assembly do GAC. Trošku nepříjemné je to, že "ne-BizTalk" assemblies, na kterých daná choreografie procesu závisí, je třeba nainstalovat do GAC ručně.
Jakmile je assembly zaregistrována v běhovém prostředí BizTalk, je třeba provést přilinkování (binding) jednotlivých logických portů ke skutečným, fyzickým portům. "Binding" provede provázání skutečného fyzického portu s logickým portem, který je použit uvnitř dané choreografie procesu. Tento "binding" se provádí při instalaci assembly poté, co jste tuto assembly zaregistrovali do běhového prostředí BizTalk. V našem případě volba "Bind..." nabídne možnost připojit se na dva fyzické porty, neboť používáme jeden vstupní a jeden výstupní port. Součástí "binding" procesu je také specifikace OS procesu, který bude hostovat danou choreografii procesu. Výsledkem kompilace BizTalk projektu je DLL soubor a proto musí BizTalk runtime vědět, který proces operačního systému bude tuto DLL hostovat. "Binding" je tedy proces, v jehož rámci připojíte všechny logické porty používané v daném orchestration s patřičnými fyzickými porty a zároveň určíte NT proces, který bude hostovat danou assembly.
Jsme skoro hotovi! Zbývá jen spuštění právě nainstalované choreografie procesu. Spuštění choreografie je provedeno ve dvou krocích, Enlist a Start, jak ukazuje následující obrázek:

Logické pořadí těchto kroků je operace Enlist následována operací Start. Volba Enlist způsobí, jak určitě tušíte, vytvoření nové subscription. Příchozí zpráva, pro kterou není vytvořena žádná subscription, je běhovým prostředím BizTalk zahozena. Jedinou detekcí této zprávy bude chybové hlášení v Event Logu. Pokud subscription pro danou zprávu existuje ale zároveň je subscription v neaktivním stavu, dojde k uložení přijaté zprávy do fronty v Message Boxu. V této frontě se budou zprávy hromadit tak dlouho, dokud nedojde k aktivaci subscription. Aktivace subscription vám dává možnost dočasně vypnout zpracování daných typů zpráv (například pokud je server pod velkou zátěží). Přijaté zprávy pro neaktivní subscription nebudou ztraceny. Všechny se uloží do fronty v Message Boxu. Pokud zrušíte registraci subscription pomocí volby Unenlist, budou všechny nově přijaté zprávy, které by byly za normálních podmínek přijaty danou subscription, ztraceny.
Nyní jsme konečně připraveni na nějakou akci. Spusťte program DebugView od SysInternals. Zkopírujte soubor Order 1.0.xml, který reprezentuje platnou instanci dokumentu z adresáře Concepts.Schemas\docs do adresáře loc\in. Po chvilce byste měli vidět následující trace v DebugView:

Pokud ne, tak jste někde udělali chybu při konfiguraci. V tom případě se mrkněte se do Event Logu, chybové hlášky jsou v BizTalku velmi popisné a měly by vám pomoci problém vyřešit.
Tracing
Tracing pomocí System.Diagnostics.Trace je jednoduchý ladící nástroj. System.Diagnostics.Trace plus DebugView používám osobně velmi často. System.Diagnostics.Trace navíc nabízí možnost připojení libovolného trace listeneru a triviální modifikací konfiguračního souboru BTSNTSvc.exe.config lze poslat trace log kamkoliv je třeba aniž by bylo nutné zasáhnout do kódu samotného orchestration. Je libo použít Logging & Instrumentation Application Block? Není problém, přeregistrujte listener a je to.
Microsoft BizTalk ovšem nabízí ještě jednu variantu - BAM (Business Activity Monitoring). BAM využívá "interception layer", který umožňuje real time sběr dat během vykonávání orchetration. Data jsou ukládány do SQL databáze. BAM má ovšem několik omezení (například BAM neumí uložit aktuální stav proměnných používaných v orchestration). V těchto případech je možné použít BAM API, což je vlastně jen jiná forma System.Diagnostics.Trace. Pokud ovšem použijete System.Diagnostics.Trace, můžete vytvořit svůj vlastní BAM listener, který přesměruje trace do BAM pomocí BAM API.
Návrhový vzor "žurnál zpráv"
Scénář: Během zpracovávání zpráv je třeba uchovat žurnál všech zpráv bez ohledu na kvalitu těchto zpráv.
Zdůvodnění: Během životního cyklu aplikace se celkem běžně stane to, že neplatná, špatná zpráva je poslána na vstupní port aplikace. Abychom byli schopni spolehlivě určit příčinu proč byla daná zpráva odmítnuta, je vhodné uchovat odmítnutou zprávu v odděleném žurnálu zpráv.
Řešení: Řešení tohoto problému je v prostředí Microsoft BizTalk možné bez jediné řádky kódu. Protože je produkt Microsoft BizTalk 2004\2006 postavený na modelu publisher\subscriber, problém je řešitelný pouhou konfigurací patřičných subscribers.
Nejdříve vytvoříme publication ("Receive Port"), která umožní příjmout a poté poslat (vypublikovat) do Message Boxu jakoukoliv zprávu:

PathThruReceive pipeline způsobí to, že tento "Receive Port" bude schopen přijmout jakoukoliv zprávu. Nově přijatá zpráva proletí vstupní frontou (receive pipeline) a bude uložena do Message Boxu.
Nyní vytvoříme dvě nové subscription ("Send Port") tak, aby všechny zprávy, které přišly na výše definovaný "Receive Port" byly přeposlány do těchto subscription. Kritéria budou nastavena takto:

V podstatě zde říkáme to, že si na tomto "Send Portu" přejeme odchytit každou zprávu, která byla původně přijata na "Receive Port" se jménem "Concepts Any Message". První ze dvou portů bude v tomto případě sloužit jako žurnál (Concepts/Reply). Tento port bude opět používat PathThruReceive pipeline, neboť tento port musí být schopen přijmout zprávu jakékoliv kvality. Druhý "Send Port" bude nakonfigurován tak, aby příchozí zprávy byly posílány na adresu, která je zároveň vstupním portem pro cílovou choreografii procesu. Tento "Send Port" bude používat XMLReceive pipeline pouze pokud choreografie procesu, která poslouchá na dané adrese, očekává zprávy ve formátu XML. Volba PathThruReceive pipeline či XMLReceive pipeline není v případě konfigurace druhého portu rozhodující. Rozhodující je, aby tento "Send Port" posílal zprávy na místo, kde je "uvidí" dané orchestration. Tímto místem může být nějaký adresář na disku, web service, MSMQ fronta apod.
|
-
Administravia
Microsoft BizTalk 2004\2006 je poměrně komplexní produkt.
Před tím, než začnete s návrhem a implementaci řešení v prostředí
BizTalk, se vyplatí promyslet strukturu jednotlivých
projektových částí celého řešení (solution). Klíčové otázky, které dle mých
zkušeností definují hranice mezi jednotlivými projektovými částmi jsou tyto:
-
Je nutné udržovat nezávislé verze pro danou část projektu
(komponentu)?
-
Kdo bude komponentu vyvíjet (různé teamy, jeden team,
externí firma apod.)?
-
Jak často bude nutné danou komponentu měnit?
-
Závisí daná část projektu na důležité externí komponentě
nad kterou nemáte plnou kontrolu?
Malý dodatek k použité terminologii. "Projektovou
částí" mám zde na mysli zejména .NET "assembly". Nesnažím se
používat české výrazy za každou cenu ale míchání velkého množství
anglických slov v českém textu nevypadá přiliž dobře. Nejsem odborníkem na
český jazyk čí překladatel. To jste ale z mých
příspěvků určitě poznali :-).
Jednou z mých osobních motivací pro psaní tohoto veřejného zápisníku
(blogu) je snaha o zlepšení svého písemného projevu. Přiznávám, že v
oboru, kde dominuje angličtina, je hledání vhodných českých výrazů opravdovým
oříškem.
Projektové řešení (Solution)
Ale zpět k podstatě věci. Při vývoji aplikací používajících
Microsoft BizTalk se mi osvědčila následující struktura projektu:
Šablonu tohoto projektového zadání (solution) spolu ze
základním kódem si můžete stáhnout
zde. V následujících článcích budu tento kód podle daných témat dále
doplňovat.
Instalační program produktu Microsoft BizTalk 2004\2006 rozšíří vývojové
prostředí Visual Studio .NET o nové typy projektu. Tyto specifické BizTalk
projekty se pak tváří jako jakýkoliv jiný .NET projekt. V rámci jedné
"solution" je proto možné míchat BizTalk projekty spolu s
"normálními" .NET projekty. Základní solution Concepts se skládá ze čtyř
projektů typu "C# Class library" a ze dvou BizTalk projektů.
Kořenovým projektem je C# assembly Concepts.Config. Pro
konfigurační proměnné mých projektů používám poměrně zhusta .config soubory.
Concepts.Config assembly hostuje veškeré konfigurační ovladače (config
handlers) a .NET třídy, které provádí
deserializaci specifických konfiguračních sekcí do daného
.NET typu. Typická implementace takového ovladače pro konfigurační sekci
pak vypadá takto:
public class SettingsHandler : IConfigurationSectionHandler
{
private XmlSerializer ser_ = new XmlSerializer(typeof(GlobalSettings));
public object Create (object parent, object configContext, XmlNode section)
{
GlobalSettings settings = (GlobalSettings)
ser_.Deserialize (new XmlNodeReader(section));
return settings;
}
}
Třída GlobalSettings je "oznámkována" pomocí XML atributů definujících XML serializaci.
Poté, co je provedena deserializace určité
konfigurační sekce v .config souboru, lze k jednotlivým konfiguračním
parametrům přistupovat přes pevně daný .NET typ.
Kód, který má na starost správu konfiguračních parametrů
jsem zde umístil do samostatné assembly Concepts.Config. To proto, že tento kód
je velmi statický ve srovnání s jinými částmi projektu. Běhové prostředí
BizTalk požaduje umístění všech podpůrných
(dependent) assembly do GAC. To také znamená, že
všechny podpůrné assembly musí mít jedinečné jméno (strong name). Pokud
používáte své vlastní konfigurační sekce v daném .config souboru, pak
nejdříve musíte v daném .config souboru určit typ, který je odpovědný pro
interpretaci dané konfigurační sekce:
<configSections>
<section name="global"
type="Concepts.Config.GlobalHandler,Concepts.Config,
Version=1.2.3.0,
Culture=neutral,
PublicKeyToken=07ccf21d1aa5a6dc" />
</configSections>
A zde vězí problém. Pokud je GlobalHandler
součástí assembly, která se mění často, nesmíte zapomenout při instalaci nové
verze této assembly aktualizovat veškeré .config soubory, které odkazují na
GlobalHandler. Bavíme se zde o integraci a tudíž o řešeních, které je často
složeno z komponent, které jsou nainstalovány na několika různých
serverech. Opomenout tyto detaily je velmi snadná záležitost a není nic
zábavnějšího než ladění problému způsobených chybnou instalací a konfigurací.
Odbočka - Správa verzí (versioning)
Microsoft BizTalk 2004\2006 je postaven na infrastruktuře
.NET a tedy podporuje souběžnou instalaci komponent různých verzí dané
assembly. Je například možné provést deployment různých verzí téže choreografie
procesu (orchestration) a v případě potřeby provést "rollback" nové verze na
verzi předchozí. Představte si situaci, kdy máte několik aktivních instancí
dané choreografie procesu a chcete provést deployment nové verze aniž byste tím
ovlivnili existující instance. V běhovém prostředí BizTalk to lze provést velmi
snadno. Nejdříve provedete instalaci nové verze choreografie procesu do
běhového prostředí BizTalk. Samotná instalace nové verze choreografie
procesu nemá žádný vedlejší efekt na existující instance této
choreografie. Pak provedete přesměrování (binding) na novou verzi choreografie
procesu. Existující instance dokončí svůj běh oproti původním verzím .NET
komponent a nové instance dané choreografie budou spuštěny oproti novým
verzím komponent. Staré instance vám postupně "vyhnijí" a uvolní místo novým.
Abyste dosáhli této nirvány, je třeba důsledně provádět
správu verzí jednotlivých komponent. Každá assembly, kterou nainstalujete na
server musí mít novou jedinečnou verzi. Vím, že je to známá věc. Píši o
tom proto, že také vím, že správa verzi je často tou poslední věcí, na kterou
je kladen extra důraz. Přepisování komponent téže verze v GAC je poměrně běžný
jev. Pokud nezačnete BizTalk projekt s jasnou představou o správě verzí
jednotlivých komponent, tak dříve nebo později narazíte na opravdové problémy.
V podstatě nebudete schopni provádět údržbu vaší aplikace bez "downtime".
Správě verzí v prostředí BizTalk bych chtěl věnovat
samostatný článek. Konkrétně, správa verzí schémat je téma, které stojí za
samostatnou úvahu. V přiloženém projektu najdete příklad, jak lze provést
správa verzí schématu v běhovém prostředí BizTalk. Je to příprava na budoucí
článek.
Rozdělení Assemblies
Jak jsem zmínil výše, Concepts.Config je kořenovým projektem
hostující kód pro správu konfiguračních parametrů. Nad touto assembly je
postavená assembly Concepts.Base. Concepts.Base závisí na Concepts.Config.
Concepts.Base obsahuje sdílené typy pro celé solution, jako například definice
globálních rozhraní (interfaces), hierarchii tříd vyjímek, definici atributů
apod. Tato assembly obsahuje především bázové typy, které se nemění často a
mají globální rozsah (scope).
V tomto místě je možná více viditelný důvod pro oddělení
Concepts.Config od Concepts.Base. Pokud by konfigurační ovladače (handlers)
byly součástí Concepts.Base, tak by při přidání nové výjimky,
například, došlo ke změně verze Concepts.Base. To by také znamenalo
aktualizaci všech konfiguračních souborů a to rozhodně není intuitivní pro
programátora, který chce pouze provést check-in nového typu
výjimky.
Concepts.Task obsahuje definice typů Tasks, což jsou typy,
které implementují rozhraní ITask:
public interface ITask
{
object Execute();
IAsyncResult BeginInvoke();
object EndInvoke(IAsyncResult asyncResult);
bool CompletedSynchronously
{
get;
}
}
Tyto třídy
implementují jednotlivé atomické operace, které se
pak volají z choreografie procesu (orchestration). Tasks se jsou svým významem
podobné Activity třídám z WWF. Přiložené solution zatím obsahuje jedinou třídu
- třídu TaskToInjectException, která slouží k vyvolání
výjimky pro testovací
účely. Tato třída také existuje z důvodu mé přípravy na další články o
zpracovávání vyjímek. Concepts.Task závisí na Context.Base a Context.Config.
Nyní zbývají dvě BizTalk assembly. Concepts.Schemas obsahuje
pouze definice XSD schémat pro jednotlivé zprávy daného projektového řešení
(solution). To je osvědčený postup, a to právě z důvodů
správe verzí schémat.
Concept.Orchestration je projekt, který obsahuje kód pro
choreografie procesů a mapy. Tento projekt závisí na projektech
Conceps.Config, Concepts.Base, Concepts.Tasks a Concepts.Schemas. Všechny typy,
které jsou definované v rámci projektového řešení (solution) jsou
viditelné uvnitř Concept.Orchestration a integrace
jednotlivých typů může začít.
BizTalk projekt bohužel nemá možnost nastavit post-build
operace. Proto používám v solution pomocné projekty s koncovkou .PostBuild.
Tyto projekty existují pouze pro aktivaci post build operací a jsou tedy
pomocnými projekty v daném solution.
Adresářová struktura
Na závěr pár malých poznámek k adresářové struktuře
projektu. Po rozbalení zip souboru se vám na disku vytvoří adresářová struktura
celého projektu. Adresář \bin slouží jako repositář pro veškeré binární
soubory. A to jak pro binární soubory, které jsou sestaveny v
rámci
projektu, tak pro binární soubory externích komponent (typové knihovny COM
komponent, interop DLL soubory apod.). Podadresáře v adresáři \loc slouží jako
zdrojové\cílové adresy pro File Adapter. \loc\in je vstupní adresa, \loc\out je
výstupní adresa a \loc\replay slouží jako žurnál minulých zpráv. File
Adapter je velmi jednoduchý adapter co se týče nastavení a je proto ideální pro
testování. Zde je ukázka nastavení "Receive Port" v nástroji BizTalk Explorer
(View -> BizTalk Explorer na systému, kde máte nainstalován Microsoft
BizTalk 2004 a VS.NET. V produktu Microsoft BizTalk 2006 se
konfigurace "Receive Port" provádí pomocí BizTalk Server 2006
Administration Console):
Pole "Address" obsahuje místo na disku, kde je adapter
připraven zpracovat nové zprávy. "Receive Handler" je Windows NT proces, který
je zodpovědný za hostování adapteru. Adapter je implementován jako DLL knihovna
a jako každá DLL knihovna i tato musí běžet uvnitř nějakého NT
procesu. "Receive Pipeline" je typ vstupní fronty, přes kterou proteče nově
přijatá zpráva. Zde je použitá "XMLReceive" vstupní fronta, což znamená,
že zpráva musí odpovídat zaregistrovanému XML schématu a že také dojde k
automatickému "property promotion" z těla přijatého XML dokumentu podle
definice "Property Schématu".
V podadresáři Concepts.Schemas naleznete instance
XML dokumentů pro schémata definovaná v assembly Concepts.Schemas.
|
-
Administravia
Co je to
KPZ?
| Zdroj: |
SysInternals |
| Popis: |
Jednoduchý nástroj ke sledování diagnostických
zpráv (trace) během vykonávání programu. |
|
 |
Komentář
DebugView je jednoduchý ale neocenitelný pomocník pro ladění
programů. Program detekuje veškeré diagnostické zprávy a zobrazí je v
jednoduchém výpisu, jak lze vidět na obrázku výše. Diagnostika, která je
výsledkem volání metod tříd System.Diagnostics.Trace, System.Diagnostics.Debug
či API funkce OutputDebugString() je zachycena programem DebugView a
zobrazena ve výpisu. DebugView podporuje přípojení k externímu počítači
(remote connection), zvýrazňování diagnostických zpráv podle kritérií či výpis
diagnostických zpráv z
paměťového výpisu (dump).
Skvělý nástroj pro ladění Windows NT služeb, COM+
objektů, BizTalk artefaktů (orchestrations, pipeline
components apod.) či obsluhy okenních zpráv Win32 API. Ladění
obsluhy okenních zpráv, jako je například obsluha zprávy WM_PAINT, je
prakticky nemožné provést na stejném počítači, kde běží laděný program, neboť
každý breakpoint v obsluze okenní zprávy způsobí přepnutí do ladícího programu
(debuggeru) a tím nové vyvolání obsluhy. Okenní zprávy pro překreslování
uživatelského rozhraní je nutné ladit buďto s pomocí "remote debugging" ze
vzdáleného počítače a nebo ladící technikou šedesátých let -
pomocí diagnostických zpráv.
|
-
Říkáte, že máte aplikaci, která záhadným způsobem spadne a nikdo neví proč, protože nemáte dostatek informací k ladění tohoto zvláštního problému? Právě v těchto situacích vím může pomoci ladění programu pomocí paměťového výpisu (memory dump).
Trivia - Co je to paměťový výpis (memory dump)?
Paměťový výpis (memory dump) je snímek paměti (memory snapshot), který je vytvořen v daném okamžiku. Ladící nástroje firmy Microsoft umožňují generovat několik různých paměťových snímků. Více typů paměťových snímků existuje kvůli snaze najít rozumný kompromis mezi velikosti generovaného paměťového výpisu a množství ladicích meta informací uvnitř tohoto paměťového výpisu. Z pohledu ladění pochopitelně žádoucí mít co nejvíce ladících informací k dispozici. Bohužel není vždy praktické generovat 500MB soubor obsahující paměťový výpis. Zákazník se asi bude tvářit velmi nevrle pokud ho požádáte o poslání souboru této velikosti přes vytáčenou linku.
Právě z těchto důvodů balík ladících nástrojů obsahuje několik možností vytvoření paměťového výpisu. Jak jsem popsal v jednom z předchozích dílů tohoto seriálu, ladící programy WinDbg, CDB a NTSD sdílí jednotný ladící aparát (engine). Z tohoto důvodu jak WinDbg, tak CDB či NTSD umí vytvořit stejné typy paměťových výpisů.
Typy paměťových výpisů jsou velmi dobře z popsány v dokumentaci, která je součástí ladících nástrojů firmy Microsoft. Místo opisování dokumentace bych zde uvedl jen některá klíčová fakta. Paměťové výpisy lze rozdělit do dvou základních skupin - "kernel dump" a "user mode dump". "Kernel dump" je, jak asi tušíte paměťový snímek celého operačního systému. V tomto výpisu naleznete strukturu paměti pro všechny procesy, které běžely v době vytvoření paměťového výpisu. "User mode dump" je paměťový výpis obsahující data pouze pro specifický proces. "User Mode" v názvu tohoto paměťového výpisu také znamená to, že interní struktury, které jsou součástí jádra operačního systému, nejsou v tomto typu paměťového výpisu dostupné k ladění.
Zaměřme se nyní na "user mode dump". Pomocí ladících programů WinDbg, CDB a NTSD je možné vytvořit dva typy "user mode dumps" - minidump nebo "full dump". Z názvu by mohlo vyplynout, že "full dump" je ten kompletní výpis, který je možné získat. Bohužel je tento název matoucí a to z historických důvodů. "Minidumps" byly vyvinuty mnohem později (tuším, že se poprvé tento koncept objevil až s příchodem Windows 2000). Do té doby existovaly pouze "full dumps". je možné vytvořit "minidump", který je nejen mnohem větší než "full dump", ale také zároveň obsahuje více informací pro ladění. Microsoft měl pravděpodobně problém s pojmenováním nového typu paměťového výpisu. Spíše než "mini" či "full" se v případě minidumpu jedná o nový formát. Slovo "formát" ovšem také není přesné, neboť mezi těmito výpisy není strukturální rozdíl (podle významu slova "formát"). Spíše než struktura se změnil způsob a počet variant jaké minidump podporuje.
Pokusme se tedy přijmout dogma, že "full dump" je pouze jedním typem minidumpu. Paměťový výpis (memory dump) je možné ve WinDbg, CDB a NTSD vygenerovat pomocí příkazu .dump. Tento příkaz vytvoří full dump: .dump /f
"Full dump" si můžete představit jako snímek všech "commit memory pages" daného procesu. Jak jsem zmínil výše, "full dump" není maximální možný paměťový výpis. Maximální paměťový výpis vytvoříte pomocí tohoto příkazu: .dump /ma
Takto vytvořený paměťový výpis bude nejen největší, ale také obsahuje mnohem více informací pro ladění než "full dump". S těmito dodatečnými ladícími informacemi je pak ladící program schopen přesné "post mortem" rekonstrukce paměti daného procesu. Důležité je ovšem to, že v případě ladění managed procesu je vždy žádoucí vytvořit tento maximální paměťový výpis (tedy pomocí příkazu .dump /ma).
Generování paměťového výpisu
Paměťový výpis lze generovat snadno tak, že spustíte ladící program WinDbg, CDB či NTSD, připojíte se k cílovému procesu a pomocí příkazu .dump vygenerujete paměťový výpis: .dump /ma /u C:\Dumps\MyProcess.dmp
Volba /u způsobí přidání časové značky (timestamp) na konec jména souboru. Výsledný soubor pak bude například vypadat takto: MyProcess_0270_2006-08-30_00-07-40-562_0164.dmp
Způsob vytvoření paměťového výpisu pomocí tím, že spustíte ladící program a připojíte se k souboru samozřejmě nebude fungovat, pokud vám program padá náhodně. V tomto scénáři by bylo spíše výhodnější vytvořit paměťový automaticky v okamžiku výskytu neošetřené výjimky. Toho lze dosáhnout pomocí nástroje ADPlus.
ADPlus
ADPlus je součástí balíku ladících nástrojů. ADPlus se nainstaluje společně s WinDbg, CDB a NTSD. Opravdu, ADPlus je ve skutečnosti pouze VBScript, který automatizuje a zapouzdřuje volání ladícího programu CDB. Tento příkaz: adplus -crash -o c:\temp -sc C:\Crash\bin\Debug\Crash.exe
způsobí to, že dojde ke spuštění ladícího programu CDB. CDB pak spustí program Crash.exe a připojí se k němu. Takto vlastně spustíte program Crash.exe uvnitř ladícího programu CDB. Volba "-crash" znamená to, že v případě výskytu neošetřené výjimky dojde k vygenerování paměťového výpisu. volba "-o" vám pak umožňuje zadat adresář, do kterého bude paměťový výpis uložen. ADPlus se umí také připojit k již existujícímu procesu. To lze udělat jednoduchou záměnou parametrů. Takto se připojíte k existujícímu procesu pomocí jeho jména: adplus -crash -o c:\temp -pn Crash.exe
a takto pomocí PID (Process Id): adplus -crash -o c:\temp -p 1234
PID pro daný proces najdete v Task Manageru. ADPlus lze dále konfigurovat pomocí speciálního konfiguračního souboru. Řekneme, například, že místo generování paměťového výpisu chcete generovat žurnál všech vyjímek, ke kterým došlo v daném procesu. V tomto případě vytvořte takovýto konfigurační soubor: <ADPLUS>
<SETTINGS>
<RUNMODE>CRASH</RUNMODE>
</SETTINGS>
<PRECOMMANDS>
<CMD>!load C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\sos.dll</CMD>
</PRECOMMANDS>
<EXCEPTIONS>
<OPTION>NoDumpOnFirstChance</OPTION>
<OPTION>NoDumpOnSecondChance</OPTION>
<CONFIG>
<CODE>clr</CODE>
<ACTIONS1>Log</ACTIONS1>
<CUSTOMACTIONS1>!pe;!CLRStack</CUSTOMACTIONS1>
<RETURNACTION1>GN</RETURNACTION1>
</CONFIG>
</EXCEPTIONS>
</ADPLUS>
ADPlus poté zavoláte takto: adplus –pn Crash.exe –c PrintExceptions.cfg
Výše uvedený konfigurační soubor je interpretován takto. Jakmile ADPlus zavolá ladící program CDB a CDB se připojí k cílovému procesu, dojde nejdříve k zavolání příkazu !load. Tento příkaz způsobí nahrání ladícího nástroje SOS do ladícího programu. Od tohoto momentu tedy bude možné používat příkazy uvnitř SOS k ladění managed procesu. Dále říkáme, že si nepřejeme generovat paměťový výpis (memory dump) v případě událostí "First chance" a "Second Chance", které se generují pro každou výjimku. Dále říkáme, že si přejeme odchytit všechny CLR výjimky (pomocí elementu CODE vnořeného do elementu CONFIG). Element ACTIONS1 naznačuje, že si přejeme logovat výjimky to textového žurnálu. CUSTOMACTIONS1 element definuje příkazy, které se vykonají v případě výskytu výjimky. Jednotlivé příkazy jsou odděleny středníkem. Příkaz !pe (Print Exception) provede výpis informací o výjimce, !CLRStack provede výpis managed zásobníku. GN (Go with exception Not handled) v elementu RETURNACTION1 znamená, že v po vykonání příkazu v CUSTOMACTIONS1 bude ladící program pokračovat ve vykonávání laděného programu a ladící program neprovede ošetření výjimky. Protože je GN příkaz určen pro události "First chance" (to je ten důvod pro koncovou jedničku či dvojku pro jednotlivé elementy v konfiguračním souboru) dostane nakonec laděný program příležitost ošetřit danou výjimku. Konečným výsledkem bude textový žurnál všech vyjímek.
Tak, a teď tedy mate vytvořený paměťový výpis (dump). Co s ním? O tom bude další díl.
|
-
Tento příspěvek nemá žádnou extra hodnotu. Následující schéma jsem si tady vystavil více méně pro sebe ale samozřejmě nikomu nebráním v jeho použítí :-). Nechce si mi to hledat pořád dokola a na tomhle místě to najdu snadno.

|
-
V minulém díle jsem popsal základní "extensibility points" produktu Microsoft BizTalk.
V této části se pokusím popsat, jak vypadá koncepčně zpráva
v prostředí BizTalk.
Poté, co je zpráva přijata pomocí daného adaptéru, je zpráva poslána do vstupní
fronty, která provede zpracování zprávy a její normalizaci. Výsledkem zpracování
zprávy je transformace původní zprávy do následující podoby:
Tento obrázek znázorňuje koncepční podobu původní zprávy tak, jak ji vidí BizTalk
engine a potažmo programátor uvnitř prostředí BizTalk přes
veřejné API. Handle slouží v tomto schématu jako
identifikátor
interní datové struktury zprávy. Body je ukazatel na blok dat, který obsahuje původní
tělo přijatého dokument. Tuto část popíši podrobně níže.
Kontext
První důležitou datovou strukturou je kontext zprávy. Kontext zprávy je seznam hodnot
(property bag), který je naplněn jednotlivými komponentami vstupní fronty. Jak
zpráva postupně proplouvá vstupní frontou, je předávána z jedné komponenty vstupní
fronty do druhé. Každá komponenta vstupní fronty provede analýzu přijaté zprávy
a
podle své interní logiky a obsahu přijaté zprávy přidá či změní hodnotu proměnné v kontextu zprávy.
Kontext zprávy je velmi důležitou datovou strukturou zprávy, neboť engine
BizTalk
nikdy nepřistupuje k datům původní zprávy. Pro engine BizTalk je původní přijatá
zpráva černou skřínkou, blob, který se engine BizTalk nesnaží žádným způsobem
interpretovat. Přestože může mít přijatá zpráva pevnou strukturu (například se jedná
o XML dokument, který odpovídá danému schématu), engine BizTalk se nikdy nebude
snažit interpretovat obsah této zprávy. I v případě XML dokumentu je formát přijaté
zprávy pro BizTalk binární blob, jehož význam je pro BizTalk neznámý.
Co se týče obsahu zprávy, tak BizTalk engine "vidí" pouze hodnoty v kontextu
zprávy. Pokud
je třeba zpřístupnit, zviditelnit, hodnotu zprávy, je nutné vyextrahovat danou hodnotu z těla
zprávy a umístit tuto hodnotu do kontextu zprávy. A to je právě úloha komponent
vstupní fronty. Každá ze zaregistrovaných komponent vstupní fronty má možnost analyzovat
obsah zprávy. Pokud je obsah zprávy dané komponentě znám, může tato komponenta vyextrahovat
hodnotu z těla zprávy a umístit kopii hodnoty do kontextu zprávy.
Implicitní vstupní fronty
Součástí dodávky systému BizTalk jsou dvě nakonfigurované vstupní fronty, PassThruReceive
fronta
a XMLReceive fronta. PassThruReceive frontu si můžete představit jako prázdnou vstupní frontu,
která neprovádí žádné zpracování přijaté zprávy. Tuto frontu můžete použít například
tehdy, pokud potřebujete přijímat zprávy v binárním formátu. V případě vstupní fronty
typu PassThruReceive přijatá zpráva "proletí" vstupní frontou, která
ovšem nebude neobsahovat žádné
nakonfigurované komponenty, které by tuto zprávu zpracovaly. Zpráva pak přeskočí
fázi, ve které je možné provést zpracování pomocí vstupní mapy.
Poté bude zpráva uložena
do MessageBoxu. V případě PassThruReceive nedochází ke
zpracování zprávy pomocí vstupní mapy, protože přijatá
zpráva má neznámý formát. Vstupní mapa je de-facto XSLT
transformace. K provedení této XSLT transformace musí znát BizTalk formát zprávy
(a pochopitelně se musí jednat o XML zprávu).
A v případě PassThruReceive je ale formát neznámý.
Pozorný čtenář si po předčtení předchozího odstavce může položit tuto otázku. Pokud
PassThruReceive neobsahuje žádné komponenty, které by prováděly zpracování zprávy,
znamená to také, že zpráva, která projde PassThruReceive
frontou nemá kontext? V předchozím
textu jsem totiž zmínil, že kontext je naplněn komponentami vstupní fronty. Pokud
PassThruReceive neobsahuje žádné takovéto komponenty, pak logicky zpráva nemůže
mít žádný kontext? Ve skutečnosti má každá vstupní zpráva kontext. Je tomu tak proto,
že kontext je plněn nejen komponentami vstupní fronty, ale i samotným engine BizTalk.
Každá zpráva například obsahuje v kontextu hodnotu se jménem BTS.AckReceivePortName.
Hodnota této proměnné identifikuje jméno portu, na kterém byla zpráva přijata.
Kontext tedy existuje pro každou zprávu.
XMLReceive fronta, která je součástí dodávky, je zajímavější než PassThruReceive
fronta. XMLReceive fronta provádí tzv. "Property Promotion" a typizaci zprávy. XMLReceive
fronta nejdříve provede identifikaci typu zprávy a
její validaci podle zaregistrovaného schématu. Pokud
použijete XMLReceive vstupní frontu a pošlete adaptéru XML zprávu s neznámým XML
formátem, dojde k odmítnutí této zprávy. V případě použití XMLReceive
fronty tedy musí být BizTalk
schopen identifikovat typ zprávy. Typem zprávy je její schéma. BizTalk identifikuje
typ zprávy spojením kořenového elementu zprávy (root element) se jmenným prostorem
(namespace) zprávy. BizTalk spojí tyto dvě informace dohromady a pokusí se pomocí
získané hodnoty nalézt zaregistrované schéma. Pokud je schéma nalezeno, dojde k
validaci dokumentu. Pokud není schéma nalezeno a nebo vstupní zpráva nemá odpovídající
formát podle schématu uvedeným ve zprávě pomocí kořenového elementu a jeho jmenného
prostoru, bude zpráva XMLReceive frontou odmítnuta.
Jakmile zná BizTalk typ zprávy, předá zprávu další komponentě XMLReceive
fronty. Tato komponenta
provede "Property Promotion". Jako součást projektu BizTalk je možné vytvořit speciální
schéma, tzv. "Property Schema". "Property Schema" obsahuje definice
XPATH ukazatelů, s pomocí kterých je možné
vyextrahovat potřebné hodnoty z těla XML zprávy daného formátu do kontextu zprávy. Tomuto procesu
se v hantýrce BizTalk říká "Property Promotion".
Patřičná komponenta XMLReceive fronty
pak podle typu dokumentu a XPATH definic nastaví hodnoty v kontextu zprávy.
Property Promotion versus Distinguished Properties
BizTalk engine umožňuje dva způsoby přístupu k hodnotám
uvnitř XML zpráv. První způsob
je "property promotion" popsaný výše, kdy dojde k vytvoření nové property
v kontextu zprávy a hodnota
této property bude nastavena aplikováním XPATH výrazu nad daným typem XML dokumentu.
Druhý způsob také používá XPATH výrazy. V tomto druhém případě však nedochází k
uložení hodnot do kontextu zprávy. Při prvním pohledu to může být matoucí - BizTalk
nabízí vlastně dva různé způsoby přístupu k hodnotám XML zprávy.
To, že v případě "distinguished property" nedochází k uložení hodnot do kontextu zprávy má zásadní
důsledek - hodnota je pro BizTalk engine neviditelná. BizTalk je publisher\subscriber
systém a subscriptions jsou vyhodnocovány podle obsahu jednotlivých hodnot v kontextu
zprávy. Pokud není daná property v kontextu zprávy, není
property pro BizTalk směrovací engine (routing engine)
viditelná a tudíž není možné provést směrování zprávy na základě
hodnoty této property. Výraz, který definuje filtr pro danou
subscription se může odkazovat pouze
na properties, které jsou v kontextu zprávy. A tudíž nepřímo pouze
na properties, které
jsou definované pomocí mechanismu "property promotion" a
tedy uloženy v kontextu zprávy. "Distinguished properties" je
mechanismus, který umožňuje pohodlný přístup do těla XML zprávy pomocí XPATH výrazu.
Tento přístup do těla zprávy je však možný pouze uvnitř choreografie procesu (orchestration)
protože, jak jsem zmínil na začátku, pro BizTalk je tělo zprávy pouze binárním
blob a to
i v případě XML zpráv. Následující obrázek se snaží demonstrovat tento rozdíl:
V tomto případě je property id objednávky
definováno jako "promoted property" a kopie hodnoty
je uložena do kontextu zprávy během průchodu zprávy vstupní XMLReceive frontou. Id objednávky
bude uloženo v kontextu zprávy a proto bude tato hodnota viditelná a použitelná
během směrování zprávy do zaregistrovaných subscriptions. Pokud je potřeba přistoupit
ke jménu odesílatele uvnitř orchestration, tak je možné definovat
"distinguished
property", což je XPATH výraz, který ukazuje přímo do těla zprávy. Hodnota elementu
<x:jmeno> je neviditelná pro směrovací (routing) BizTalk engine, ale
uvnitř orchestration je možné pomocí definované "distinguished
property"
pohodlně přistoupit k hodnotě elementu. A to právě přes nadefinovaný XPATH výraz
pro danou "distinguished
property".
Aby bylo možné použít danou property v kontextu zprávy ke směrování (use
for routing), nestačí
pouze tuto property uložit do kontextu zprávy. Směrovatelná property, tedy taková
property, která bude použita k nalezení zaregistrovaných subscriptions, musí mít nastaven příznak
"Promoted". Tento příznak je znázorněn ve výše uvedených diagramech jako hodnota 1
či 0, která je připojena ke každé property v kontextu. Proto je třeba
důsledně rozlišit
mezi pouhým vložením nové property do kontextu zprávy a mezi
"property promotion". "Property promotion"
se skládá ze dvou atomických operací - vložení property do kontextu
zprávy a zároveň nastavení
příznaku "Promoted". Property lze nastavit jako "Promoted" uvnitř
komponenty vstupní fronty, a to pomocí
metody IBaseMessageContext.Promote(). Dalším způsobem, jak přidat
property do kontextu zprávy a zároveň nastavit její příznak
"Promoted", je vytvořit
"correlation set" uvnitř orchestration. Tento "correlation set" musí obsahovat
property, kterou chceme přidat do kontextu zprávy s
příznakem "Promoted". Ale o tom jindy.
Message parts
Jak je možno vysledovat z předcházejících diagramů, zpráva může obsahovat více částí.
Jedna z těchto částí je označena jako tělo (body). Počet a význam jednotlivých částí
je plně v režii jednotlivých komponent vstupní fronty a choreografie procesu
(orchestration). Pokud je například přijata zpráva pomocí SMTP adaptéru, tak tělo
zprávy může reprezentovat text emailové zprávy a další části pak reprezentují jednotlivé
přílohy připojené ke zprávě. BizTalk neklade omezení na počet částí zprávy. Nemám
ověřeno, zda zpráva musí obsahovat aspoň jednu část, totiž tělo. V praxi budete
pravděpodobně vždy potřebovat tělo přijaté zprávy. Nesetkal jsem se s případem,
kdy by mělo smysl původní tělo zprávy zahodit. Typická zpráva tedy bude obsahovat
aspoň jednu část. Myslím si ale, že zpráva s nulovým počtem částí by měla být pro
BizTalk stravitelná jako jakákoliv jiná zpráva.
|
-
Legální verze Microsoft Office obvykle obsahuje holografickou známku. V současné době neexistuje běžně dostupné kopírovací zařízení, které by umělo věrohodně zkopírovat holografickou známku. Dalším jednoduchým prvkem je záznamové médium, které je od verze Office 95 výhradně CD nosič. Teď již tedy poznáte, zda je tato verze pro ruský trh legální:

|
-
Pokud používáte Virtual PC 2004 či Virtual Server 2005 (a vzhledem k tomu, že jsou oba produkty zdarma, tak není moc důvodu proč je ne), tak se vám možná bude hodit následující informace. Jaký je vlastně rozdíl mezi virtualním image, který vytvoříte v prostředí Virtual PC 2004 a virtuálním image, který vytvoříte v prostředí Virtual Server 2005? Obecně platí, že virtuální image, který byl vytvořen ve Virtual PC 2004 je plně kompatibilní s virtuálním image vytvořeným ve Virtual Server 2005. Oba produkty vytváří virtuální stroje, které jsou navzájem kompatibilní. Existuje pouze několik drobných rozdílů, o kterých je dobré vědět:
-
Virtual PC 2004 emuluje zvukovou kartu kdežto Virtuální Server 2005 nikoliv. Myšlenka je ta, že server, který hraje, je sice super, ale pravděpodobně stejně není slyšet, protože je určitě neprodyšně uzamčen v "servrovně". Pokud vytvoříte virtuální image pod Virtual PC 2004 a plánujete použít tento image i pod Virtual Server 2005, tak deaktivujte emulovanou zvukovou kartu. Tím zabráníte zbytečným chybám Plug and Play rozhraní pokud se pokusíte rozjet virtuální stroj vytvořený pod Virtual PC 2004 pod prostředím Vistual Server 2005.
-
SCSI podpora. Virtual Server 2005 podporuje SCSI zatímco Virtual PC 2004 nikoliv. Pokud vytvoříte virtuální image ze SCSI disky v prostředí Virtual Server 2005, tak tyto SCSI disky nebudou v prostředí Virtual PC 2004 vůbec viditelné a dostupné. To může způsobit celou řadu problému, zvláště, pokud jste v původním Virtual Server 2005 image použili SCSI disk jako zaváděcí disk operačního systému. Pokud plánujete použít virtuální image jak ve Virtual PC 2004 tak ve Virtual Server 2005, tak namapujte do vašeho virtuální stroje pouze IDE disky.
-
Vícenásobné CD-ROM zařízení. Virtual Server 2005 vám umožní vytvořít virtuální image s několika emulovanými CD-ROMy. Virtual PC 2004 podporuje pouze jednu CD-ROM mechaniku.
-
Saved state (soubor .vsv) není kompatibilní mezi těmito produkty. Pokud přenášíte virtuální image z jednoho produktu na druhý, proveďte kompletní zastavení (Shutdown) emulovaného operačního systému (guest operating system).
|
|
|
|