SDN_Magazine_124
SDN_Magazine_124
SDN_Magazine_124
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
MAGAZINE<br />
SOFTWARE DEVELOPMENT NETWORK<br />
ISSN: 2211-6486<br />
IN DIT NUMMER O.A.:<br />
Remote debugging naar een Azure VM <<br />
Decrease dataflows between systems with CDC <<br />
SQL Server In-Memory OLTP <<br />
SCRUM is meer dan een project management methodologie <<br />
Nummer <strong>124</strong> februari 2015 <strong>SDN</strong> <strong>Magazine</strong> verschijnt elk kwartaal en is een uitgave van Software Development Network<br />
<strong>124</strong><br />
www.sdn.nl
Colofon<br />
Uitgave:<br />
Software Development Network<br />
Drieëntwintigste jaargang<br />
No. <strong>124</strong> • februari 2015<br />
Bestuur van <strong>SDN</strong>:<br />
Marcel Meijer, voorzitter<br />
Rob Suurland, penningmeester<br />
Remi Caron, secretaris<br />
Redactie:<br />
Marcel Meijer<br />
(redactie@sdn.nl)<br />
Aan dit magazine<br />
werd meegewerkt door:<br />
Roel Hans Bethlehem, Bob Swart, Maarten<br />
van Stam, Arjen Bos, Alexander Meijers,<br />
Remi Caron, Marcel Meijer en natuurlijk alle<br />
auteurs!<br />
Listings:<br />
Zie de website www.sdn.nl voor eventuele<br />
source files uit deze uitgave.<br />
Contact:<br />
Software Development Network<br />
Postbus 506, 7100 AM Winterswijk<br />
Tel. (085) 21 01 310<br />
E-mail: info@sdn.nl<br />
Vormgeving en opmaak:<br />
Reclamebureau Bij Dageraad, Winterswijk<br />
www.bijdageraad.nl<br />
©2015 Alle rechten voorbehouden. Niets uit<br />
deze uitgave mag worden overgenomen op<br />
welke wijze dan ook zonder voorafgaande<br />
schriftelijke toestemming van <strong>SDN</strong>. Tenzij<br />
anders vermeld zijn artikelen op persoonlijke<br />
titel geschreven en verwoorden zij dus niet<br />
noodzakelijkerwijs de mening van het bestuur<br />
en/of de redactie. Alle in dit magazine<br />
genoemde handelsmerken zijn het eigendom<br />
van hun respectievelijke eigenaren.<br />
Beste <strong>SDN</strong> <strong>Magazine</strong> lezer,<br />
voorwoord<br />
Hebben jullie met open mond naar de Windows 10 presentatie zitten kijken? Gezien<br />
hoe de opvolger van Windows 8 steeds volwassener wordt en alle plooien er nu wel<br />
uitstrijkt? Heb je al gespeeld met de volgende versie van Office 2015 welke meer gericht<br />
is op touch gebruik? Heb je al gekeken naar de nieuwe Visual Studio versie met<br />
daarin allerlei performance meters? Heb je de vele Microsoft applicaties op het Android<br />
en iOS platform al bekeken? Dat zijn er al ruim 100. In het verleden is<br />
Microsoft vaak verweten dat ze een gesloten omgeving waren, hoewel ze als eerste<br />
ooit voor de MAC applicaties ontwikkelde. Maar tegenwoordig zijn ze nog opener en<br />
laten dat ook graag weten.<br />
In de volgende magazines en events van de <strong>SDN</strong> komen jullie naast artikelen en<br />
sessies van de andere platformen ook verhalen tegen over Microsoft. De <strong>SDN</strong> is voor<br />
alle soorten developers en alle soorten platforms. En dat blijft zo.<br />
Op vrijdag 20 maart is het volgende <strong>SDN</strong> event. Op dit event zal ook de Algemene<br />
leden vergadering weer plaats vinden. Dit is naast natuurlijk rechtstreeks met mij te<br />
mailen of ons te bellen, de uitgelezen kans om je als lid van de vereniging te laten<br />
informeren en te horen over het reilen en zeilen van de vereniging. Kom dus allemaal<br />
en laat je stem spreken.<br />
Dit magazine <strong>124</strong> bevat wederom een uiteenlopende hoeveelheid aan onderwerpen.<br />
Over Dynamics CRM, Remote debugging op Azure, Application Insights deel 2, CDC<br />
wat is de zin en onzin hiervan, Azure Webjobs, Microservices een mooie<br />
verhandeling, de ELK stack wat is het, In-Memory OLTP databases, SCRUM is<br />
bruikbaar in meerdere onderdelen van een organisatie, de Delphi's REST Client<br />
Library, Microsoft Test Manager beschrijving en nog een paar kleine tips en tricks.<br />
Kortom, Bas van de Sande, Cary Jensen, Eric Tummers, Hassan Fadili, Jeffrey<br />
Verheul, Marcel Meijer, Patrick Kalkman, Peter ter Braake. Piet Willem Overvoorde,<br />
Sander Hoogendoorn en Wouter de Kort hebben weer veel tijd gestoken in deze<br />
stuk voor stuk mooie verhalen. Speciaal voor jullie als <strong>SDN</strong> magazine lezer.<br />
Het volgende magazine 125 maken we iets specialer. Daarover later meer.<br />
Heel veel leesplezier en tot 20 maart bij de ALV.<br />
Groeten,<br />
Marcel Meijer eindredacteur <strong>Magazine</strong> en Voorzitter <strong>SDN</strong> •<br />
Adverteerders<br />
Microsoft 2<br />
Achmea 44<br />
Adverteren?<br />
Informatie over adverteren en de advertentietarieven<br />
kunt u vinden op www.sdn.nl<br />
onder de rubriek <strong>Magazine</strong>.<br />
magazine voor software development 3
Agenda 2015<br />
Inhoud<br />
• 16-19 maart 2015<br />
Microsoft Convergence 2015<br />
Atlanta<br />
• 20 maart<br />
<strong>SDN</strong> event, Zeist<br />
• 29 april - 1 mei<br />
//Build<br />
San Francisco<br />
• 4-8 mei<br />
Microsoft Ignite<br />
Chicago at McCormick Place<br />
• 12-13 mei<br />
Techorama Belgium 2015<br />
• 28-29 mei<br />
TechDays, Den Haag<br />
• 12 juni<br />
<strong>SDN</strong> event<br />
• 12-16 juli<br />
Worldwide Partner Conference<br />
Orlando<br />
• 18 september<br />
<strong>SDN</strong> event<br />
03 Voorwoord<br />
Marcel Meijer<br />
04 Inhoudsopgave<br />
04 Agenda<br />
05 Microsoft Dynamics CRM<br />
Bas van de Sande<br />
08 Remote debugging naar een Azure VM<br />
Eric Tummers<br />
10 Application Insights<br />
for Visual Studio Online (Part 2)<br />
Hassan Fadili<br />
15 Decrease dataflows<br />
between systems with CDC<br />
Jeffrey Verheul<br />
17 Azure Webjobs<br />
Marcel Meijer<br />
19 Microservices.<br />
The good, the bad and the ugly<br />
Sander Hoogendoorn<br />
23 Improving traceability<br />
of distributed systems using the ELK stack<br />
Patrick Kalkman<br />
30 SQL Server In-Memory OLTP<br />
Peter ter Braake<br />
32 SCRUM is veel meer dan een<br />
project management methodologie<br />
Piet Willem Overvoorde<br />
36 Delphi's REST Debugger<br />
and REST Client Library, Part 1<br />
Cary Jensen<br />
41 Ken jij Microsoft Test Manager?<br />
Wouter de Kort<br />
43 API Management<br />
Marcel Meijer
GENERAL<br />
Bas van de Sande<br />
Microsoft Dynamics CRM<br />
“A journey of a SharePoint developer into the world of CRM”<br />
Na jarenlang software ontwikkeld te hebben in C#, SQL Server, BizTalk en SharePoint ben<br />
ik onlangs overgestapt op het Microsoft Dynamics CRM platform. In deze serie artikelen wil<br />
ik mijn ervaringen delen en jullie enthousiast maken voor dit relatief onbekende platform.<br />
In dit artikel beschrijf ik in hoofdlijnen wat CRM inhoudt en waarom de ‘C’ van CRM eigenlijk<br />
een ‘x’ hoort te zijn. Ten slotte werp ik een eerste blik onder de motorkap van Microsoft<br />
Dynamics CRM.<br />
Geschiedenis<br />
De eerste versie van Microsoft Dynamics CRM is uitgebracht in 2003.<br />
Microsoft was in die tijd bezig met het opkopen van een aantal<br />
spelers in de ERP en boekhoudmarkt (o.a. Great Plains, Navision) om<br />
zo een positie in de Enterprise markt te verwerven. De CRM, ERP en<br />
boekhoudproducten zijn later ondergebracht onder de noemer<br />
Microsoft Dynamics, te weten AX (ERP), NAV (boekhouding) en<br />
uiteraard CRM. Op dit moment is CRM 2015 net beschikbaar<br />
gekomen. Naast de on-premise versie is CRM ook verkrijgbaar als<br />
CRM Online.<br />
Wat is CRM?<br />
CRM staat voor Customer Relationship Management, oftewel het<br />
beheren van de relatie tussen een klant en een organisatie. Elke<br />
klantrelatie kent een levensduur die uit een aantal fases bestaat.<br />
De inzet van CRM is er opgericht om de klant in iedere fase van de<br />
relatie optimaal te kunnen bedienen om zo een maximaal rendement<br />
uit de relatie te halen.<br />
Maar niet iedereen die een relatie met een organisatie of bedrijf<br />
onderhoudt, is per definitie een ‘customer’. Je kan bijvoorbeeld lid<br />
van zijn van een vereniging, deelnemer aan een community, donateur<br />
van een goed doel, student bij een opleidingsinstituut of juist leverancier<br />
aan een bedrijf.<br />
Microsoft Dynamics CRM<br />
Net zoals bijvoorbeeld SharePoint is ook Microsoft Dynamics CRM<br />
beschikbaar als een on-premise versie (CRM 2013/2015) en online<br />
als CRM Online. Echter, in tegenstelling tot SharePoint lopen de<br />
on-premise en de online versie van CRM voor de ontwikkelaar niet ver<br />
uitelkaar en kun je de technieken die je gebruikt voor je on-premise<br />
oplossing gemakkelijk naar de online versie brengen. Zowel de<br />
on-premise als de online versie bieden een goede ondersteuning voor<br />
mobiele devices (iOS, Android en Windows Phone).<br />
Microsoft Dynamics CRM integreert nagenoeg naadloos binnen de<br />
Office suite (add-in voor Outlook) en leunt technologisch zwaar op<br />
de SQL Server database, SQL Server Reporting Services, Internet<br />
Information Server en het Microsoft.Net framework (sandbox). Kortom,<br />
alle bouwstenen voor een solide applicatieplatform zijn hiermee<br />
voorhanden.<br />
Zowel de on-premise als de online versie van CRM ziet er in hoofd lijnen<br />
als volgt uit:<br />
De ‘C’ in CRM moet je dus ruim zien en de essentie van CRM is het<br />
optimaal bedienen van de relatie tussen een persoon of organisatie en<br />
jouw organisatie. De ‘C’ moet je dan eigenlijk ook zien als een ‘x’,<br />
waarbij de ‘x’ staat voor de andere partij.<br />
Als ontwikkelaar moet je er altijd rekening mee houden dat CRM wordt<br />
ingezet om te voorzien in een functionele behoefte. CRM wordt, in<br />
tegenstelling tot andere softwareproducten, niet vanuit de IT-afdeling<br />
gepusht, maar juist geïnitieerd voor en/of door de gebruiker; vaak<br />
werkzaam op de klantgerichte afdelingen binnen het bedrijf (marketing,<br />
verkoop, ledenadministratie, klantenservice). Binnen CRM zijn<br />
de klantgegevens, en wat de organisatie wil met die klantgegevens<br />
leidend, de technologie is volgend.<br />
In projecten betekent dit dat oplossingen grotendeels door functionele<br />
consultants in samenwerking met de gebruikers in elkaar worden<br />
gezet. Daar waar nodig mogen wij - ontwikkelaars - bijspringen om<br />
de complexe onderdelen, rapportages, integraties te ontwikkelen en<br />
om de gebouwde oplossing in de vorm van een solution uit te rollen.<br />
Fig. 1: schematische weergave opbouw Microsoft Dynamics CRM<br />
De business functionaliteit van Microsoft Dynamics CRM wordt<br />
ontsloten door middel van een .NET API. Daarbovenop is een web<br />
magazine voor software development 5
GENERAL<br />
API geplaatst waarmee allerlei client applicaties verbinding kunnen<br />
maken. Binnen de formulieren kan gebruik gemaakt worden van<br />
javascript om extra functionaliteit te ontsluiten.<br />
The power of SQL Server<br />
De kern van CRM zijn de SQL Server databases. Een van de data -<br />
bases bevat metadata omtrent de configuratie, verder is er nog een<br />
content database. Deze database bevat de feitelijke data.<br />
Waarin CRM hemelsbreed verschilt ten opzichte van SharePoint, is<br />
dat in de CRM data fysieke entiteiten en velden worden aangemaakt<br />
waarin de data wordt opgeslagen. Dit in tegenstelling tot SharePoint,<br />
waarbij de database bestaat uit een aantal metatabellen en data -<br />
tabellen, waar op basis van de opgeslagen meta-informatie de echte<br />
data kan worden teruggevonden. Hier ligt dan ook echt de kracht van<br />
CRM, namelijk een échte database, met fysieke relaties tussen<br />
entiteiten (referentiële integriteit).<br />
Het is echter niet de bedoeling dat gegevens rechtstreeks in de<br />
database worden aangepast; je zou daarmee een aantal ingestelde<br />
business rules kunnen overtreden (constraints). Het aanpassen van<br />
de data gebeurt via het objectmodel dat CRM je ter beschikking stelt.<br />
Nu vraag je je waarschijnlijk af: “Ja… maar als ik nou niet de regels<br />
overtreed, waarom mag ik dan niet rechtstreeks de tabellen<br />
vullen?”. Dat heeft te maken met de manier waarop<br />
Microsoft Dynamics CRM omgaat met aanpassingen<br />
op het applicatieplatform.<br />
In de online versie is het niet mogelijk om rechtstreeks bij de<br />
onderliggende SQL Server databases te komen, waar je<br />
normaal als DBA extra indexen kan leggen om de performance<br />
te verbeteren. In dat geval zal je terug moeten<br />
vallen op Microsoft support. Zij kunnen dit voor je doen.<br />
Reporting<br />
Als CRM ontwikkelaar werk je normaal gesproken tegen<br />
het objectmodel aan. Echter, in het geval van rapportages<br />
werk je tegen een database view aan die door CRM wordt<br />
beheerd.Microsoft Dynamics CRM maakt gebruik van SQL<br />
Server Reporting Services. Juist omdat CRM geheel is<br />
gebaseerd op data, gebruikt het gelukkig ook de kracht van<br />
de onderliggende SQL Server database om query’s uit te<br />
voeren. Je kan dan ook in de datasets die je maakt<br />
volledig gebruik maken van de mogelijkheden van<br />
Transact SQL. De report definities die uit SSRS voort -<br />
komen, kun je later uitrollen via je eigen solution.In de online<br />
versie kun je geen gebruik maken van SQL query’s, je<br />
moet hier met FetchXML werken. FetchXML is een op<br />
XMLgebaseerde querytaal voor Dynamics CRM.<br />
van de solution worden aanpassingen binnen de database gemaakt,<br />
hierbij wordt de oorspronkelijke structuur met rust gelaten.<br />
Wanneer je met bijvoorbeeld SQL Server Management Studio naar de<br />
database kijkt, zie je dat van een bepaalde entiteit (bijvoorbeeld<br />
Account) meerdere tabellen bestaan. Wanneer je de geïnstalleerde<br />
solution verwijdert, dan zullen eventuele aangemaakte tabellen of<br />
relaties verdwijnen.<br />
Het solution mechanisme van Microsoft Dynamics CRM is erg<br />
krachtig en ook gemakkelijk in het gebruik. Je hoeft geen ingewikkelde<br />
provisioning te bouwen en je kunt de solution letterlijk in elkaar<br />
klikken.Solutions die zijn gemaakt op één omgeving kan je exporteren,<br />
zodat je deze op een andere omgeving kan importeren en uitrollen.<br />
Dit mechanisme leent zich uitstekend voor een OTAP straat.<br />
Autorisatie<br />
Net als ieder server platform, maakt ook Microsoft Dynamics CRM<br />
gebruik van autorisatie. Hierin gaat Microsoft Dynamics CRM erg ver<br />
- terecht trouwens, want je werkt vaak met erg gevoelige informatie.<br />
De data die in CRM is opgeslagen, wordt beschermd door middel van<br />
een zeer uitgebreide autorisatiematrix (door een beheerder instelbaar).<br />
Fig. 2: voorbeeld autorisatiematrix binnen CRM<br />
Het werken met solutions<br />
Net zoals Microsoft SharePoint is ook Microsoft Dynamics<br />
CRM een applicatieplatform, waarbij ontwikkelaars en<br />
gebruikers aanpassingen kunnen maken om zo toepassingen<br />
te maken die aansluiten op de processen binnen de<br />
organisatie.<br />
Binnen Microsoft Dynamics CRM is altijd minimaal één<br />
solution geïnstalleerd. Dit is de default solution. Als je<br />
wijzingen maakt op de default solution pas je hiermee de<br />
kern van CRM aan. De wijzigingen die je uitvoert, kunnen<br />
niet met één druk op de knop worden verwijderd.<br />
Om te waarborgen dat je aanpassingen wel ongedaan<br />
gemaakt kunnen worden, maak je gebruik van solutions.<br />
Binnen de solution wordt van alle objecten die je gaat<br />
aanpassen (die je dus toevoegt aan de solution) een kopie<br />
gemaakt en met deze kopie ga je aan het werk.<br />
Nadat je de wijzigingen hebt doorgevoerd publiceer je deze<br />
naar Microsoft Dynamics CRM toe. Tijdens het publiceren<br />
Fig. 3: autorisatieniveaus binnen CRM<br />
6<br />
MAGAZINE
GENERAL<br />
In de matrix wordt vastgelegd wie wat mag doen met welke data en<br />
wie eigenaar is van welke data. Dit is te vergelijken met item level<br />
security binnen SharePoint, maar dan vele malen krachtiger en<br />
uitgebreider uitgevoerd.<br />
Per gebied, rol, veld en/of entiteit kan worden vastgelegd wie wat met<br />
data mag doen en wie eigenaar is van de data. In onderstaande<br />
afbeelding geef ik aan wat de symbolen voorstellen<br />
Binnen CRM modelleer je de organisatie. Een organisatie bestaat uit<br />
business units (dit kunnen business units maar ook afdelingen zijn, en<br />
kunnen hiërarchisch worden weergegeven). Op het onderste niveau<br />
staat de gebruiker. De autorisatiematrix maakt gebruik van dit principe<br />
en de symbooltjes geven aan wie de eigenaar is van de gegevens<br />
binnen CRM. Naarmate het bolletje meer is ingekleurd, is er een<br />
grotere groep die toegang heeft tot de gegevens.<br />
Ogenschijnlijk een eenvoudig te gebruiken mechanisme, maar in de<br />
praktijk een van de lastigste onderdelen binnen CRM om te<br />
doorgronden.<br />
Ten slotte<br />
Mijn ervaringen tot zover met Microsoft Dynamics CRM is dat het een<br />
erg krachtig platform is om bedrijfstoepassingen te bouwen waarin<br />
relaties tussen organisaties en personen worden onderhouden.<br />
Wanneer je gewend bent om te ontwikkelen op een platform als<br />
SharePoint zal je aangenaam verrast worden door een aantal zaken<br />
die standaard voor je geregeld worden binnen CRM zonder dat je je<br />
hiervoor in allerlei bochten hoeft te wringen.<br />
Het prettige aan het ontwikkelen op CRM is dat het eigenlijk niet<br />
uitmaakt of je voor de on-premise of voor de online versie ontwikkelt.<br />
Het enige verschil dat ik ben tegengekomen zit hem in het moeten<br />
gebruiken van FetchXML wanneer je met SQL Server Reporting<br />
Services werkt.<br />
Microsoft Dynamics CRM is geen wondermiddel; maar wel een goed<br />
stuk gereedschap dat je moet inzetten waarvoor het bedoeld is,<br />
namelijk het onderhouden van relaties en processen die daarmee<br />
gerelateerd zijn. •<br />
Bas van de Sande<br />
Bas van de Sande heeft zich sinds<br />
1995 gespecialiseerd in softwareontwikkeling<br />
en advisering op het<br />
Microsoft platform. Hij heeft zich<br />
sinds 2005 voornamelijk bezig<br />
gehouden met SharePoint en<br />
Microsoft.Net. Op dit moment ligt<br />
zijn focus op Microsoft CRM en<br />
blogt hij zeer actief over zijn<br />
ervaringen met CRM. Bas is werkzaam als Senior Software<br />
Developer/Architect bij CRM Partners.<br />
ConnectionStrings / AppSettings Azure<br />
Zoals je op pagina 17 in dit magazine kunt lezen, wordt een Webjob gedeployed<br />
bij een Azure website. Bij de Webjob hoort ook een dashboard. Na het deployen<br />
van de Webjob waren er Errors en Warnings over een setting. Zoals de error/<br />
warning verteld, moet je de Connectionstring toevoegen aan het Connection string<br />
gedeelte van de Azure website. Daarna is de error/warning weg.<br />
In je code gebruik je:<br />
var storageAccount =<br />
CloudStorageAccount.Parse(<br />
ConfigurationManager.<br />
ConnectionStrings[“AzureWebJobsStorage”].<br />
ConnectionString<br />
);<br />
Maar de Connectionstrings of App settings geef je een waarde op de Configure<br />
tab van de Azure Website.<br />
Nu lijkt het net of je deze Connectionstring op twee plekken moest configureren.<br />
Een keer op de portal en een keer in de app.config van de Webjob. Dat zou niet<br />
mooi zijn, maar dat blijkt ook niet te hoeven.<br />
En dit werkt ook voor de App.config van een Azure Webjob.<br />
Meer informatie: http://www.asp.net/identity/overview/features-api/best-practices-for-deploying-passwords-and-other-sensitive-data-to-aspnet-and-azure<br />
magazine voor software development 7
CLOUD<br />
Eric Tummers<br />
Remote debugging<br />
naar een Azure VM<br />
Je hebt OTAP met Windows Azure virtual machines ingericht. Deployment gebeurd automatisch<br />
na een nightly build. Alles is koek-en-ei totdat er een probleem optreedt dat je wil debuggen.<br />
Hoe doe je dat in Azure? Installeren van Visual Studio op de VM lijkt de enige optie? Gebruik<br />
Remote Debugging vanuit je development machine naar een Azure VM.<br />
Debugger extension<br />
Via de Server Explorer in Visual Studio kan de debugger extension op<br />
een Azure VM geïnstalleerd worden. Integratie in Visual Studio maakt<br />
het makkelijker om een debug session te starten.<br />
VPN<br />
Als jouw development machine in hetzelfde network zit, kun je een<br />
remote debugging sessie starten. Hiervoor maak je een VPN aan.<br />
Ga naar het virtual network in de azure portal. Open de Configure tab<br />
en check Configure point-to-site connectivity. Kies daarna een<br />
starting IP.<br />
Fig. 2: Point-to-site connectivity van virtual network<br />
De sectie eronder zal de melding geven dat een gateway nodig is. Klik<br />
add gateway subnet en wijzig indien nodig het starting IP. Kies Save<br />
en wacht tot alle wijzigingen zijn doorgevoerd.<br />
Fig. 1: Remote debugger extension installation<br />
Hiermee worden echter wel drie poorten geopend en dat is een optie<br />
die je mogelijk niet hebt. Dan moet een VPN gebruikt worden en de<br />
remote debugging tools.<br />
Virtual Network<br />
Een best practice is om je VM’s in een virtual network te plaatsen.<br />
Hierdoor kunnen machines elkaar makkelijker vinden. Ook bied het<br />
een extra laag van beveiliging, omdat poorten voor interne<br />
communicatie niet naar de boze buitenwereld open staan.<br />
Fig. 3: Gateway van virtual network<br />
Open een Visual Studio Command prompt en maak een self-signed<br />
root certificate aan. Maak ook een authenticatie certificaat aan voor het<br />
root certificaat.<br />
8<br />
MAGAZINE
CLOUD<br />
makecert -sky exchange -r -n "CN=MyNetwork"<br />
-pe -a sha1 -len 2048 -ss My "MyNetwork.cer"<br />
makecert -n "CN=Developer" -pe -sky exchange<br />
-m 96 -ss My -in "MyNetwork" -is my -a sha1<br />
Listing 1: Self-signed root certificate en<br />
authenticatie certificaat aanmaken<br />
Upload het root certificaat (MyNetwork.cer) op<br />
de Certificates tab. Dit wordt gebruikt om de<br />
client VPN te configureren.<br />
Op de Dashboard tab wordt de gateway nou<br />
weergegeven als niet aangemaakt. Klik CREATE<br />
GATEWAY, dit zal ongeveer 15 minuten duren.<br />
Als de gateway aangemaakt is, kun je de Client<br />
VPN Package downloaden en installeren.<br />
Start de VPN in Network Connections van<br />
Windows.<br />
Remote debugging<br />
Maak een Remote Desktop connectie naar de<br />
Azure VM. Download en installeer de visual<br />
studio remote debugging tools van Microsoft. Bij<br />
de eerste keer starten van de Remote Debugger<br />
moet deze geconfigureerd worden. Kies<br />
configure remote debugging om de defaults te<br />
gebruiken. Daarna opent de Remote Debugger<br />
en wacht op connectie van een machine.<br />
Fig. 4: Download client vpn package<br />
Open Visual Studio op de development machine.<br />
Ga naar Debug > Attach to Process … Laat het<br />
transport op Default staan. Gebruik bij Qualifier<br />
het IP adres dat bij de machine staat op het virtual<br />
network dashboard (Figure 3) en de default<br />
poort 4018. Log in met dezelfde credentials als<br />
de Remote Desktop.<br />
Selecteer het process en klik Attach. Remote<br />
Debugging naar een Azure VM zonder poorten<br />
open te zetten.<br />
Conclusie<br />
Met remote debugging kun je ook in een Azure VM sneller bugs<br />
oplossen. OTAP in Windows Azure is de toekomst. De redenen om het<br />
niet te doen worden steeds minder.<br />
Links<br />
Remote debugging tools<br />
(http://www.microsoft.com/en-us/download/details.aspx?id=43724)<br />
Debugging a Cloud Service or Virtual Machine in Visual Studio<br />
(http://msdn.microsoft.com/en-us/library/azure/ff683670.aspx) •<br />
Fig. 5: Attach to remote process<br />
Eric Tummers<br />
Eric Tummers is werkzaam als<br />
technisch consultant bij Valid en<br />
richt zich op kwaliteit in software<br />
development. Denk hierbij aan unit<br />
testen, build en deployment<br />
processen. Bloggen doet Eric voornamelijk<br />
over zijn werk, maar af en<br />
toe komt een thuis project erop te<br />
staan, een productiviteit tip of een review. Als het maar bijdraagt<br />
aan het sociale internet.In 2015 gaat Eric aan de slag met devops.<br />
Daarbij staan powershell en Windows Azure centraal.<br />
magazine voor software development 9
.NET /<br />
CLOUD<br />
Hassan Fadili<br />
Application Insights<br />
for Visual Studio Online (Part 2)<br />
In one of the previous <strong>SDN</strong> <strong>Magazine</strong>s (<strong>Magazine</strong> 121), I have introduced Application Insights<br />
on VSO basics and usage of it on project level and on Visual Studio Online Dashboards. In this<br />
article, I will go a step further and explain & show “How Application Insights can help by many<br />
scenarios to get more out telemetry of your Application / Systems?”<br />
To make this concrete, I will walk through the following scenario: “Use<br />
Application Insights to understand application behavior”. To do so,<br />
I have split this scenario into the following tasks:<br />
• Create MVC Web Application and Add Application Insights to It<br />
• Create load / Web tests to simulate the scenarios.<br />
• Use App Insights and Load test to validate the assumptions.<br />
By clicking Add Application Insights To Project, this process starts as<br />
shown below (Fig.3) where the NuGet packages needed are installed:<br />
To start, an ASP.NET MVC Web Application is created. During this<br />
creation, the Application Insights are added to that MVC Web<br />
Application as shown below (Fig 1):<br />
Fig. 3: Adding progress of AI to Project and<br />
NuGet packages Install process<br />
Once this step is finished, the Application<br />
Insights.config and Web ApplicationI Ovreview files<br />
are added to project as shown below (Fig.4):<br />
Fig. 1: Creation of MVC Web Application with Add Application<br />
Insights selected<br />
As part of the Add Application<br />
Insights Process, a resource<br />
MUST be specified<br />
to send telemetry to. This<br />
can be an existing resource<br />
or a new created one as<br />
shown below (Fig 2):<br />
Fig. 2: Add Application<br />
Insights to Project and<br />
specifying the resource<br />
to send telemetry to<br />
Fig. 4: Added Application<br />
Insights Resources to Project<br />
10<br />
MAGAZINE
.NET /<br />
CLOUD<br />
Beside the Application Insights Resources added to Project, there are<br />
also some Application Insights References added to the project as<br />
well. This specific references are shown below (Fig.5):<br />
Open Application Insights from Visual Studio (Solution Explorer)<br />
guides to VSO Dashboard:<br />
Fig. 7: Opening AI from Solution Explorer guides to VSO Dashboard<br />
Because the VSO Dashboard is on Microsoft Azure, the user MUST be<br />
authenticated and authorized to access the specific Azure Instance<br />
by signing to it as shown below (Fig.8):<br />
Fig. 5: Application Insights Specific References added to Project<br />
To examine the added ApplicationInsights.config, this can be opened<br />
by double click on It. The content of it is shown below (Fig.6):<br />
Application Insights Configuration file content:<br />
Fig. 8: Signing to Azure Portal for Accessing Application Insights<br />
on Project Level in Microsoft Azure<br />
By Signing into Microsoft Azure Portal with the right credentials (Email<br />
and Password), Microsoft Azure Portal is shown and Application<br />
Insights can be added as Tile on this Dashboard as shown below<br />
(Fig.9 + Fig.10)<br />
Adding Application Insights to Project from Azure Portal:<br />
Fig. 6: Application Insights Configuration File Content<br />
Once the Add process and examining the Application Insights<br />
content on Visual Studio are done, the next step can be to get into<br />
Visual Studio Online Dashboard (VSO) to see the Application Insights<br />
Information in action. This can be done in 2 ways:<br />
• By right click the Web Application Overview file and select Open<br />
Application Insights (see below Fig.7)<br />
• By double click on the same Web Application Overview file<br />
Fig. 9: Adding AI to Azure Project Dashboard<br />
magazine voor software development 11
.NET /<br />
CLOUD<br />
Adding Application Insights from Azure Portal Futures to Project:<br />
Progress of Adding AI to Project on Azure Portal:<br />
Fig. 10: Adding Application Insights to Project from Azure Portal<br />
Futures<br />
To be more specific on this add process, the user MUST specify the<br />
Web Application Information that can be used to be added as shown<br />
below (Fig.11) like:<br />
• Application Name<br />
• Application Type<br />
• Resource Group<br />
• Subscription<br />
• Location<br />
Fig. 12: Progress of Adding Application Insights to Project on Azure<br />
Portal<br />
From this point, all Application Insights information of a specific Web<br />
Application can be analyzed from the Application Insights Dashboard<br />
like “Events” a shown below (Fig.13):<br />
Status of Application Insights Events on Azure Portal after<br />
Creation:<br />
Application Information Specifying for Application Insights on<br />
the Azure Portal:<br />
Fig. 13: Status of AI Events on Azure portal after Creation<br />
To monitor telemetry for the Web Application, the selected source<br />
code below (Fig.14) MUST be added to all pages that must be<br />
tracked for Application Insights telemetry like we have done below for<br />
Index.cshtml file:<br />
Adding Source code to all webpages that have to be tracked for<br />
Application Insights:<br />
Fig. 11: Application Information to be added for Application Insights<br />
on Azure Portal<br />
When all the necessary information is provided, the user can click on<br />
Create button and creation progress is shown on the Microsoft Azure<br />
Dashboard as shown below (Fig.12)<br />
Fig. 14: Code to be added to all Web Pages that have to be tracked<br />
for AI<br />
12<br />
MAGAZINE
.NET /<br />
CLOUD<br />
When all the specific pages are updated with the code above (Fig.14),<br />
The Web Application can be compiled and executed. At that moment<br />
the first Application Insights Events are sent to Visual Studio<br />
Online Dashboard that is configured as show below (Fig.15)<br />
Overview Page Views Information on Azure Portal:<br />
First Application Insights Events sending to Azure Portal after<br />
Adding code to Specific Page(s) that have to be tracked:<br />
Fig. 18: More Application Insights Info (Page Views) on Azure<br />
Dashboard<br />
Overview Page Views Charts Information on Azure Portal:<br />
Fig. 15: First Application Insights Events sent to Azure Portal after<br />
adding the specific source code to It<br />
Below (Fig.16, Fig.17, Fig.18, Fig.19, Fig.20 ) some specific Application<br />
Insights Information you can track from the Microsoft Azure<br />
Portal on Visual Studio Online like:<br />
• TimeLine overview<br />
• Pages Views<br />
• Page Views Charts<br />
• Diagnostic Search<br />
• ……<br />
Overview TimeLine Information on Azure Portal:<br />
Fig. 19: Application Insights Page Views Charts Info Configuration<br />
Overview Diagnostic Search Information on Azure Portal:<br />
Fig. 20: Application Insights-Diagnostic Search on Azure Dashboard<br />
Fig. 16: Overview TimeLine Information on Azure Portal<br />
Usage TimeLine Information on Azure Portal:<br />
Creating Load Test / Web Test for the application and Instrument It:<br />
Adding Load / Performance Test Project to Solution for instrumen -<br />
tation:<br />
Fig. 17: Usage TimeLine Information on Azure Portal<br />
Fig. 21: Adding Web-Performance-Load Test Project<br />
magazine voor software development 13
.NET /<br />
CLOUD<br />
Running Web Test of AI_WebApplication:<br />
Fig. 25: WebTest Results after investigation in Visual Studio<br />
Fig. 22: Running Web Test Status of AI_WebApplication<br />
After you've deployed your web application, you can set up web tests<br />
to monitor its availability and responsiveness. Application Insights will<br />
send web requests at regular intervals from points around the world,<br />
and can alert you if your application responds slowly or not at all.<br />
So we can act directly by tracking all information needed on applica<br />
tion level and simulate the load and usage of our application /<br />
System. Because of the good integration of Visual Studio, Visual<br />
Studio Online and Microsoft Azure Dashboard, we can request all<br />
Application Insights information for our applications to track like:<br />
• Application Health<br />
• Diagnostics<br />
• Performance<br />
• Usage Analytics ( X Days)<br />
• Operations<br />
• Access<br />
In the next series of this articles, I will take this topic a step further and<br />
walk through other cool Application Insights futures and configurations.<br />
So I will discuss the “Segmentation; Application Insights support<br />
for Multiple Environments, Stamps and App Versions; Search your logs<br />
instantly using property filters”. Stay Tuned ;-).<br />
Fig. 23: Web Tests Response time (ms)<br />
NB: You can set up web tests for any HTTP endpoint that is<br />
accessible from the public internet.<br />
Overview All WebTest Response Information on Azure Portal:<br />
Links:<br />
Getting started with Application Insights:<br />
http://azure.microsoft.com/en-us/documentation/articles/<br />
app-insights-get-started/<br />
Channel 9: Application Insights overview:<br />
https://channel9.msdn.com/Events/Visual-Studio/Connect-event-<br />
2014/216<br />
Application Insights SDK:<br />
http://blogs.msdn.com/b/visualstudioalm/archive/2014/10/21/<br />
application-insights-sdk-0-11-0-prerelease.aspx<br />
Application Insights: Exception Telemetry<br />
http://blogs.msdn.com/b/visualstudioalm/archive/2014/12/12/<br />
application-insights-exception-telemetry.aspx<br />
Monitor any web site's availability and responsiveness:<br />
http://azure.microsoft.com/en-us/documentation/articles/<br />
app-insights-monitor-web-app-availability/<br />
Web tests for Microsoft Azure Websites:<br />
http://azure.microsoft.com/en-us/documentation/articles/<br />
insights-create-web-tests/ •<br />
Hassan Fadili<br />
Fig. 24: All Web Test Investigation of Failed Request<br />
Failed tests can be analyzed to determine why they failed. Drill into a<br />
failed web test and download and open Visual Studio Web Test<br />
Result File to analyze and understand why the test failed.<br />
After investigation in Visual Studio by correcting the WebTest errors,<br />
the results looks like below on the Microsoft Azure portal (Fig.25):<br />
Conclusion:<br />
With the actual Application Insights future in Visual Studio Online, we<br />
have more control on the status of our applications / Systems in terms<br />
of investigation when things goes wrong or applications / systems failed.<br />
Hassan Fadili is werkzaam als Freelance<br />
Lead Architect / Consultant en<br />
VS ALM Consultant (MVP) voor zijn<br />
eigen bedrijf FadiliCT Consultancy<br />
(http://www.fadilict-consultancy.nl).<br />
Hassan is zeer actief in de Community<br />
en mede bestuurslid van<br />
DotNed (.NET & VS ALM UG NL) en<br />
VS ALM Track Owner. Hassan<br />
houdt zijn blog op: http://hassanfad001. blogspot.com en te<br />
bereiken via: hfadili@fadilict-consultancy.nl, hassan@dotned.nl,<br />
hassanfad11 @hotmail.com en/of via Twitter op: @HassanFad<br />
14<br />
MAGAZINE
SQL<br />
Jeffrey Verheul<br />
Decrease dataflows<br />
between systems with CDC<br />
Dealing with data is becoming a bigger challenge every day, if you work with a wrongly<br />
designed system. And haven’t we all been there? One of the senior software engineers<br />
designed the system, and tested it with 10.000 records. But in the past few years, he left, and<br />
the system increased so much in size, that it’s impossible to work with it. And now a new<br />
invoice system (or a BI team for example) needs to read data from the same system. Throwing<br />
hardware at the problem isn’t an option, so what do you do next?<br />
In the past, reading data from that one core production system wasn’t<br />
an issue. The invoice processes ran at night, and the process used to<br />
finish before the first employee got in the office in the morning. But<br />
with the amounts of data currently being poured in the system, this<br />
becomes impossible. Redesigning the system takes up too much time<br />
and money, so that’s off the table. So how do you technically solve<br />
this puzzle, without rebuilding your entire architecture?<br />
What is CDC?<br />
CDC (Change Data Capture) is a feature that’s included in SQL<br />
Server Enterprise. This gives you the opportunity to capture Inserts,<br />
Updates and Deletes of records on specific objects. This can be used<br />
to perform “incremental updates” to the invoice system, instead of<br />
reading the entire content of the database at night. So how does it<br />
work?<br />
In SQL Server, every change you make to a record or table, is stored<br />
in the transaction log before your database is changed on disk. CDC<br />
reads the transaction log, and records all changes on the tables you<br />
have enabled CDC on.<br />
Enabling CDC<br />
Enabling CDC is as easy as running a query. First, let’s create some<br />
resources:<br />
/* Create a database */<br />
CREATE DATABASE CompanyInfo<br />
GO<br />
/* Use the database we just created */<br />
USE CompanyInfo<br />
GO<br />
/* Create the Customer table */<br />
CREATE TABLE dbo.Customer<br />
(CustomerID INT IDENTITY(1,1),<br />
FirstName VARCHAR(50),<br />
LastName VARCHAR(50),<br />
PhoneNumber VARCHAR(50),<br />
AccountNumber VARCHAR(50),<br />
CONSTRAINT PK_Customer PRIMARY KEY(CustomerID))<br />
GO<br />
In order to use CDC, we need to enable CDC on the database, and<br />
on the table:<br />
USE CompanyInfo<br />
GO<br />
/* Enable CDC on database */<br />
EXEC sys.sp_cdc_enable_db<br />
GO<br />
/* Enable CDC on table */<br />
EXEC sys.sp_cdc_enable_table<br />
@source_schema = 'dbo',<br />
@source_name = 'Customer',<br />
@supports_net_changes = 1,<br />
@role_name = NULL,<br />
@index_name = 'PK_Customer',<br />
@captured_column_list = 'CustomerID, FirstName, LastName,<br />
AccountNumber'<br />
GO<br />
The query above only captures changed on the “FirstName”, “Last-<br />
Name” and “AccountNumber” columns (ID needs to be included,<br />
because it’s the primary key on the table). Changes on the “Phone-<br />
Number” column aren’t interesting for the invoice system. If you do<br />
want to capture changed to that column, you can add it to the list<br />
passed into “@captured_column_list” parameter. Another option is to<br />
leave out the “@captures_column_list” parameter, so it will capture all<br />
columns in the table.<br />
After running these statements, SQL Server created a number of<br />
objects for CDC. The most important things: 2 functions you can query<br />
to get data, 2 jobs (capture and cleanup), and a “Customer_CT” table<br />
(system table), where the data changes are stored.<br />
Capture and Cleanup<br />
As long as the SQL Server Agent is running, changes are captured.<br />
The capture job, that is responsible for capturing all changes on<br />
CDC-enabled tables, runs every 5 seconds by default. This value can<br />
be changed, but I’ve never seen a reason to change this.<br />
The cleanup job is responsible for removing old data from the<br />
“Customer_CT” table. By default, old data is removed after 4320<br />
minutes (3 days). You can change this by executing this statement:<br />
magazine voor software development 15
SQL<br />
USE CompanyInfo<br />
GO<br />
/* Change the retention for cleanup */<br />
EXEC sys.sp_cdc_change_job<br />
@job_type = 'cleanup',<br />
@retention = 7200<br />
GO<br />
/* Check the result of the change */<br />
SELECT<br />
job_type,<br />
retention<br />
FROM msdb.dbo.cdc_jobs<br />
In this case the retention of the data is changed to 7200 minutes. This<br />
means that old data is deleted after 5 days. This setting gives you the<br />
opportunity to feed the invoice system with data for 5 days. This could<br />
help you if there is downtime of your system, or if you have a maintenance<br />
windows for the system every week for example. If that’s not<br />
needed, you could set it to a smaller value. How larger the value is,<br />
how longer you could query the change data, but also the more<br />
storage you need to store the change data.<br />
Querying the data<br />
Now that we’re storing the changed data, how do we query it? There<br />
are several options, all with their own pros and cons. Before we start<br />
querying the data, let’s insert and update a record in the table:<br />
USE CompanyInfo<br />
GO<br />
/* Insert a customer record */<br />
INSERT INTO dbo.Customer<br />
(FirstName, LastName, PhoneNumber, AccountNumber)<br />
VALUES<br />
('John', 'Doe', '555-6162', 'AA-5206204855882426')<br />
GO<br />
/* Update the LastName of the customer */<br />
UPDATE dbo.Customer<br />
SET LastName = 'Smith'<br />
WHERE LastName = 'Doe'<br />
GO<br />
The best practice to query the data, is to use the build-in functions.<br />
These functions (all_changes for the entire change set, or net_changes<br />
for the combined changes), all work with LSN’s (Log Sequence<br />
Numbers). An LSN uniquely identifies a record in the SQL Server<br />
transaction log. These LSN’s can be translated to a readable<br />
“datetime” datatype. Also, a “datetime” datatype can be translated in<br />
an LSN. Translating can be done with the build-in functions:<br />
/* Translate LSN to datetime */<br />
SELECT sys.fn_cdc_map_lsn_to_time(0x00000000000000000000)<br />
GO<br />
/* Translate datetime to LSN */<br />
SELECT sys.fn_cdc_map_time_to_lsn('smallest greater than or<br />
equal', '1900-01-01')<br />
GO<br />
With these functions, you can create your own “window” of data<br />
extraction. In practice this means that you can start your invoice<br />
process at 10PM, and in that window query data changed from<br />
yesterday 10PM, till today 10PM. Another option is to only query<br />
changes for a specific day, for example between 10AM and 2PM on<br />
Wednesday. The possibilities are endless, and can be fully customized<br />
to work for your system.<br />
So how does this look in the 2 different functions?<br />
As you can see, the all_changes function will return the inserted record<br />
(operation code 2), and the record after the update (operation code 4).<br />
The net_changes function, returns the combined result within the<br />
window you created. In this case, the inserted and updated record<br />
are combined within a single record.<br />
Another option you have, is to retrieve data directly from the<br />
“Customer_CT” table. This option isn’t considered a best practice, but<br />
you have the opportunity to do that if that suits you better.<br />
Design decisions<br />
If you decide to use CDC, there are some design decisions you need<br />
to take a look at. One of the first things you need to think about is<br />
storage. Data changes are captured and stored, so you need some<br />
extra storage to save these records. Another thing to think about, is<br />
the way your invoice system reads data from the primary system. If<br />
you’re going to use CDC, you might need to change the way data is<br />
retrieved. But these changes might be easier, and much safer than<br />
changing your primary system. And if you use SQL Server Integration<br />
Services (SSIS) for example, there are some standard components<br />
you could use. The changed you need to make depend on the<br />
system and architecture you have in your company.<br />
Conclusion<br />
With the options you’ve seen you can decide what works the best for<br />
your system. There are alternatives you could use, but these options<br />
all require system changes, or are more intrusive on your system than<br />
CDC. For example, you could use triggers on your tables, but those<br />
tend to slow down your system.One thing is certain: CDC reduces the<br />
amount of data that needs to be exchanged between systems, and<br />
the time needed to update secondary systems by a lot. And maybe<br />
even more important to the business, it saves you from a huge<br />
investment needed to re-design the entire system!<br />
Personally, I would say CDC isn’t the silver bullet that solves all your<br />
cross-system dataflow problems, but it is very effective when you use<br />
it the way it was intended: capture changes in a very lightweight way.<br />
The only real downside of CDC is that it’s an Enterprise-only feature.<br />
But the flexibility and compatibility (for example with SSIS and BIML)<br />
makes up for these shortcomings. CDC is definitely something to take<br />
a look at, even if you’re not a data professional! •<br />
Jeffrey Verheul<br />
Jeffrey Verheul is a DBA and database<br />
developer from the Netherlands,<br />
with over 10 years experience<br />
in the Microsoft stack. After a short<br />
side-track as a software engineer,<br />
he returned to his true love: SQL<br />
Server. His main focus is on database<br />
development, performance tuning and database administration.<br />
He is a member of the Friends of Red Gate, and blogs<br />
regularly on devjef.wordpress.com. You can contact him on his<br />
blog, or via Twitter (@DevJef).<br />
16<br />
MAGAZINE
CLOUD<br />
Marcel Meijer<br />
Azure Webjobs<br />
Tijdens de afgelopen Microsoft Techdays 2014 deed ik een sessie over Azure Cloud Services.<br />
De opname is te vinden op Channel 9. In het begin van Azure waren Cloud services de<br />
“way to go”.<br />
Cloud Servies is een krachtig concept, maar er kleefde ook de nodige<br />
nadelen aan. Bestaande applicaties konden niet zomaar via de Lift en<br />
Shift methode naar de Cloud gebracht worden. Meestal was dit<br />
gewoon te wijten aan de applicaties zelf. Weinig applicaties zijn of<br />
waren zuiver stateless, asynchroon in de basis en in staat als meerdere<br />
instanties naast elkaar te draaien.<br />
Zoals gezegd bestond het uit een WebRole en een WorkerRole.<br />
De WebRole voor het uploaden en bekijken van de plaatjes.<br />
In de afgelopen jaren is het Azure platform rijker geworden met<br />
verschillende diensten. In plaats van iets zelf te verzinnen of te<br />
kopieren van anderen, zijn er nu bestaande tools/producten opgepakt<br />
en in samenwerking geschikt gemaakt voor Azure (Hadoop, Docker,<br />
etc). Maar ook is IT development een stuk volwassener geworden.<br />
Developers en architecten realiseren zich steeds vaker dat Scale up<br />
niet helpt met availability, dat services/servers stuk gaan en dat een<br />
internet applicatie de potentie van een miljoenen publiek heeft.<br />
Standaard dogma’s als SOA architecture, Servicebussen of SOAP<br />
webservices lijken ook hun kracht te verliezen, Microservices krijgen<br />
meer draagvlak en betere tooling. Daarover ga ik zeker nog vaker<br />
bloggen.<br />
Terug naar mijn Techdays demo. Die zag er zo uit:<br />
De flow van de applicatie zag er zo uit.<br />
Zoals je ziet, de WebRole moest naast het uploaden ook een bericht<br />
op een queue zetten voor de WorkerRole. Aan de WorkerRole kant<br />
moet er een mechanisme zijn om de queue leeg te lezen. Zoals ik<br />
vertelde in mijn sessie, moet je dan ook het Busy waiting oplossen.<br />
Het lezen van de queue is een transactie en dat kost geld. Een<br />
belangrijk onderdeel van architectuur op Azure is Cost Based design.<br />
Dus wil je het lezen van bijvoorbeeld een queue zo efficiënt en<br />
effectief mogelijk houden met het oog op de kosten.<br />
Op Azure zijn tegenwoordig Webjobs beschikbaar. Met deze webjobs<br />
is het mogelijk om deze te laten triggeren na het toevoegen van een<br />
nieuwe blob op storage. Dat scheelt in mijn geval een bericht op de<br />
queue en eigen check actie van de queue. Het hele wachten en kijken<br />
of er werk (nieuwe blob op storage) is, wordt nu door het platform<br />
verzorgd en geregeld. En wat ik niet hoef te doen, dat scheelt tijd en<br />
het platform kan dat efficiënter. Dus de WorkerRole wordt vervangen<br />
door een Webjob. De WebRole heeft ook een alternatief. Moest ik voor<br />
de WebRole toch nog iets aparts leren, zoals bijvoorbeeld het lezen<br />
van de configuratie settings. Met een Azure Website kan ik de<br />
technieken gebruiken die ik altijd al gebruikte. En voor de settings zie<br />
je in mijn vorige blogpost de oplossing.<br />
Het proces plaatje ziet er dan zo uit.<br />
De solution zag er zo uit. De code is te downloaden of op te vragen.<br />
magazine voor software development 17
CLOUD<br />
En de website ziet er na een kleine redesign zo uit.<br />
De WorkerRole besloeg ongeveer het dubbele aantal regels code,<br />
waarvan het grootste gedeelte zaken die niets met het proces te<br />
maken hebben.<br />
Op deze manier krijg je precies zoals ik altijd zeg tijdens presentaties.<br />
We kunnen ons richten op de functionaliteit en het echte werk, de rest<br />
wordt overgenomen en geregeld door het Azure platform.<br />
Nu moet de Client op een andere manier genotificeerd worden en niet<br />
op een queue hoeven te kijken.<br />
NB In dit artikel beweer ik niet dat Cloud Services niet bruikbaar zijn.<br />
Voor het hier genoemde scenario waren de uitgebreide mogelijk heden<br />
van Cloud Services niet nodig. Er is op de Azure site (http:/ /azure.<br />
microsoft.com/nl-nl/documentation/articles/choose-web-site-cloudservice-vm/)<br />
een vergelijkend overzicht van de mogelijk -heden tussen<br />
de verschillende oplossingen. •<br />
En de code van de Webjob is eigenlijk alleen dit, ongeveer 55 regels.<br />
Marcel Meijer<br />
Marcel is een allround Microsoft<br />
Architect en Microsoft Cloud<br />
specialist bij Xpirit Nederland<br />
(www.xpirit.com), Marcel heeft al<br />
meerdere bedrijven geholpen met<br />
succesvolle Cloud/Microsoft Azure<br />
implementaties. Hij is voorzitter van<br />
de Software Development Network<br />
(<strong>SDN</strong>), redacteur end event organisator.<br />
Hij is ook een frequente blogger en spreker op verschillende<br />
community events en conferences in Nederland. Since 2010 mag<br />
hij zich Microsoft MVP noemen.<br />
TIP:<br />
Macro’s in Excel Werken niet meer<br />
na Office update<br />
Als je Excel 2013 macro’s bevat en deze werken niet meer na<br />
de laatste Office update. De oplossing hiervoor is, zoek het<br />
bestand MSForms.exd op. Deze staat normaal gesproken in<br />
de folder C:\Users\user.name\AppData\Local\Temp\Excel8.0\.<br />
Verwijder het bestand MSForms.exd.<br />
Bij het opnieuw opstarten van Excel 2013 wordt dit bestand<br />
opnieuw aangemaakt. Daarna werken alle VBA macro’s<br />
werken weer.<br />
20 maart<br />
<strong>SDN</strong> Event<br />
Zeist<br />
18<br />
MAGAZINE
GENERAL<br />
Sander Hoogendoorn<br />
Microservices.<br />
The good, the bad and the ugly<br />
Back in 1988, when I was first employed by a company for writing software, the world was fairly<br />
simple. The development environment we had was character-based, the database was<br />
integrated and traversed with cursors, and we built a whole new administrative system<br />
covering everything but the kitchen sink. It took us five years to complete the project, basically<br />
because the client kept changing his mind every now and then, and because every change<br />
in the code could break code elsewhere in the system. Unit testing hadn’t been invented yet,<br />
and testing was done by the end users. In production..<br />
So far for monoliths. Then in 1994 I joined a company that build<br />
desktop applications - remember the world wide web was only a<br />
couple of years old, and web applications hadn’t been invented yet.<br />
We used a great tool called PowerBuilder and now we had two<br />
components to worry about; the application on the desktop and the<br />
database on the server. The applications we build usually served<br />
departments or sometimes even a whole company. Not highly<br />
complicated, but not highly scalable either. Ah well, we had fun as long<br />
as the client-server paradigm lasted.<br />
Component based development<br />
The world got more complex in the mid-nineties. Companies wanted<br />
web applications, basically running on intranets to get rid of desktop<br />
deployments. And applications needed to serve multiple departments,<br />
and sometimes even break company borders. A new paradigm set<br />
in: component based development, also known as CBD. The<br />
paradigm promised us re-use, scalability, flexibility and a way to<br />
harvest existing code (usually written in COBOL). We started breaking<br />
up our systems into big functional chunks, and tried hard to have those<br />
components communicate to each other. Java was invented and<br />
everybody now wanted to write code in Java (apparently some<br />
people still to this nowadays). Components where running in<br />
impossible technologies such as application servers and CORBA (to<br />
impress your co-workers, look that one up on Wikipedia). The good<br />
old days of object request brokers!<br />
At that time I was working for a large international bank trying to set<br />
up an methodology for doing component based development. Even<br />
with a heavily armed team of Anderson consultants it took us three<br />
years to write the damn thing. In the end both the paradigm and the<br />
technology where too complex to write decent and well-performing<br />
software. It just never took off.<br />
Service oriented architecture<br />
At that point in time, the early years of this century, I thought we got<br />
rid of distributed software development, and happily started building<br />
web applications. I guess everyone bravely ignored Martin Fowler’s<br />
first law of distributed objects: do not distribute your objects.<br />
Gradually we moved into the next paradigm of distributed computing,<br />
re-packaging the promises of component based development into a<br />
renewed set of technologies. We now started doing business process<br />
modeling (BPM), and implemented these processes in enterprise<br />
services buses (ESB’s), with components delivering services.<br />
Fig. 1: Scary stuff, an object request broker architecture<br />
Fig. 2: An enterprise service bus<br />
magazine voor software development 19
GENERAL<br />
We were in the age of service oriented architecture, better known as<br />
SOA.<br />
Coming from CBD, SOA seemed easier. As long as your components<br />
- the producers - were hooked into the enterprise service bus, we<br />
figured out how to build-up scalable and flexible systems. We now<br />
had much smaller components that we could actually extract from our<br />
existing systems (now not only written in COBOL, but also in<br />
PowerBuilder, .NET and Java). The mandatory design patterns books<br />
where published and the world was ready to go. This time we would<br />
crack it!<br />
I found myself working for an international transport company, and we<br />
happily build around SAP middleware – delivering both ESB and BPM<br />
tooling. We now not only needed regular Java and .NET developers,<br />
but we employed middleware developers and SAP consultants as<br />
well. And although agile was introduced to speed up development<br />
(I know, this is not the right argument), projects still suffered from<br />
sluggishness and moreover, when we got pieces of the puzzle in place,<br />
we started to realize that integration testing and deployment of new<br />
releases got more complicated by the day.<br />
At last: microservices!<br />
I do hope you forgive me this long and winding introduction to the<br />
actual topic: microservices. You might think: why do we need yet<br />
another article on microservices? Isn’t there enough literature already<br />
on the topic. Well yes there is. But if you look closely to the flood of<br />
articles that you find on the internet, most of them only describe the<br />
benefits and possibilities of microservices (sing hallelujah), some of<br />
them take a look at the few famous path finding examples (Netflix,<br />
Amazon, and Netflix, and Amazon, and Netflix…). Only a few articles<br />
actually dig a bit deeper, and they usually consist of summing up the<br />
technologies people seem to be using when implementing<br />
microservices. It’s still early in the game.<br />
That’s were a little historical perspective won’t hurt. I find it interesting<br />
to witness that the benefits and possibilities of the predecessors of<br />
microservices are still with us. Microservices seem to promise<br />
scalable and flexible systems, based on small components that can<br />
easily be deployed independently, and thus promote use of the best<br />
choice in technologies per component. Basically the same promises<br />
we fell for with CBD and SOA in the past. Nothing new here, but that<br />
doesn’t mean that microservices aren’t worthwhile investigating.<br />
Is it different this time around?<br />
So why is it different this time? What will make microservices the<br />
winning paradigm, where its predecessors clearly were not? What<br />
makes it tick? As a developer, there’s no doubt that I am rather<br />
enthusiastic about microservices, but I was enthusiastic as well (more<br />
or less) when people came up with CBD and SOA.<br />
I do suppose there are differences. For the first time we seem to have<br />
the technology in place to build these type of architectures. All the<br />
fancy and complex middleware is gone, and we rely solely on very<br />
basic and long-time existing web protocols and technologies. Just<br />
compare REST to CORBA. Also we seem to understand deployment<br />
much better, due to the fact that we’ve learned how to do continuous<br />
integration, unit testing, and even continuous delivery. These differences<br />
suggest that we can get it to work this time around.<br />
Still, from my historical viewpoint some skepticism is unavoidable. Ten<br />
years ago, we also really believed that service oriented architecture<br />
would be technologically possible, it would solve all our issues, and we<br />
would be able to build stuff faster, reusable and more reliable. So, to<br />
be honest, the fact that we believe that the technology is ready, is not<br />
much of an argument. Meanwhile the world also got more complex.<br />
Over the last year I’ve been involved with a company that is moving<br />
away from their mainframe (too expensive) and a number of older Java<br />
monoliths (too big, and hard to maintain). Also time-to-market plays an<br />
important role. IT need to support introducing a new product in<br />
months, if not in weeks. So we decided to be hip and go micro -<br />
services. Here’s my recap of the good, the bad and the ugly of<br />
microservice architectures, looking back on our first year on the road.<br />
The good<br />
Let’s start with the good parts. We build small components, each<br />
offering about two to six services. Good examples of such small<br />
components are a PDF component, that does nothing more than<br />
generate PDF’s from a template with some data, or a Customer<br />
component that allows users to search for existing customers. These<br />
components offer the right size. The right size of code, he right size of<br />
understandability, to right size to document, to test an to deploy.<br />
The good<br />
Our team tend to evolve towards small teams designing, implementing<br />
and supporting individual components. We didn’t enforce ownership,<br />
but over time small teams are picking up the work on a specific<br />
component and start feeling responsible for it.<br />
When we outlined the basic architecture for our microservices landscape<br />
we set a number of guidelines. We are not only building small<br />
components, but are also building small single-purpose web applications.<br />
Applications can talk to other applications, and can talk to<br />
components. Components handle their own persistence and storage,<br />
and can also talk to other components. Applications do not talk<br />
directly to storage. Components do not talk to each others storage.<br />
For us these guidelines work.<br />
Microservices lives up to some of its promises. You can pick the right<br />
technology and persistence mechanisms for each of you components.<br />
Some components persist to relational databases (DB2 or SQLServer),<br />
others persist to document databases (MongoDB in our case).<br />
The hipster term here of course is polyglot persistence.<br />
We also stated that every application and component has it’s own<br />
domain model. We employ the principles and patterns of domain<br />
driven design straightforward. We have domain objects, value objects,<br />
aggregates, repositories and factories. Because our components are<br />
small, the domain models are fairly uncomplicated, and thus<br />
maintainable.<br />
Although we have had quite a journey towards testing our<br />
components and services, from Fitnesse to hand-written tests, we are<br />
now moving towards testers specifying tests in SoapUI, which we are<br />
running both as separate tests and during builds. We had to learn to<br />
understand REST, but we’ve got this one figured out for now.<br />
Andtesters love it.<br />
20<br />
MAGAZINE
GENERAL<br />
When we started our microservices journey, the team I’m was in a<br />
highly reactive mode – tell us what to program and how to program it,<br />
and we’ll do our job. I probably won’t have explain what that does<br />
with the motivation of the team members. However, with micro services<br />
there is no such thing as a ready-to-use cookbook or a predefined<br />
architecture. It simply doesn’t exist. That means that we continuous<br />
find ourselves solving new pieces of the microservices puzzle, from<br />
discovering how to design microservices (we use smart use case), to<br />
how implement REST interfaces, how to work with a whole new set<br />
of frameworks, and a brand new way of deploying components. It’s<br />
this puzzle that make working on this architecture interesting. We allow<br />
ourselves to learn everyday.<br />
The bad<br />
But as always, there’s a downside. When you start going down the<br />
microservices road – for whatever you may find it beneficial - you need<br />
to realize that this is all brand new. Just think of it: if you’re not working<br />
for Netflix or Amazon, who do you know who actually already<br />
does this already? Who has actively deployed services into production,<br />
with a full load? Who can you ask?<br />
The bad<br />
You need to be aware that you really need to dig in and get your hands<br />
dirty. You will have to do a lot of research yourself. There are no<br />
standards yet. You will realize that any choices you now make in<br />
techniques, protocols, frameworks, and tools is probably temporarily.<br />
When you are learning on a daily basis, newer and better options<br />
become available or necessary, and your choices will alter. So if you’re<br />
looking for a ready-made IKEA construction kit for implementing<br />
microservices the right way, you might want to stay away from<br />
microservices for the next five to seven years. Just wait for the big<br />
vendors, they will jump in soon enough, as there’s money to make.<br />
From a design perspective you will have to start to think differently.<br />
Designing small components is not as easy as it appears. What makes<br />
a good size component? Yes, it has a single business purpose,<br />
undoubtedly, but how do you define the boundaries of your<br />
component? When do you decide to split a working, operational<br />
component into two or more separate components? We’ve come<br />
across a number of these challenges over the past year. Although we<br />
have split up existing components, there are no hard rules on when to<br />
actually do this. We decided mainly based on gut feeling, usually when<br />
we didn’t understand a components structure anymore, or when we<br />
realized it was implementing multiple business functions. It gets even<br />
harder when you are chipping off components from large systems.<br />
There’s usually a lot of wiring to cut, and in the meantime you will need<br />
to guarantee that the system doesn’t break. Also, you will need a fair<br />
amount of domain knowledge to componentize your existing systems.<br />
Basically we found that components are not as stable as we first<br />
thought. Occasionally we merge components, but it appeared far<br />
more common to break components into smaller ones to provide<br />
reuse and shorter time-to-market. As an example, we pulled out a<br />
Q&A component from ourProduct component that now supplies<br />
questionnaires for other purposes than just about products. And more<br />
recently we created a new component that only deals with validating<br />
and storing filled-in questionnaires.<br />
There’s lots of technical questions you will need to answer too. What’s<br />
the architecture of a component? Is an application a component as<br />
well? Or, a less visible one, if you are thinking of using REST as your<br />
communication protocol – and you probably are – is: how does REST<br />
actually work? What does it mean that a service interface is RESTful?<br />
What return codes do you use when? How do we implement error<br />
handling in consumers if something isn’t handled as intended by one<br />
of our services? REST is not as easy as it appears. You will need to<br />
invest a lot of time and effort to find out your preferred way of dealing<br />
with your service interfaces. We figured out that to make sure that<br />
services are more or less called in a uniform way, we’d better create<br />
a small framework that does the requests, and also that deals with<br />
responses and errors. This way communication is handled similar with<br />
every request, and if we need to change the underlying protocol or<br />
framework (JAX-RS in our case), we only need to change it in one<br />
location.<br />
That automatically brings me to the next issue. Yes, microservices<br />
deliver on the promise that you can find the best technology for every<br />
components. We recognize that in our projects. Some of our<br />
components are using Hibernate to persist, some are using a<br />
MongoDB connector, some rely on additional frameworks, such as<br />
Dozer for mapping stuff, or use some PDF-generating framework. But<br />
with additional frameworks comes the need for additional knowledge.<br />
At this company, we will easily grow to over a hundred small<br />
components and maybe even more. If even only a quarter of these<br />
use some specific framework, we will end up with twenty-five to thirty<br />
different frameworks( did I mention we do Java?). We will need to<br />
know about all of these. And even worse, all of these frameworks<br />
(unless they’re dead) version too.<br />
Then there’s the need to standardize some of the code you are writing.<br />
Freedom of technology is all good, but if every component is literally<br />
implemented differently, you will end up with an almost unmaintainable<br />
code base, especially since it is likely that no-one oversees all the<br />
code that is being written. I strongly suggest to make sure there’s<br />
coherence over your components on aspects of your code base that<br />
you could and probably should unify. Think of your UI components<br />
(grids, buttons, pop-ups, error boxes), validation (of domain models),<br />
talking to databases or how responses from services are formulated.<br />
Also, although I strongly oppose having a shared domain model<br />
(please don’t go that route), there’s elements in your domain models<br />
you might need to share. We share a number of enumerations and<br />
value objects for instance, such as CustomerId orIBAN.<br />
If you’re a bit like us this generic code ends up in a set of libraries<br />
- a framework if you will – that is reused by your components. We have<br />
learned that with every new release of this home-grown framework<br />
we end up refactoring some of the code of our components. I rewrote<br />
the interface of our validation framework last week, which was<br />
necessary to get rid of some state it kept - components need to be<br />
stateless for clear reasons of scalability - and I’m a bit reluctant to<br />
merge it back into the trunk when I get back to work after the<br />
weekend. Most of our components use it, and their code might not<br />
compile. I guess what I’m saying here is that it’s good to have a<br />
home-grown framework. With some discipline it will help keep your<br />
magazine voor software development 21
GENERAL<br />
code somewhat cleaner and a tad more uniform, but you will have to<br />
reason about committing to it and releasing new versions of it.<br />
The ugly<br />
So what about the really nasty parts of microservices? Let’s start with<br />
deployment pipelines. One of the promises of microservices is that<br />
they can and should be individually deployed and released. If you are<br />
currently used to having a single build and deployment pipeline for the<br />
one system you are building or extending, you might be in for a treat.<br />
With microservices you are creating individual pipelines for individual<br />
components.<br />
The hockey stick model<br />
Early in the game? Yes, we’ve only been on the road to microservices<br />
for about a year. And I still haven’t figured out whether we are on a<br />
stairway to heaven or on a highway to hell. I do suppose, as with it’s<br />
historical predecessors, we will end up somewhere in the middle,<br />
although I really do believe that we do have the technology to get this<br />
paradigm working – and with we I don’t just mean Netflix, Amazon or<br />
some hipster mobile company, but the regular mid-size companies<br />
you and I work for.<br />
But will it be worthwhile? Shorten time-to-market? Deliver all the<br />
goodies the paradigm promises us? To be honest, I don’t know yet -<br />
despite or maybe even because of all the hype surrounding microservices.<br />
What I did notice is that, given the complexity of everything<br />
surrounding microservices, it takes quite a while before you get your<br />
first services up and running, and we are only just passing this point.<br />
Some weeks ago, I was having a beer with Sam Newman, author of<br />
Building Microservices. Sam confirmed my observations from his own<br />
examples and referred to this pattern as the hockey stick model.<br />
The ugly<br />
Releasing the first version of a component is not that hard. We<br />
started with a simple Jenkins pipeline, but are currently investigating<br />
TeamCity. We have four different environments. One for development,<br />
one for testing, one for acceptance and of course the production<br />
environment. Now we are slowly getting in the process of releasing<br />
our components, most of them with their own database, we start to<br />
realize that we can not do this without the support and collaboration<br />
of the operations team. Our expectations are that we will slowly evolve<br />
into a continuous delivery mode, with operations incorporated in the<br />
team. Right now we already have enough trouble getting operations<br />
on-board. They are now used to quarterly releases of the whole<br />
landscape, and certainly have no wish for individually deploying<br />
components.<br />
Another that worries me is versioning. If it is already hard enough to<br />
version a few collaborating applications, what about a hundred<br />
applications and components each relying on a bunch of other ones<br />
for delivering the required services? Of course, your services are all<br />
independent, as the microservices paradigm promises. But it’s only<br />
together that your services become the system. How do you avoid to<br />
turn your pretty microservices architecture into versioning hell - which<br />
seems a direct descendant of DLL hell?<br />
To be honest, at this point in time, I couldn’t advice you well on this<br />
topic, but a fair warning is probably wise. We started out with a<br />
simple three digit numbering scheme (such as 1.2.5). The rightmost<br />
number changes when minor bugs have been solved. The number in<br />
the middle raises when minor additional functionality has been added<br />
to a component, and the leftmost number changes when we deploy<br />
a new version of a component with breaking changes to its interface.<br />
Not that we strongly promote regularly changing interfaces, but it does<br />
happen.<br />
Next to that, we test our services during the build, both using coded<br />
tests and tests we assemble in SoapUI. And we document the<br />
requirements in smart use cases and domain models of our<br />
applications and components using UML. I’m quite sure in the future<br />
we need to take more precautions to keep our landscape sane, such<br />
as adding Swagger to document our coded services, but it’s still to<br />
early in the game to tell.<br />
There’s a lot to take care of before you are ready to release you first<br />
service. Think of infrastructure, sorting out how to do REST properly,<br />
setting up you deployment pipelines, and foremost change the way<br />
you think about developing software. But as soon as the first service<br />
is up and running, more and more follow faster and faster.<br />
Be patient<br />
So, if there’s one thing I’ve learned over the past year, it is to be<br />
patient – a word which definitively did not appear in my dictionary yet.<br />
Don’t try to enforce all kinds of (company) standards if they just don’t<br />
exist yet. Figure it out on the fly. Allow yourself to learn. Take it step by<br />
step. Simply try to do stuff a little bit better than the day before. And<br />
as always, have fun! •<br />
Sander Hoogendoorn<br />
Sander is an independent consultant;<br />
as a mentor, trainer, coach,<br />
software architect, developer, writer,<br />
speaker, for his company<br />
ditisagile.nl (after the Dutch title of<br />
my latest book This Is Agile).<br />
Over the past decade, in my roles<br />
as Principal Technology Officer and<br />
Global Agile Thoughtleader at<br />
Capgemini. During this period I’ve learned a great deal and have<br />
contributed to the innovation of software development at<br />
Capgemini and its many international clients.<br />
22<br />
MAGAZINE
GENERAL<br />
Patrick Kalkman<br />
Improving traceability<br />
of distributed systems<br />
using the ELK stack<br />
With all IT systems, traceability is an important non-functional requirement. If the traceability of<br />
a system is high, it is easier to find the root cause of a problem that occurs in a production<br />
environment. As a system gets distributed over multiple applications or services, tracing a<br />
problem in a production environment becomes more difficult. As there are simply more application<br />
and services to check. New architectures such as a microservices architecture makes this<br />
even more difficult because the functionality of the system can literally be distributed over<br />
dozens or hundreds of services. The services could be implemented using different development<br />
languages and be running on different platforms. This article describes a solution for increasing<br />
the traceability of a distributed system by using Log aggregation via the ELK stack.<br />
Tracing using the Elk stack<br />
Most distributed systems consist of different types of applications<br />
implemented using different programming language running on<br />
different operating systems. Normally these systems grow organically<br />
over time. There is not a single standard way of logging when a<br />
service or application fails.<br />
Elasticsearch uses Java and Kibana is implemented using HTML, CSS<br />
and JavaScript. Although these three products work great together,<br />
they can also be used separately.<br />
Fig. 1: Microservices architecture<br />
The most common way to log error events is writing these events in<br />
log files. Each row of these text files minimally contain a timestamp<br />
and some data about the event. With a distributed system such as a<br />
microservices architecture this could mean that an engineer has to go<br />
through hundreds of log files to find a problem.<br />
The ELK stack provides a solution for this problem by aggregating all<br />
of these log files into a single system. The ELK stack combines the<br />
Elasticsearch, Logstash and Kibana products. Elasticsearch is a<br />
search and analytics engine, Logstash is a tool for scrubbing and<br />
parsing log data into a single format and Kibana is a visualization<br />
engine to interact with Elasticsearch.<br />
The logs of a system are transported through and enhanced by<br />
Logstash. The data is then indexed and stored by Elasticsearch and<br />
finally visualized using the Kibana dashboard. All the components of<br />
the ELK stack are open source. Logstash is implemented using JRuby,<br />
Fig. 2: ELK stack overview<br />
After the ELK stack is installed and configured you are able to search<br />
in real-time through the logs of all your applications and services. Using<br />
Kibana you are able to visualize trends and spot anomalies in your log<br />
files.<br />
There is not a single standard way<br />
of logging when a service or<br />
application fails<br />
Installing the ELK stack<br />
The ELK stack can be installed on Unix as well as Windows. For this<br />
article, I will be installing the ELK stack on a single Ubuntu server.<br />
The Ubuntu server will be running as a VM on the Microsoft Azure<br />
platform. The version of Ubuntu that I will be using is 14.04 LTS.<br />
magazine voor software development 23
GENERAL<br />
The installation of all components is done through a remote shell, using<br />
putty as an ssh client.<br />
Installing Elasticsearch<br />
As Elasticsearch runs on top of Java, the first prerequisite we have to<br />
fulfill before we can install Elasticsearch is Java. We install Java by<br />
entering the following command on the command line.<br />
$ sudo apt-get install openjdk-7-jre-headless<br />
The name of the Elasticsearch node is automatically generated, so it<br />
will probably be different in your installation.<br />
We now have the E of the ELK stack running. Next, we will install<br />
Logstash.<br />
Installing Logstash<br />
Before we can install Logstash we first have to download the Logstash<br />
package. We download Logstash with the following command.<br />
This will download and install Java version 1.7. To validate if Java was<br />
installed correctly we enter the following command.<br />
$ wget https://download.elasticsearch.org/logstash/logstash/packages/debian/logstash_1.4.2-1-2c0f5a1_all.deb<br />
$ java –version<br />
If Java was installed correctly the following response will be generated<br />
(the version number may differ)<br />
And install it by entering the following command<br />
$ sudo dpkg -i logstash_1.4.2-1-2c0f5a1_all.deb<br />
java version "1.7.0_65"<br />
OpenJDK Runtime Environment (IcedTea 2.5.3) (7u71-2.5.3-<br />
0ubuntu0.14.04.1)<br />
OpenJDK 64-Bit Server VM (build 24.65-b04, mixed mode)<br />
To install Elasticsearch we first have to download the package.<br />
We download Elasticsearch with the following command.<br />
$ wget https://download.elasticsearch.org/elasticsearch/<br />
elasticsearch/elasticsearch-1.4.1.deb<br />
There is an additional package with community added contributions<br />
for Logstash that we need. We download this package with the<br />
following command.<br />
$ wget https://download.elasticsearch.org/logstash/log-<br />
stash/packages/debian/logstash-contrib_1.4.2-1-<br />
efd53ef_all.deb<br />
And install it using this command.<br />
$ sudo dpkg –i logstash-contrib_1.4.2-1-efd53ef_all<br />
When downloaded we can install Elasticsearch with the following<br />
command.<br />
$ sudo dpkg -i elasticsearch-1.4.1.deb<br />
We then issue the following command to start Logstash<br />
$ sudo service logstash start<br />
And start it with the following command<br />
$ sudo service elasticsearch start<br />
We can validate if Elasticsearch was installed and is running correctly<br />
by entering the following command.<br />
$ curl http://localhost:9200<br />
Elasticsearch should give a JSON response that looks like the<br />
following<br />
{<br />
"status" : 200,<br />
"name" : "Ultron",<br />
"cluster_name" : "elasticsearch",<br />
"version" : {<br />
"number" : "1.4.1",<br />
"build_hash" :<br />
"89d3241d670db65f994242c8e8383b169779e2d4",<br />
"build_timestamp" : "2014-11-26T15:49:29Z",<br />
"build_snapshot" : false,<br />
"lucene_version" : "4.10.2"<br />
},<br />
"tagline" : "You Know, for Search"<br />
}<br />
This concludes the installation of the L part of the ELK stack. We move<br />
to the last part, installing Kibana, the front-end.<br />
Kibana is implemented using HTML,<br />
CSS and JavaScript<br />
Installing Kibana<br />
Kibana is implemented using HTML, CSS and JavaScript. Therefore,<br />
to run Kibana we need a web server. Kibana runs completely clientside<br />
in the browser, so we don’t have any server side dependencies.<br />
If the web server can serve HMTL you will be ok. I will be using nginx.<br />
To install nginx enter the following command<br />
$ sudo apt-get install nginx<br />
The installation process will automatically start nginx. To validate if<br />
nginx is installed correctly and running issue the following command.<br />
$ curl http://localhost<br />
nginx should respond as follows<br />
24<br />
MAGAZINE
GENERAL<br />
<br />
<br />
<br />
Welcome to nginx!<br />
<br />
…<br />
We download and extract Kibana by entering the following command<br />
$ curl https://download.elasticsearch.org/kibana/kibana/kibana-3.1.2.tar.gz<br />
| tar xvz<br />
Configuring Logstash<br />
The community maintaining Logstash has an interesting project<br />
principle. They say that if a newbie has a bad time using Logstash it’s<br />
probably a bug. The documentation should have be better and more<br />
instructive.<br />
If a newbie has a bad time,<br />
it's a bug<br />
Logstash is configured using a configuration file. A Logstash<br />
configuration file has the following structure.<br />
We then have to copy the Kibana folder to the nginx html folder by<br />
entering the following command.<br />
$ sudo cp kibana-3.1.2/* /usr/share/nginx/html –R<br />
To validate if Kibana is working correctly we have to open two<br />
additional endpoints on the virtual machine running on Microsoft<br />
Azure. One endpoint for port 80 to be able to talk to the web server<br />
and another endpoint for port 9200 to let Kibana talk to Elasticsearch.<br />
The Logstash configuration file describes how events should flow<br />
through the Logstash pipeline with an input, filter and an output stage.<br />
Input specifies the source of the data. This could be a file, a TCP port<br />
or other input plugins that are available.<br />
Filter defines how the input stream should be parsed.<br />
Output defines where the parsed output should be sent and stored.<br />
Each part of the pipeline can be configured using the logstash<br />
configuration file. The configuration file resembles the structure of the<br />
pipeline.<br />
input {<br />
}<br />
filter {<br />
}<br />
output {<br />
}<br />
Fig. 3: Azure Endpoints<br />
When you now browse to your webserver you should be welcomed by<br />
the Kibana start screen.<br />
Logstash contains several plugins that can be configured in each part<br />
of the pipeline. The list is too extensive to list here, but these are some<br />
examples.<br />
• Input plugins (log4j, collectd, eventlog, tcp, wmi, udp, heroku, file)<br />
• Filter plugins (grok, json, split, translate, drop)<br />
• Output plugins (elasticsearch, agios, http, stdout, rabbitmq,<br />
websocket, tcp)<br />
See the Logstash website (http://logstash.net/) for a complete list of<br />
available plugins.<br />
The first real configuration we create is for parsing and indexing logs<br />
from an IIS server. We choose an IIS log because it contains a lot of<br />
different tokens we have to configure in the configuration file. Note<br />
that this could be any log file.<br />
The Logstash configuration file should be stored on our Ubuntu<br />
server in /etc/logstash/conf.d/logstash.conf<br />
Fig. 4: Kibana welcome screen<br />
Congratulations, you have just installed all parts of the ELK stack.<br />
Next, we will look at configuring Logstash to get events into the<br />
system.<br />
Fig. 5: Logstash configuration file structure<br />
input {<br />
lumberjack {<br />
port => 6379<br />
type => "IISLogs"<br />
ssl_certificate => "/home/azureuser/logstash.crt"<br />
ssl_key => "/home/azureuser/logstash.key"<br />
}<br />
}<br />
filter {<br />
if [type] == "IISLogs" {<br />
if [message] =~ "^#" {<br />
drop {}<br />
}<br />
grok {<br />
magazine voor software development 25
GENERAL<br />
match => ["message",<br />
"%{TIMESTAMP_ISO8601:log_timestamp}<br />
%{IPORHOST:site}<br />
%{WORD:method}<br />
%{URIPATH:page}<br />
%{NOTSPACE:querystring}<br />
%{NUMBER:port}<br />
%{NOTSPACE:username}<br />
%{IPORHOST:clienthost}<br />
%{NOTSPACE:useragent}<br />
%{NUMBER:response}<br />
%{NUMBER:subresponse}<br />
%{NUMBER:scstatus}<br />
%{NUMBER:time_taken}"]<br />
}<br />
date {<br />
match => [ "log_timestamp", "YYYY-MM-dd HH:mm:ss" ]<br />
timezone => "Etc/UCT"<br />
}<br />
useragent {<br />
source => "useragent"<br />
prefix => "browser"<br />
}<br />
mutate {<br />
remove_field => [ "log_timestamp"]<br />
}<br />
}<br />
}<br />
output {<br />
elasticsearch {<br />
}<br />
}<br />
Filter<br />
The filter actually tries to parse the data of the event. The first line of<br />
the filter contains a condition which checks the type of the event.<br />
if [type] == "IISLogs" {<br />
This means that the lines following this condition will only be executed<br />
if the type of the event equals “IISLogs”. As you remember we added<br />
this type to events that are input using the lumberjack input plugin.<br />
The next line states that events that start with a hash should be<br />
ignored.<br />
if [message] =~ "^#" { drop {} }<br />
Lines in an IIS log file that start with a hash indicate a comment. These<br />
are normally only present in the header of the IIS logfile.<br />
The next part uses the Logstash GROK plugin. GROK is a wrapper<br />
around a regular expression engine which enables you to reuse<br />
existing regex patterns. It is the ideal solution for parsing custom log<br />
messages and comes with 120 existing patterns.<br />
Using GROK we are going to parse a IIS log event. A log line of a IIS<br />
log event looks like the following:<br />
2014-12-08 00:00:17 172.16.12.172 POST /url1/api.asmx - 443<br />
VODKIJKWIN 192.168.16.135 PHP-SOAP/5.3.28-1~dotdeb.0 200 0 0<br />
343<br />
I will describe each part of the configuration file, starting with the input.<br />
Input<br />
The input plugin I am using is called lumberjack which is a specific<br />
input plugin specially created for securely receiving events from<br />
Logstash-forwarder. Logstash-forwarder is a type of application runs<br />
on your server and sends log events to the log server. Logstashforwarder<br />
is an application that consume low resources.<br />
The Logstash-forwarders motto:<br />
I'm a lumberjack and I'm ok!<br />
I sleep when idle, then I ship logs<br />
all day! I parse your logs, I eat the<br />
JVM agent for lunch!<br />
The lumberjack input plugin has several configuration fields which<br />
define on what port and which certificate is used to setup an<br />
encrypted connection. We are using port 6379 for the lumberjack<br />
input. To be able to send the log events securely to the server we need<br />
a certificate. This can be a self-signed certificate or a real certificate.<br />
I will show later how to create this certificate.<br />
The type fields adds a new field called ‘type’ to each event. The value<br />
of this field when events are retrieved by lumberjack is “IISlogs”. Types<br />
are mainly used for filter activation, we can specify that a certain filter<br />
should only be used for events that have type=”IISLogs”, which we<br />
will describe next.<br />
The grok match parameter specifies the pattern to parse this line.<br />
grok {<br />
match => ["message",<br />
"%{TIMESTAMP_ISO8601:log_timestamp}<br />
%{IPORHOST:site}<br />
%{WORD:method}<br />
%{URIPATH:page}<br />
%{NOTSPACE:querystring}<br />
%{NUMBER:port}<br />
%{NOTSPACE:username}<br />
%{IPORHOST:clienthost}<br />
%{NOTSPACE:useragent}<br />
%{NUMBER:response}<br />
%{NUMBER:subresponse}<br />
%{NUMBER:scstatus}<br />
%{NUMBER:time_taken}"]<br />
}<br />
Note, that for readability the grok pattern has been split on to multiple<br />
lines. The actual grok match line should be on a single line.<br />
It starts by reusing an existing pattern in grok called TIMESTAMP_<br />
ISO8601 which parses the date and time from the event and stores it<br />
into the field log_timestamp and ends with NUMBER which is stored<br />
into the time_taken field. An online tool is available http://grok<br />
debug.herokuapp.com/ for testing grok patterns.<br />
After the GROK stage of the filter we have parsed the IIS log line into<br />
several specific fields.<br />
26<br />
MAGAZINE
GENERAL<br />
The filter continues with using the date plugin. The date plugin is able<br />
to convert a field into a date time and use that date time as the<br />
timestamp of this specific event.<br />
No other fields are specified as we are running Elasticsearch on the<br />
same machine as Logstash. Otherwise we could have specified, for<br />
example the host and port.<br />
date {<br />
match => [ "log_timestamp", "YYYY-MM-dd HH:mm:ss" ]<br />
timezone => "Etc/UTC"<br />
}<br />
Restart Logstash<br />
We have to restart Logstash after we have added or changed the<br />
Logstash configuration file. We restart Logstash with the following<br />
command.<br />
If no time zone is specified it adds a default time zone of “Etc/UTC” to<br />
the event.<br />
$ sudo service logstash restart<br />
The user agent plugin parses user agentstring into structured data.<br />
It uses BrowserScope data to add information like family, operating<br />
system, version and device. Browserscope is an open-source project<br />
for profiling web browsers and storing and aggregating crowd-sourced<br />
data about browser performance.<br />
useragent {<br />
source => "useragent"<br />
prefix => "browser"<br />
}<br />
The prefix field specifies to add “browser” to all of the extracted fields.<br />
The last part of the filter shows the mutate plugin which enables you<br />
to mutate fields. You can remove, rename, replace or modify fields in<br />
events.<br />
mutate {<br />
remove_field => [ "log_timestamp"]<br />
}<br />
Here we remove the log_timestamp field because we don’t need it<br />
anymore as it already converted into a timestamp.<br />
As the log event is now parsed and has a timestamp it is time to move<br />
it to the output.<br />
Output<br />
In the output we specify a single output plugin. The elasticsearch<br />
plugin is obviously used for sending the event to Elasticsearch.<br />
output {<br />
elasticsearch {<br />
}<br />
}<br />
This concludes installing and configuring our ELK stack using a single<br />
server. The final part to getting log events into the server is adding and<br />
configuring a shipper on the server that contains the logs of the<br />
application that we want to monitor.<br />
Sending events to Logstash<br />
We first have to send the events to Logstash before we can parse,<br />
index and search through them. There are several so called shippers<br />
which are responsible for transmitting events to Logstash.<br />
There are several shippers available that move events to Logstash.<br />
Logstash itself can also be used as a shipper. As Logstash runs with<br />
a footprint that is not friendly to under provisioned systems, several<br />
alternatives were created that have a smaller footprint, for example, the<br />
earlier mentioned Logstash-forwarder. Other alternatives are Beaver<br />
(written in Python) and Woodchuck (written in Ruby).<br />
I will be using Logstash-forwarder as I develop a lot of software that<br />
has to run on Windows. Logstash-forwarder is developed in Go and<br />
as such can be compiled and run on Windows.<br />
Currently there is no binary distribution of Logstash-forwarder, therefore<br />
to use it you have to compile it first. Instructions can be found at<br />
https://github.com/elasticsearch/logstash-forwarder.<br />
As you may recall the input filter of Logstash used the lumberjack<br />
plugin to receive events from the logstash-forwarder.<br />
input {<br />
lumberjack {<br />
port => 6379<br />
type => "IISLogs"<br />
ssl_certificate => "/home/azureuser/logstash.crt"<br />
ssl_key => "/home/azureuser/logstash.key"<br />
}<br />
}<br />
We are using port 6379 for the lumberjack input. To be able to send<br />
the log events securely to the server we need a certificate. This can be<br />
a self-signed certificate or a real certificate. I will be generating and<br />
using a self-signed certificate.<br />
I used the openssl command line to generate the self-signed certificate<br />
on the Ubuntu server. We generate a private key and certificate with<br />
the following command.<br />
$ openssl req -x509 -nodes -days 365 -newkey rsa:4096 -keyout<br />
logstash.key -out logstash.crt<br />
Fig. 6: Shippers move events to Logstash<br />
The self-signed certificate needs several types of information to put<br />
into the certificate. The only thing that is important is the Common<br />
Name, this must be set to the fully qualified domain name of the<br />
logstash server.<br />
magazine voor software development 27
GENERAL<br />
After the self-signed certificate is created, you have to copy the<br />
logstash.key and the logstash.crt files from the Unbuntu server to the<br />
folder on the machine that contains the logstash-forwarder.<br />
Creating the logstash-forwarder configuration file<br />
Before we can start the logstash-forwarder we have to create a<br />
configuration file that instructs the forwarder where to get the log event<br />
from and where to send them. Below a configuration file called<br />
logstash-forwarder.conf I use on a machine to send IIS logs to my<br />
central logstash server.<br />
{<br />
"network": {<br />
"servers": [ "elkstack.cloudapp.net:6379" ],<br />
"ssl ca": "Logstash.crt"<br />
},<br />
"files": [<br />
{<br />
"paths": [ " C:\\inetpub\\logs\\LogFiles\\W3SVC1\\*.log"<br />
],<br />
"type": ["IISLogs"]<br />
}<br />
]<br />
}<br />
The logstash-forwarder will monitor the folder for new or added<br />
logfiles and will send them to the logstash server. To run logstashforwarder<br />
in the background as a Windows service, we have to convert<br />
it into a Windows service. This can be done using NSSM (the<br />
Non-Sucking Service Manager) from http://nssm.cc/<br />
Filtering events using Kibana<br />
After we got the event flowing into the server, we can visualize the<br />
events using Kibana. With Kibana you can create and save custom<br />
dashboards. The default installation already contains a dashboard<br />
which is configured for Logstash as can be seen in Figure 8.<br />
The default Logstash dashboard contains a graph which counts the<br />
number of events over time and includes a search field which allows<br />
you to search on free text or search in specific fields.<br />
The functionality of Kibana deserves a separate article on its own.<br />
There are multiple ways to create graphs, combine geo-ip data and<br />
filters.<br />
It specifies under network which certificate to use and to what server<br />
the logs should be sent The files parameter specifies which paths and<br />
pattern should be used to search the log files. Pay special interest to<br />
using the double backslash on Windows as a folder separator. Before<br />
starting the logstash forwarder I have to add another end point to my<br />
Azure virtual machine to let Logstash connect to port 6379.<br />
Fig. 9: Kibana extended dashboard<br />
Scaling the ELK stack<br />
As we are going to expand our system to receive and group more<br />
logs, the single Logstash server that we are currently using won’t<br />
be sufficient. We have to scale our architecture. Current it looks like<br />
Figure 8.<br />
Fig. 7: Specific end point for Lumberjack<br />
Fig. 10: Current Architecture<br />
The first thing we can scale is the Broker. Broker is the part that<br />
receives the log events. Currently we are using the message buffer<br />
from Logstash. A good way to scale the broker is to use Redis on a<br />
separate server to acts as a broker. Redis is a popular open source key<br />
value storage. Logstash includes plugins for using Redis.<br />
Fig. 8: Default Logstash dashboard in Kibana<br />
Redis is a popular open source key<br />
value storage<br />
The Logstash forwarder can now be started with the following<br />
command.<br />
C:\lgf> logstash-forwarder.exe -config=logstash-forwarder.conf<br />
To increase the throughput of the Indexer, we could also separate<br />
Logstash from Elasticsearch. So the new architecture looks like<br />
28<br />
MAGAZINE
GENERAL<br />
The protocol that Logstash-forwarder uses includes compression,<br />
encryption and message acknowledgement, which Redis does not<br />
support. There are alternative shippers which do, such as beaver and<br />
woodchuck.<br />
Fig. 11: Scaled Architecture<br />
Elasticsearch can be scaled<br />
by adding new Elasticsearch nodes<br />
to the cluster<br />
If we switch to using Logstash as a shipper we could configure it using<br />
the following output filter in which the events are sent to one of the<br />
two configured Redis servers.<br />
output {<br />
redis {<br />
host => ["redis-server1:6379", "redis-server2:6380"]<br />
}<br />
}<br />
Fig. 12: Horizontally Scaled Architecture<br />
This architecture can be scale horizontally very easily. We can add<br />
more Redis servers to increase the queue capacity, we can add more<br />
Logstash server to increase indexing capacity and add more nodes to<br />
the Elasticsearch cluster to increase the performance of querying and<br />
filtering of data. A first step into scaling horizontally looks like Figure 10.<br />
By cross connecting both Redis servers and the Logstash indexer we<br />
also create redundancy and fault tolerance between the systems. The<br />
shippers also can connect to both Redis servers so that if one of the<br />
servers goes down, a shipper is still able to send its events.<br />
Elasticsearch can be scaled by adding new Elasticsearch nodes to<br />
the Elasticsearch cluster. It will automatically detect and distribute data<br />
over the available nodes.<br />
Configuring the Scaled Architecture<br />
To configure the horizontally scaled ELK stack we need to make some<br />
changes to the configuration files.<br />
The Logstash configuration file on both indexers needs to change.<br />
We use the Redis plugin to get the input from both Redis servers.<br />
input {<br />
redis {<br />
host => "redis-server1"<br />
port => 6379<br />
data_type => "list"<br />
key => "logstash"<br />
}<br />
redis {<br />
host => "redis-server2"<br />
port => 6380<br />
data_type => "list"<br />
key => "logstash"<br />
}<br />
}<br />
Conclusion<br />
In this article I showed how to install and configure the ELK stack in<br />
such a way that enables transfering application logs from a Windows<br />
machine using logstash-forwarder to the machine that hosts the ELK<br />
stack. The host parses the application logs using Logstash, indexes<br />
the logs using Elasticsearch and allows visualizing hem using Kibana.<br />
By combining the logs from all your services and applications you can<br />
improve the traceability of your IT system. All your logs become<br />
searchable in almost real-time. By parsing extra information using<br />
Logstash per application you could give more meaning to your<br />
existing logs without having to go through all the logs individually.<br />
To scale out the ELK stack, Redis servers can be added together with<br />
separate Logstash servers. Scaling Elasticsearch is as easy as adding<br />
nodes to the cluster. The easy way the ELK stack can be scaled<br />
horizontally really shows the strength of the platform.<br />
This article barely scratched the surface of what you can do with the<br />
ELK stack. Topics I did not cover but are very interesting are security,<br />
creating dashboards with Kibana, adding semantics to log events,<br />
alerting, exporting and creating your own Logstash plugins.<br />
Other alternative platforms for log aggregation that you should<br />
consider when evaluating a log aggregation platform are Splunk,<br />
Sumologic and Scribe. •<br />
Patrick Kalkman<br />
Patrick Kalkman is a software<br />
architect at HintTech where he<br />
designs and implements state of the<br />
art web applications using an agile<br />
proces.<br />
Currently Logstash-forwarder does not support connecting to Redis.<br />
magazine voor software development 29
SQL<br />
Peter ter Braake<br />
SQL Server In-Memory OLTP<br />
2014 was het jaar van de release van SQL Server 2014. Nog meer dan dat was het het jaar van<br />
de release van tientallen nieuwe cloud services. Dit artikel gaat (een keer) niet over de cloud of<br />
over Azure. Dit artikel gaat over een nieuwe revolutionaire engine die volledig is geïntegreerd in<br />
SQL Server: Hekaton!<br />
Hekaton<br />
Hekaton was de code naam voor de In-Memory engine van SQL<br />
Server. Hekaton komt uit het Grieks en verwijst naar de ambitie van<br />
Microsoft om SQL Server honderd keer zo snel te maken. Honderd<br />
keer! Honderd keer is bij lange na niet gehaald, maar de resultaten zijn<br />
ondanks dat meer dan indrukwekkend.<br />
Hekaton, ofwel memory optimized tabellen, is één van de vele nieuwe<br />
in-memory features. De database engine van SQL Server is in de kern<br />
alle ruim twintig jaar oud. Veel designkeuzes zijn dus ook al meer dan<br />
twintig jaar geleden gemaakt. Weet u nog met welke computer u<br />
twintig jaar geleden werkte?<br />
De hardware van toen was ontzettend beperkt ten opzichte van de<br />
huidige hardware. Voornamelijk de hoeveelheid geheugen die we<br />
tegenwoordig met 64-bits computers kunnen is drastisch toegenomen.<br />
Tegelijkertijd is de prijs gekelderd zodat ook iedereen zich dat<br />
geheugen kan permitteren. Door de dure en beperkte hoeveelheid<br />
geheugen van toen is SQL Server een file-based database. Hoewel de<br />
engine zoveel mogelijk gebruik maakt van geheugen middels de<br />
buffer pool, is het uitgangspunt dat de gegevens op disk staan.<br />
De datafiles op disk waar de gegevens in opgeslagen worden, zijn<br />
opgedeeld in blokken van 8 KB, de pages. Ook in het geheugen<br />
zitten de records nog steeds opgeslagen op die pages.<br />
Latches<br />
Hoewel het concept van pages een optimalisatie betekende voor filebased<br />
databases, levert het ook beperkingen op. Op het moment dat<br />
SQL Server een nieuw record moet wegschrijven, of dat een bestaand<br />
record gewijzigd moet worden, bestaat er de kans dat records over<br />
elkaars ruimte heen schrijven. Dat zou inconsistenties (corruptie)<br />
veroorzaken. Daartegen moet SQL Server ons beschermen.<br />
werken. Als er maar één proces actief is in uw database, is dat geen<br />
probleem. Maar hoe meer cores u heeft, hoe meer processen tegelijkertijd<br />
actief zijn. Dat houdt in dat de kans dat een proces moet<br />
wachten op een ander proces steeds groter wordt. Wachtende<br />
processen is wat mensen ervaren als slechte performance.<br />
In het screenshot van figuur 1 ziet u het aantal transacties per seconde<br />
in een voorbeeld applicatie van Microsoft. In dit voorbeeld zijn dat 520<br />
transacties per seconde. Opvallend is het CPU verbruik van nog geen<br />
50%. Meer CPU’s gaat waarschijnlijk niet helpen om meer transacties<br />
te verwerken. Tweede opvallende feit is het aantal latches per<br />
seconde. Die latches kosten overhead in het systeem en veroorzaken<br />
wachttijden bij andere user processen. Daar zit de grote bottleneck.<br />
Memory optimized tables<br />
Met Memory optimized tables draait Microsoft het uitgangspunt van<br />
SQL Server om. Gegevens zitten in principe in het geheugen. Uiteraard<br />
moet alle data uiteindelijk ‘landen’ op disk, anders bent u die data<br />
kwijt. Memory optimized tables zijn wat in theorie genoemd wordt:<br />
fully durable. Dat wil zeggen dat als een transactie succesvol is<br />
afgerond, de gegevens gegarandeerd in de database zitten en niet<br />
meer kwijt kunnen raken. Gegevens worden dus weggeschreven naar<br />
disk, maar het uitgangspunt is dat de gegevens in het geheugen<br />
zitten. Daarvoor wordt geoptimaliseerd.<br />
Memory optimized tables omgekeerd<br />
uitgangspunt van SQL Server;<br />
Memory first then disk<br />
Omdat gegevens worden opgeslagen in geheugen is het concept van<br />
pages niet langer nodig. Een record zit in geheugen op een<br />
willekeurige plek die toevallig vrij was toen het geschreven werd.<br />
Omdat een record niet op een pagina staat, hoeft er ook geen latch<br />
te zijn om per ongeluk overschrijven van gegevens te voorkomen.<br />
Zonder latches zijn er ook geen processen die moeten wachten op<br />
latches. En minder wachtende processen is betere benutting van de<br />
beschikbare CPU’s, is betere performance.<br />
Fig. 1<br />
De bescherming die SQL Server biedt wordt een latch genoemd.<br />
Latches worden vaak uitgelegd als zijnde light-weight locks. Maar nu<br />
weet u nog niet veel meer. Als een proces begint met schrijven, wordt<br />
de hele pagina geblokkeerd voor dat proces. Totdat het proces klaar<br />
is met schrijven, kunnen andere processen niet met die pagina<br />
Locks<br />
Pagina’s worden beschermd met latches, records worden beschermd<br />
door middel van locks. Naast het feit dat twee processen op dezelfde<br />
pagina moeten zijn, kan het ook voorkomen dat ze met hetzelfde<br />
record werken. Locks voorkomen problemen door één van de<br />
processen te laten wachten. Memory optimized tabellen hanteren een<br />
lock and latch free mechanisme. Of in een moeilijk woord: optimistic<br />
multi version concurrency control. Een record wordt eigenlijk nooit<br />
meer gewijzigd. Een record wordt simpelweg met een timestamp<br />
30<br />
MAGAZINE
SQL<br />
gemarkeerd als oud en er wordt een nieuw record aangemaakt. Twee<br />
processen die tegelijkertijd met een record werken krijgen allebei hun<br />
eigen versie van het record.<br />
Natively compiled stored procedures<br />
Zonder locks en latches wordt een grote performance bottleneck<br />
weggenomen. Maar valt er nog meer te winnen? Zonder locks and<br />
latches wordt de CPU voor 100% gebruikt in de voorbeeldapplicatie<br />
van figuur 1. SQL Server zou eigenlijk in staat moeten zijn om met<br />
dezelfde hoeveelheid CPU cycles, meer werk te doen. Dat is precies<br />
wat u bereikt met natively compiled stored procedures. Tijdens de<br />
CREATE van deze stored procedures worden deze gecompileerd tot<br />
een C-dll. Deze vooraf gecompileerde code is veel beter geoptimaliseerd<br />
dan interpreted T-SQL en daardoor veel sneller.<br />
Natively compiled stored procedures kunnen nog niet de volledige<br />
SQL functionaliteit gebruiken. Niet alle data types worden ondersteund,<br />
niet alle functies worden ondersteund. Bovendien kunt u met<br />
een natively compiled stored procedure alleen werken met memory<br />
optimized tables, niet met klassieke file based tables. Andersom kan<br />
wel. Met Query interop wordt bedoeld dat u met gewoon SQL zowel<br />
gewone tabellen als memory optimized tables kunt benaderen.<br />
Alles bij elkaar krijgt u een architectuur zoals in figuur 2.<br />
Dat is niet meteen vanzelfsprekend.<br />
De CREATE TABLE ziet er als volgt uit.<br />
CREATE TABLE Sales.SalesOrderDetailHashOnly<br />
(<br />
[SalesOrderID] [int] NOT NULL,<br />
[SalesOrderDetailID] [int] NOT NULL PRIMARY KEY NON-<br />
CLUSTERED HASH WITH (BUCKET_COUNT=200000),<br />
[CarrierTrackingNumber] [nvarchar](25) NULL,<br />
[OrderQty] [smallint] NOT NULL,<br />
[ProductID] [int] NOT NULL INDEX IXH_ProductID NON-<br />
CLUSTERED HASH WITH (BUCKET_COUNT=300),<br />
[SpecialOfferID] [int] NOT NULL,<br />
[UnitPrice] [money] NOT NULL,<br />
[UnitPriceDiscount] [money] NOT NULL CONSTRAINT<br />
[DF_SalesOrderDetail_UnitPriceDiscount] DEFAULT ((0.0)),<br />
[LineTotal] [money],<br />
[rowguid] [uniqueidentifier] NOT NULL CONSTRAINT<br />
[DF_SalesOrderDetail_rowguid] DEFAULT (newid()),<br />
[ModifiedDate] [datetime] NOT NULL CONSTRAINT<br />
[DF_SalesOrderDetail_ModifiedDate] DEFAULT (getdate())<br />
) WITH (MEMORY_OPTIMIZED = ON, DURABILITY =<br />
SCHEMA_AND_DATA);<br />
Het goede nieuws is dat dit hoofdzakelijk is wat u gewent bent. Let<br />
vooral op de inline indexen en de bucket count bij de hash indexen.<br />
Verder valt op dat het statement eindigt met MEMORY_OPTIMIZED = ON<br />
en DURABILITY = SCHEMA_AND_DATA. Voor durability zijn er twee<br />
opties: schema_and_data en schema_only. Met die laatste zitten de<br />
gegevens alleen in memory, nooit op disk. Bij een server herstart bent<br />
u dus alle gegevens kwijt. Voor situaties als state van een website of<br />
staging tabellen bij ETL kan dat grote voordelen hebben.<br />
Bij het maken van een natively compiled stored procedure komt net<br />
iets meer nieuwe kennis kijken. De code begint altijd als volgt:<br />
Fig. 2<br />
Impact voor de programmeur<br />
Dit klinkt allemaal fantastisch, maar waarom dat verhaal in het<br />
Developers <strong>Magazine</strong>? Helaas is memory optimized tables geen<br />
feature die je aan of uit zet en die zonder verdere aanpassingen<br />
voordeel oplevert. De programmeur zal in zijn of haar code rekening<br />
moeten houden met de feature. Allereerst zijn er enkele zaken om over<br />
na te denken bij het maken van de tabel.<br />
CREATE PROCEDURE usp_InsertOrderMemoryOptimized<br />
@SalesOrderID int, @SalesOrderDetailID int, @OrderQty smallint,<br />
@ProductID int<br />
WITH NATIVE_COMPILATION<br />
, SCHEMABINDING<br />
, EXECUTE AS OWNER<br />
AS<br />
BEGIN ATOMIC WITH (<br />
TRANSACTION ISOLATION LEVEL = SNAPSHOT<br />
, LANGUAGE = 'us_english'<br />
, DELAYED_DURABILITY = OFF)<br />
Memory optimized tables<br />
een Developers taak<br />
Een memory optimized tabel kent geen ALTER TABLE. Van een tabel<br />
wordt, net als een natively compiled stored procedure, tijdens de<br />
CREATE een dll gemaakt. De enige manier om die aan te passen is<br />
hem weggooien om hem daarna opnieuw aan te maken. Dit klinkt<br />
misschien nog wel overkomelijk, maar geldt ook voor indexen. Ook<br />
indexen kunnen niet later aangemaakt worden of verandert worden.<br />
Memory optimized tabellen kennen twee soorten indexen, hash<br />
indexes en range indexes. Beide worden tijdens de CREATE TABLE al<br />
gedefinieerd. Bij de hash index moet u opgeven uit hoeveel hash<br />
buckets de index bestaat. De vuistregel is dat u ongeveer twee keer<br />
zoveel hashbuckets maakt als dat u unieke waarden in de te indexeren<br />
kolom heeft. Maar u moet wel vooraf een keuze maken.<br />
Het eerste dat opvalt, is de optie WITH NATIVE_COMPILATION. Die<br />
optie heeft geen verdere uitleg nodig. Omdat er een dll gemaakt wordt<br />
is de optie SCHEMABINDING verplicht. Verder is het verplicht een<br />
execution context te bepalen, de owner in dit voorbeeld.<br />
Vervolgens begint u altijd met de clausule BEGIN ATOMIC BLOCK.<br />
Zoals gezegd gaat memory optimized uit van optimistic multi version<br />
concurrency control. Dat houdt in dat er niet vooraf door middel van<br />
locks beschermd wordt tegen concurrency problemen. Iedereen werkt<br />
met zijn eigen versie van de records. Op het moment dat u uw transactie<br />
commit, wordt pas gekeken of uw versie wel commitbaar is. Het<br />
kan zijn dat iemand anders u voor is geweest en al een wijziging heeft<br />
doorgevoerd. U krijgt dan een foutmelding. Error handling code is dus<br />
van essentieel belang binnen uw stored procedure. Gelukkig kent<br />
T-SQL TRY … CATCH en sinds SQL Server 2012 ook THROW.<br />
Uw stored procedure is altijd een atomic block, ofwel een transactie.<br />
lees verder op pagina 35 ><br />
magazine voor software development 31
SCRUM<br />
Piet Willem Overvoorde<br />
SCRUM is veel meer dan<br />
een project management<br />
methodologie<br />
Dat is zonder meer waar en een methodologie die, mits die op de goede manier wordt gebruikt,<br />
heel goed toepasbaar is op allerlei soorten projecten. Dus het gebruik ervan is zeker niet beperkt<br />
tot ICT (gerelateerde) ontwikkelingen. Scrum is prima toepasbaar bij complexe producten<br />
(eindproduct is moeilijk vooraf tot in detail te beschrijven) en bij complexe organisaties (veel<br />
stakeholders).<br />
De uitdaging (opdracht) is om de effecten van het werken op basis<br />
van SCRUM te delen met de organisatie met het doel als collectief<br />
nog effectiever en efficiënter samen te werken.<br />
Belangrijke kernmerken van SCRUM zijn:<br />
• Eenduidig interpreteerbare werk- en projectafspraken;<br />
• Op basis van geplande evaluatie momenten continue aandacht<br />
voor opzet en inhoud van de werkzaamheden; maar aan<br />
gemaakte afspraken wordt niet getoornd;<br />
• Korte, afgeronde werkzaamheden;<br />
• Geen ad-hoc interventies;<br />
• Team prestatie is bepalend (zelfsturende en zelflerende<br />
organisatie);<br />
• Continue aandacht voor de kwaliteit van het door alle betrokken<br />
partijen geleverde product;<br />
• Rust en duidelijkheid in het project en in het proces.<br />
SCRUM is veel breder toepasbaar<br />
Overal waar er sprake is van een opdrachtgever en van het halen van<br />
financiële, inhoudelijke- en planningsdoelstellingen is SCRUM<br />
toepasbaar. Inderdaad niet altijd in de meest zuivere vorm maar wel als<br />
handvat voor het maken van afspraken en het opvolgen en managen<br />
hiervan. Als het eindproduct vast staat, heeft SCRUM geen toegevoegde<br />
waarde. Als voorbeeld de auto: het ontwikkelen kan met<br />
scrum, het produceren van de auto bijvoorbeeld met lean.<br />
Wanneer je de hiervoor beschreven kenmerken van SCRUM nog een<br />
keer doorneemt en projecteert op de dagelijkse werkelijkheid van<br />
bijvoorbeeld de samenwerking tussen sales en delivery in verkoop en<br />
implementatie trajecten dan blijkt dat deze aanpak zonder meer ook<br />
hierop prima toepasbaar is.<br />
SCRUM leidt tot verbeterd begrip<br />
tussen de verschillende bloedgroepen<br />
binnen een organisatie<br />
Waarom het SCRUM gedachtengoed als basis voor het beheer<br />
van processen?<br />
De voordelen van het gebruik van (een variant) van SCRUM in sales<br />
processen zijn onder andere:<br />
• Duidelijke afspraken tussen alle deelnemers (sales, pre-sales,<br />
delivery/operations, prospect, adviseur etc.);<br />
• Heldere lijnen voor het managen van het proces;<br />
• Alle deelnemers worden ‘gedwongen’ vooraf heel goed nagedacht<br />
te hebben;<br />
• Voor en bij het afsluiten van het contract zijn alle relevante partijen<br />
betrokken geweest.<br />
Naast een eenvoudiger en succesvoller beheer van de genoemde<br />
voorbeeld processen leidt een breder gebruik van (de uitgangspunten<br />
van) SCRUM ook tot een verbeterd begrip, over en weer, tussen<br />
de verschillende bloedgroepen binnen een organisatie. De zaken<br />
waarmee sales, project management, consultancy en ontwikkeling<br />
dagelijks te maken hebben in hun ‘eigen wereld’ worden binnen het<br />
team gedeeld. Het team is verantwoordelijk voor het realiseren van de<br />
doelstellingen en niemand kan zich achter de performance van een<br />
ander verschuilen.<br />
Een andere, meer effectieve en resultaatgerichte vorm van<br />
samenwerking<br />
De eerder in dit stuk genoemde rust en duidelijkheid komen, wanneer<br />
deze manier van werken effectief is geïmplementeerd, iedereen ten<br />
goede. Ad hoc vragen en interventies van collega’s en zeker ook van<br />
managers mogen in principe niet meer voorkomen.<br />
32<br />
MAGAZINE
SCRUM<br />
Ieder lid van het team moet acteren als eigenaar en verantwoordelijke<br />
voor het eindresultaat (overall en van een sprint). En in die rol wil je<br />
zaken niet over hoeven doen omdat de WAT vraag niet voldoende is<br />
uitgevraagd. Of het antwoord op de HOE vraag niet op de beste<br />
manier is afgestemd en geformuleerd.<br />
SCRUM kan in een bepaalde vorm worden toegepast voor de<br />
beheersing van andere processen. Maar de volgende zaken kunnen<br />
zonder meer organisatie breed worden geadopteerd:<br />
• Het benoemen van de doelstelling(en)/het product van de samenwerking,<br />
de WAT vraag;<br />
• Het definiëren van sprints/stappen waarbinnen het antwoord op de<br />
HOE vraag vorm moet krijgen (of deze allemaal van een gelijke duur<br />
moeten en kunnen zijn is sterk afhankelijk van het project en de<br />
hierin onderkende stappen; het verzorgen van een demo kost bijvoorbeeld<br />
minder tijd dan het beantwoorden van een RFI of RFP);<br />
• Het toekennen van duidelijke taken en verantwoordelijkheden aan<br />
de Product Owner, de SCRUM Master (of de procesbeheerder) en<br />
het team (of de teams, wanneer die per sprint verschillend zouden<br />
zijn; dit laatste is een concreet verschil tussen SCRUM in de<br />
zuivere vorm als project management tool (vooral gebruikt binnen de<br />
ontwikkeling van softwarematige toepassingen) en de SCRUM<br />
methodologie als kapstok voor het managen van andere soorten<br />
projecten/activiteiten);<br />
• Gebruik maken van de praktische hulpmiddelen zoals de rol van de<br />
SCRUM Master, de dagelijkse afstemming/update, het SCRUM<br />
bord (met alles dat daar deel vanuit maakt) en de pokerkaarten;<br />
• En na afloop een integrale evaluatie van de kennis en ervaring die<br />
vanuit het project kan worden meegenomen en ingezet om<br />
toekomstige projecten nog beter te laten verlopen.<br />
bedrijfsprocessen. Combinaties van allerhande, technische en<br />
functioneel, rol/ functie gerichte, tools. Dat is nu ook mogelijk omdat<br />
het koppelen van oplossingen en het synchroniseren van databases<br />
veel eenvoudiger is geworden. Door de focus van alle betrokken<br />
partijen is de kans groot dat een investering een veel meer toekomstbestendige<br />
blijkt te zijn. De behoefte aan het eenvoudig kunnen delen<br />
van informatie zal ook verder toe gaan nemen.<br />
De samenwerking is gebaseerd op<br />
onderling vertrouwen<br />
De ontwikkeling die hiervoor is beschreven met betrekking tot ICT<br />
oplossingen geldt ook voor heel veel andere soorten projecten. Steeds<br />
meer is er sprake van virtuele, project specifieke, teams van professionals<br />
die het afgesproken resultaat tot stand moeten brengen.<br />
Het gebruik van een erkende en gestandaardiseerde project aanpak<br />
biedt dan uitkomst. En voorkomt allerhande spraakverwarring met<br />
betrekking tot verwachtingen, communicatie, voortgangsrapportage<br />
etc. Het is om die reden dat het aantal online SCRUM ondersteunende<br />
tools zeker toe zal nemen in de komende periode.<br />
Gaat die samenwerking vanzelf en gelijk goed?<br />
Het is voor medewerkers en managers wennen wanneer SCRUM<br />
breed in de onderneming wordt geïntroduceerd. De hiervoor zo<br />
benoemde verschillende bloedgroepen binnen een organisatie, sales,<br />
consultants, ontwikkelaars, project leiders en managers, zullen stuk<br />
voor stuk het gevoel kunnen hebben dat anderen in hun domein<br />
‘binnen dringen’.<br />
Dat is natuurlijk ook zo, maar erg is anders! De samenwerking moet<br />
worden gebaseerd op een oprecht onderling vertrouwen: gemaakte<br />
afspraken moeten gestand worden gedaan. En als daar reden voor is<br />
dan worden zorgen en aandachtspunten tijdig onderkend en gedeeld.<br />
Een heel groot voordeel voor de betrokken managers is dat zij hun<br />
eigenlijke rol en opdracht inhoud kunnen geven.<br />
Het succes moet zijn gebaseerd op het op deze manier WILLEN<br />
werken. En iedereen beperkt zich in dit geval niet tot de interne<br />
organisatie. Binnen de teams zullen ook partners, prospects en klanten<br />
actief zijn. Het is goed om de introductie van deze werkwijze op te<br />
pakken samen met een of meerdere bestaande klanten en partners.<br />
Een andere vorm van samenwerking is noodzakelijk<br />
We zitten in de eindigende periode dat alles binnen dezelfde<br />
zogenaamde ERP oplossing moet kunnen worden opgelost. Op basis<br />
van de standaard set aan functionaliteiten gecombineerd met branche<br />
specifieke modules en maatwerk. Initieel is dit zonder meer een goede<br />
gedachte.<br />
De ervaring heeft geleerd dat er in de loop van de tijd vaak sprake is<br />
van a-synchronisatie tussen de ondersteunde versies van applicaties,<br />
besturingssystemen, ontwikkelomgevingen en databases. Dit heeft te<br />
maken met de periodieke heroverweging met betrekking tot branchefocus<br />
en de wil en mogelijkheid om in een ontwikkeling te blijven<br />
investeren. De wil wordt o.a. bepaald door de kans op een redelijk<br />
rendement.<br />
Er zal gebruik gemaakt gaan worden van ‘best of breed’ oplossingen<br />
als basis voor de ondersteuning van alle voor een organisatie relevante<br />
Is dit de basis voor het succes van ieder project?<br />
Nee! Hoe goed een project aanpak ook is, het team bepaalt het<br />
succes. Ook in sectoren waar er sprake is van strikte regels en<br />
procedures, zoals in de luchtvaart, de gezondheidszorg en de off<br />
shore, gaan er dingen mis. Maar oorzaken worden snel achterhaald.<br />
En de nodige maatregelen snel genomen.<br />
Wanneer het aantal variabelen toeneemt, neemt de behoefte aan<br />
duidelijke afspraken en kortlopende trajecten toe. Korte, overzichtelijke<br />
trajecten waardoor de risico’s tot een minimum worden beperkt<br />
worden steeds meer geëist door de klant. En dat is de basis van<br />
SCRUM. Dingen opnieuw doen is vaak mogelijk. Maar werkzaam -<br />
heden over-/anders doen is altijd kosten¬verhogend, marge verlagend<br />
en reputatie schadend.<br />
De implementatie<br />
Voor iedere verandering die wordt doorgevoerd geldt dat deze gaande<br />
het proces en mede op basis van de input van alle betrokkenen vorm<br />
moet krijgen.<br />
Een heel groot voordeel van de introductie van SCRUM als uitgangspunt<br />
voor de vormgeving van de samenwerking is dat vanaf het prille<br />
begin op deze manier gewerkt kan, beter zal worden.<br />
magazine voor software development 33
SCRUM<br />
Daardoor worden stap voor stap meer mensen hiermee bekend en<br />
groeit het vertrouwen dat dit inderdaad een positieve bijdrage zal gaan<br />
leveren. Naast het organiseren van allerhande praktische zaken moet<br />
in dit proces de ‘menselijke’ kant zeker niet worden onderschat en<br />
vergeten. Diverse rollen binnen de organisatie zullen een ander<br />
karakter krijgen. Dit vraagt aanpassing van het dagelijkse doen en<br />
laten.<br />
Zoals eerder gememoreerd is het ontwikkelen van een authentiek<br />
onderling vertrouwen een heel belangrijk aspect. Naast een goede<br />
uitwerking van de praktische aspecten en tools is een goede,<br />
professionele begeleiding op het ‘menselijke’ vlak zonder meer<br />
noodzakelijk.<br />
De beoordeling van de medewerkers moet primair gericht zijn op de<br />
realisatie van (collectieve) lange(re) termijn doelstellingen. Wanneer<br />
persoonlijke belangen (beloning, prestige, kans op promotie etc.) de<br />
boventoon voeren in het besluit onderdeel te willen zijn van bepaalde<br />
projecten dan zal deze methodiek nagenoeg zeker haar doel niet<br />
bereiken.<br />
Het management moet er klaar voor zijn of klaar voor gestoomd<br />
willen worden. Zo nodig ondersteund door een vorm van professionele<br />
inhoudelijke en persoonlijke coaching. Het commitment van alle<br />
managers is een essentiële bouwsteen van een succesvolle<br />
implementatie.<br />
Is dit alles nieuw en innoverend?<br />
Nee, bijna altijd is er voor elk proces een projecten<br />
procesaanpak aanwezig. Gedreven vanuit de<br />
primaire behoeften van de ‘bloedgroep’.<br />
Ja, want heel weinig organisaties gebruiken, om<br />
een veelheid aan (historische) redenen, voor alle<br />
aanwezige processen dezelfde uitgangspunten en<br />
werk¬methodiek.<br />
Een praktische voorbeeld: de opvolging van een RFI/RFP<br />
Zoals hiervoor is beschreven is het zeker niet het primaire doel om<br />
SCRUM in de meest zuivere vorm toe te willen passen. Wel wordt<br />
zoveel als mogelijk gebruik gemaakt van praktische handvatten die de<br />
methodologie biedt om processen op basis van heldere en eenduidige<br />
uitgangspunten professioneel en maximaal effectief en efficiënt<br />
te organiseren en realiseren. Opmerkingen als ‘dat wist ik niet’, ‘Maar<br />
wat nu als we toch/alsnog op basis van deze oplossing aanbieden<br />
….’ en ‘o, ik dacht dat …’ worden hiermee voorkomen. Door het team<br />
worden tenslotte voor in ieder geval een bepaalde periode (sprint)<br />
afspraken gemaakt op basis waarvan gewerkt wordt.<br />
De basis motivatie voor deze benadering is het creëren en behouden<br />
van het bewustzijn dat iedereen binnen een organisatie een rol kan<br />
spelen in de positieve afronding van projecten.<br />
Globaal kunnen in het proces van opvolging van een RFI/RFP de<br />
volgende fases worden onderscheiden:<br />
• Initiële evaluatie van de aanvraag;<br />
• Beantwoording van de functionele en technische vragen;<br />
• Oplevering van de documentatie;<br />
• Presentatie van de organisatie, de oplossing en het voorstel;<br />
• Proces om te komen tot een overeenkomst;<br />
• Realisatie van het project;<br />
• Doorontwikkeling van de relatie.<br />
Fase ‘0’van het project<br />
In deze fase worden onder andere de ‘opdrachtgever’ en de (potentiële)<br />
teamleden, eventueel per onderdeel/fase, bepaald. In vervolg<br />
hierop worden in de eerste samenwerking tussen opdrachtgever en<br />
team de hoofdfases benoemd.<br />
SCRUM binnen organisaties levert<br />
voordelen op<br />
Conclusie<br />
De introductie van een op de uitgangspunten van SCRUM gebaseerde<br />
samenwerking tussen alle bij een organisatie betrokken partijen biedt<br />
eigenlijk alleen maar voordelen. Mits dit proces vanaf het begin op een<br />
goede en professionele manier is gemanaged.<br />
• Duidelijkheid in doelstellingen, werkwijze, taken en verantwoordelijkheden;<br />
• Substantiële verbetering van de juistheid van het antwoord op de<br />
vraag WAT er wordt verwacht;<br />
• Een duidelijke kwaliteitsverbetering van het antwoord op de HOE<br />
vraag;<br />
• Efficiency verbetering op vele fronten, bezig zijn met de juiste<br />
dingen;<br />
• Verbetering en verduurzaming van de relatie en samenwerking met<br />
klanten en partners;<br />
• Versterking en verdieping van het onderlinge begrip en vertrouwen<br />
en daarmee de teamgeest.<br />
Kortom: zeker het overwegen waard!<br />
Handvatten na Fase ‘0’<br />
Geen RFI/RFP is hetzelfde en er wordt steeds meer op basis van<br />
business cases gewerkt in plaats van (of in combinatie met) lijsten met<br />
technische en functionele eisen en wensen. Hierdoor wordt het steeds<br />
belangrijker goed in staat te zijn om vat te krijgen op de werkelijke<br />
vraagstelling. Naast de standaard acties zoals het in kaart brengen<br />
van het beslistraject en de hierbij (in)direct betrokkenen.<br />
De WAT vraag bestaat in deze fase uit de volgende elementen (basis<br />
voor het definiëren van de sprints in deze fase):<br />
• WAT is de werkelijke behoefte van de prospect<br />
nu en in de toekomst;<br />
• WAT zijn de werkelijke technische en inhoudelijke wensen en eisen;<br />
34<br />
MAGAZINE
SCRUM<br />
• WAT is de planning van het voortraject en de realisatie;<br />
• WAT zijn de argumenten om deze RFI/RFP in te vullen;<br />
• WAT kunnen wij bieden dat ons bijzonder maakt en onze kansen<br />
maximaliseert;<br />
• WAT moeten wij doen om dit project tot een succes te maken;<br />
• WAT …..<br />
Op basis van de lijst (inderdaad er is geen enkelvoudige WAT vraag in<br />
deze toepassing te benoemen) met WAT vragen moet het antwoord<br />
worden gegeven op de HOE vragen die niet zonder meer vanuit de<br />
beschikbare documentatie kan worden beantwoord:<br />
• HOE gaan we de werkelijk behoeften, wensen en eisen in kaart<br />
brengen;<br />
• HOE brengen we de beslissers, beïnvloeders etc. in kaart;<br />
• HOE gaan we de beantwoording inhoudelijk en wat betreft<br />
presentatie vormgeven;<br />
• HOE (op basis van welke oplossingen, met welke partners, etc.)<br />
geven we technisch en functioneel het beste invulling aan hetgeen<br />
in de RFI/RFP is beschreven<br />
• ……..<br />
Alle vragen worden gesteld en beantwoord<br />
binnen een team. Daarbij wordt<br />
van iedereen verwacht dat die zich open<br />
en kwetsbaar opstelt. Wat voorheen<br />
vaak binnen de comfortzone van een<br />
afdeling werd besproken wordt nu<br />
gedeeld, beoordeeld en daarmee<br />
verrijkt. Door het toevoegen van de input<br />
en invloed vanuit andere perspectieven<br />
vindt er op meerdere manieren en<br />
diverse fronten een verbetering plaats die bijdraagt aan de kwaliteit en<br />
de uitkomst van het project.<br />
Waar de antwoorden op deze vragen bij het ‘reguliere’ gebruik van<br />
SCRUM in de methodologie zijn ingebakken moeten deze bij het<br />
beoogde bredere gebruik van deze aanpak specifiek worden<br />
beantwoord:<br />
• Op basis van de antwoorden op de HOE vragen zal het antwoord<br />
op de WIE vragen moeten gegeven. WIE (welk TEAM) maakt zich<br />
verantwoordelijk voor welke onderdeel. In tegenstelling tot SCRUM<br />
in de zuiver vorm zal er naar verwachting sprake zijn van een<br />
wisselende samenstelling van de teams.<br />
• Tenslotte moet het antwoord worden gegeven op de WANNEER<br />
vragen. Wanneer moet welke ‘sprint’ zijn afgerond en hoe wordt de<br />
(continue) evaluatie vorm gegeven. In tegenstelling tot SCRUM in<br />
de zuivere vorm zullen ‘sprints’ in deze toepassing per stuk in lengte<br />
kunnen variëren.Voor het managen van het proces is het logisch<br />
om een SCRUM Master in te zetten. Maar wel een die begrip heeft<br />
voor de wijze waarop het SCRUM gedachtengoed in het project<br />
wordt gebruikt.<br />
Een groot voordeel van het inzetten van een SCRUM Master is ook dat<br />
de overgang van bijvoorbeeld de sales naar de delivery organisatie en<br />
vervolgens de uitvoering van het project nog makkelijker zal verlopen.<br />
En op het gewenste kwaliteitsniveau. De borging van alle aspecten<br />
die nodig zijn voor een succesvol verloop van het project zijn tenslotte<br />
door de SCRUM Master geborgd. •<br />
Pietwillem Overvoorde<br />
Pietwillem Overvoorde (1964) heeft<br />
in de loop van de tijd nagenoeg alle<br />
mogelijke rollen vervuld binnen<br />
(inter)nationale ICT projecten.<br />
Software ontwikkeling, business<br />
consultancy, project management,<br />
business development, sales- en<br />
accountmanagement maken deel uit van zijn CV.<br />
Bij zijn werkgever, Yellowstar Solutions (www.yellowstarsolutions.nl),<br />
wordt SCRUM sinds de oprichting toegepast in alle<br />
processen. Voor bijna alle activiteiten geldt: geen lange<br />
vergaderingen maar korte, effectieve stand-ups. De zelfsturende<br />
teams zijn verantwoordelijk voor het resultaat. In deze manier van<br />
werken zijn ook medewerkers van klanten betrokken. Vaak gaat<br />
dit in de eerste fase van samenwerking gepaard met een<br />
gewenningsproces; iets waarin de medewerkers van Yellowstar<br />
coachend optreden. De praktijk heeft geleerd dat het kort op de<br />
bal spelen voor alle betrokken partijen zeer effectief is.<br />
vervolg van pagina 31 ><br />
Scenario’s<br />
De feature heet niet voor niets in-memory OLTP. SQL Server kent sinds<br />
SQL Server 2012 de zogenaamde ColumnStore index. Dit is een<br />
feature die ook valt in de range in-memory features. ColumnStore is<br />
specifiek voor datawarehouse queries. Memory optimized tables heel<br />
specifiek niet. Als u een workload heeft met veel schrijven, en als de<br />
transactie throughput wordt beperkt door locking and latching, dan<br />
kunnen memory optimized tables uitkomst bieden. Zoals gezegd is<br />
het uitgangspunt waar gegevens leven anders (geheugen in plaats van<br />
disk). Nog belangrijker is dat het programmeermodel anders is. Van<br />
pessimistic concurrency met locking gaat u over op optimistic<br />
concurrency met versioning. Dat vergt een andere opbouw van uw<br />
code. Een tweede scenario zijn de tabellen met durability op<br />
SCHEMA_ONLY. Gegevens in een database die kwijt kunnen raken?<br />
Eigenlijk een soort temp tables dus, maar dan zonder de overhead<br />
van IO on TempDB.<br />
Conclusie<br />
Dit artikel is slechts een high level overview van memory optimized<br />
tabellen. De belangrijkste take-away is dat er een ongelofelijke<br />
perfomance winst valt te halen. Maar die winst is er alleen in heel<br />
specifieke situaties. En een nieuw concurrency model vergt<br />
waarschijnlijk wat aanpassingen aan uw code. •<br />
Peter ter Braake<br />
Peter ter Braake is sinds de zomer<br />
van 2008 zelfstandig trainer / consultant<br />
/ MVP op het gebied van<br />
SQL Server. Ik verzorg voor klanten<br />
database en Business Intelligence<br />
trainingen. Tevens doe ik korte projecten<br />
in dezelfde aandachtsgebieden.<br />
In 2005 heb ik met een aantal<br />
mensen PASS Nederland opgericht.<br />
PASS is de gebruikersgroep voor SQL Server. Ik ben daar<br />
momenteel vice-voorzitter en verantwoordelijk voor de events die<br />
PASS organiseert.<br />
magazine voor software development 35
DELPHI<br />
Cary Jensen<br />
Delphi's REST Debugger and<br />
REST Client Library, Part 1<br />
At <strong>SDN</strong>'s Software Development Conference in Papendal this December I presented a session<br />
on DataSnap and REST using FireDAC. In that presentation I demonstrated a DataSnap server<br />
that used FireDAC FDMemTables to create special data streams that could be delivered to client<br />
applications written in Delphi, and from which specialized streams containing a user's updates<br />
to the data could be returned. Importantly, the client/server communication made use of HTTP<br />
(hypertext transfer protocol) requests and JSON (JavaScript Object Notation), two elements<br />
central to a distributed application style typically referred to as REST (REpresentational State<br />
Transfer).<br />
The client application that I demonstrated made use of a TDSREST-<br />
Connection component, which was then used to import the interface<br />
of the TServerMethods class found on the DataSnap server. Much of<br />
that interface was designed to demonstrate FireDACJSONReflect, a<br />
set of classes and interfaces designed to wrap and unwrap data for<br />
use with FDMemTables in the client application.<br />
I bring up that presentation as a starting point for a discussion about<br />
REST clients, client applications that connect to data using HTTP. I<br />
am not going to get into a detailed discussion of FireDACJSONReflect,<br />
as that is just one of many possible ways to wrap data that is<br />
consumed by a REST client, and one that is somewhat limited, in that<br />
it more or less requires a Delphi client. Instead, I am going to use that<br />
server to demonstrate some of the REST-related tools that have<br />
shipped in Delphi since Delphi XE5. These include the REST<br />
Debugger and the REST Client Library But before we do that, it is<br />
necessary to first understand some features of the DataSnap server.<br />
The DataSnap Server<br />
Methods exposed by a REST-based DataSnap server are those<br />
methods associated with the TServerMethods class. When you use<br />
the DataSnap Server wizard from the Object Repository, you have the<br />
option of creating this class as a TComponent, a TDataModule, or a<br />
TDSDataModule. So long as you are not using the server to expose<br />
TDataSetProviders, it really doesn't matter which one you pick.<br />
Personally, I prefer either the TDataModule or TDSDataModule options,<br />
as they provide a design surface on which to place components.<br />
If your DataSnap server is data-aware, as this one is, these components<br />
will be associated with connecting to a database and executing<br />
queries. Figure 1 shows how my DataSnap server methods data<br />
module looks like in Delphi's designer. Note that some of the components<br />
on this data module, such as the TFDStanStorageBinLink and<br />
the TFDStanStorageJSONLink, are there to support FireDACJSON<br />
Reflect, and not necessarily required by a DataSnap REST server.<br />
Fig. 1: The server methods data module in the designer<br />
Here is the declaration of the TDSDataModule class, showing some of<br />
the methods exposed through this class (for the most part, I am only<br />
showing the methods that I will be calling in the clients I discuss later<br />
in this article). The methods being exposed are those found in the<br />
public section of the class declaration.<br />
type<br />
TServerMethods1 = class(TDSServerModule)<br />
CustomerQuery: TFDQuery;<br />
FDConnection1: TFDConnection;<br />
FDStanStorageBinLink1: TFDStanStorageBinLink;<br />
FDStanStorageJSONLink1: TFDStanStorageJSONLink;<br />
OrdersQuery: TFDQuery;<br />
CustomerOrdersQuery: TFDQuery;<br />
private<br />
{ Private declarations }<br />
public<br />
{ Public declarations }<br />
function EchoString(Value: string): string;<br />
function ReverseString(Value: string): string;<br />
function EchoStringRaw(Value: string): string;<br />
function ReverseStringRaw(Value: string): string;<br />
function GetCustomerCDSRaw: string;<br />
end;<br />
EchoString and ReverseString are the sample methods generated by<br />
the DataSnap Server wizard, and they return a JSON result. The other<br />
methods are custom methods whose names ends with Raw. Those<br />
methods return a custom string that does not necessarily wrap the<br />
result in a JSON object.<br />
REST = REpresentational State<br />
Transfer; JSON = JavaScript Object<br />
Notation<br />
I don't want to focus too much on the implementation of these<br />
methods, instead permitting you to learn more about them by<br />
36<br />
MAGAZINE
DELPHI<br />
examining the source code from the download I will reference later in<br />
this article. However, permit me to show two methods: EchoString,<br />
and EchoStringRaw, so that you can see the basic difference between<br />
how Delphi's default server returns data (EchoString) and how you<br />
can take control over the returned content.<br />
Since the path to these files must be defined before the server starts,<br />
I insert a reference to the certificate files upon creation of the data<br />
module that holds the DataSnap-enabling components. This class is<br />
referred to as the server container unit, and the relevant code is shown<br />
in the following code segment.<br />
function TServerMethods1.ReverseString(Value: string):<br />
string;<br />
begin<br />
Result := System.StrUtils.ReverseString(Value);<br />
end;<br />
function TServerMethods1.ReverseStringRaw(Value: string):<br />
string;<br />
begin<br />
//Must use the DBXPlatform unit for GetInvocationMetadata<br />
GetInvocationMetadata().ResponseCode := 200;<br />
GetInvocationMetadata().ResponseContent :=<br />
System.StrUtils.ReverseString(Value);<br />
end;<br />
GetInvocationMetadata is discussed later in this article.<br />
{$DEFINE UseAuthentication}<br />
var<br />
AppDir: string;<br />
procedure TServerContainer1.DataModuleCreate(Sender: TObject);<br />
begin<br />
AppDir := ExtractFilePath(ParamStr(0)) + 'keys\';<br />
DSCertFiles1.CertFile := AppDir + 'MyDataSnap.pem';<br />
DSCertFiles1.KeyFile := AppDir + 'MyDataSnap.key';<br />
{$IFDEF UseAuthentication}<br />
DSHTTPService1.AuthenticationManager := DSAuthenticationManager1;<br />
{$ENDIF}<br />
end;<br />
DataSnap Servers and Security<br />
This DataSnap server implements security through secure socket layer<br />
and, optionally, through authentication. Since both of these features<br />
impose requirements for any REST client application, permit me to<br />
spend a moment explaining this in more detail.<br />
Secure socket layer, or SSL, is implemented in DataSnap using<br />
OpenSSL. OpenSSL is an open source technology used to provide<br />
encrypted communications between a server (which is an HTTP<br />
server in this case) and an HTTP client. The HTTP client could<br />
potentially be any client, such as a Delphi application, a Web browser,<br />
or a mobile application employing JavaScript.<br />
Note: If you are using OpenSSL on<br />
your server, you should ensure that<br />
you are using a recent version of the<br />
OpenSSL libraries (libeay32.dll and<br />
libssl32.dll). Older versions of<br />
OpenSSL contain a vunerability<br />
named heartbleed<br />
For this demonstration, I created an SSL certificate using OpenSSL.<br />
This process is described by Paweł Głowacki, Embarcadero's<br />
European Technical Lead for Delphi and RAD Studio technologies, in<br />
his blog found at:<br />
http://blogs.embarcadero.com/pawelglowacki/2013/10/16/40089.<br />
When you download and install OpenSSL, and then run the batch file<br />
provided by Pawel in his blog, you can generate a certificate that is<br />
suitable for testing, but not for deployment. In order to create a<br />
certificate for deployment, you need to purchase one from a trusted<br />
certificate authority, such as Symantec, Thawte, or GoDaddy.<br />
In order to simplify your use of the DataSnap server demo, I have<br />
included a directory containing the certificate files that I generated.<br />
As you can see from this code, there is a conditional define that can<br />
be used to turn on or off authentication. This allows me to easily<br />
enabled or disable authentication, and then show how doing so<br />
affects the client applications. When authentication is turned on, the<br />
first attempt by a client to connect to the DataSnap server will be<br />
challenged for a username and password. This is handled by the<br />
OnUserAuthenticate event handler associated with the TDSAuthenticationManager<br />
component. In my simple demonstration I am only<br />
requiring the user to enter the password Delphi, as you can see from<br />
the following event handler.<br />
procedure TServerContainer1.DSAuthenticationManager1UserAuthenticate(<br />
Sender: TObject; const Protocol, Context, User, Password:<br />
string;<br />
var valid: Boolean; UserRoles: TStrings);<br />
begin<br />
valid := Password = 'Delphi';<br />
end;<br />
Because the primary concern of this article is about REST clients,<br />
I have described as much as I intend to about the DataSnap server.<br />
REST Clients<br />
As mentioned earlier, REST clients come in a variety of flavors. Let's<br />
begin by using one of the more ubiquitous, the everyday web<br />
browser.<br />
Making REST Calls using a Browser<br />
To begin with, you need to run the DataSnap server. In this first<br />
demonstration, the UseAuthentication define is commented out,<br />
meaning that only SSL encryption is used.<br />
Let's start by calling the ReverseString method. Since my server is<br />
listening on port 8081, and I am using the default DSContext and<br />
RESTContext properties of the TDSHTTPService component in the<br />
server container unit, and my server methods class name is TServer-<br />
Methods1, I can call ReverseString, passing the string "Delphi," using<br />
the following URL:<br />
https://localhost:8081/datasnap/rest/tservermethods1/Reverse-<br />
String/Delphi<br />
magazine voor software development 37
DELPHI<br />
Since I have used a custom (some would say phoney) SSL certificate,<br />
Internet Explorer balks at my attempt to go to this URL, instead<br />
warning me of a potential problem, as shown in Figure 2.<br />
Fig. 5: A username and password is requested prior to connecting<br />
to the DataSnap server<br />
Fig. 2: IE warns that the custom certificate was not issued by a<br />
trusted certificate authority<br />
Since I know that there is no threat, I click Continue to this website.<br />
So long as the browser is open, this is the last time I am going to have<br />
to verify that I want to go to this URL. Having accepted the risk,<br />
IE now shows the value returned by the call to ReverseString,<br />
as shown in Figure 3.<br />
The value shown in Figure 3 is a JSON object containing a single<br />
name/value pair. As you can see, the name is result. The value part is<br />
a JSON array, and this is where all of the data returned by a REST call<br />
to a DataSnap server will appear, by default. In some cases, such as<br />
when you return a data set, this array can contain a great deal of data.<br />
Authentication happens the first time you touch a given DataSnap<br />
server from a given client. Authorization, by comparison, happens<br />
upon each and every REST method invocation. You use authorization<br />
to implement role-based permissions, either permitting or denying a<br />
particular user the right to invoke the method they are trying to call. A<br />
further discussion of authorization is beyond the scope of this article.<br />
Calling REST Methods Using the REST Debugger<br />
Introduced in Delphi XE5, Delphi's REST Debugger is a stand alone<br />
application that permits you to test calls to REST services. In it's<br />
simplest form, you enter a URL with a correctly formed REST<br />
invocation into the REST Debugger and then click Send Request.<br />
Figure 6 shows how the REST Debugger looks after sending the same<br />
request used in Figure 3 to the DataSnap server. In this figure, the<br />
Body tab of the Response pane is selected, displaying a formatted<br />
view of the returned JSON.<br />
Fig. 3: The JSON object returned by DataSnap<br />
There might be some cases where you do not want to use the default<br />
format employed by DataSnap. In that case you can use a technique<br />
like that shown in the implementation of the ReverseStringRaw<br />
method. There I've used the TDSInvocationMetadata object returned<br />
by the GetInvocationMetadata function to return a string without<br />
wrapping it in a JSON object. This permits me to create my own string,<br />
even one that represents a JSON object using a different format.<br />
Figure 4 shows the text returned by the call to ReverseStringRaw,<br />
which is simple text in this case.<br />
Fig. 4: You can return custom formats using a TDSInvocation<br />
Metadata object<br />
Things are a little different if we invoke our methods with authentication<br />
enabled. In that case, the first time we invoke one of the methods<br />
on the DataSnap server, in other words, the first time we touch the<br />
DataSnap server through HTTP, we are challenged for a username<br />
and password, as shown in Figure 5.<br />
Since my implementation of the OnUserAuthenticate event handler<br />
only requires a password of Delphi, so long as I provide the password<br />
Delphi (a case-sensitive string), the method being invoked will return<br />
its value. If I do not pass a valid username/password pair, the browser<br />
will display an error, and the call to the REST method will fail.<br />
Fig. 6: The REST Debugger executes the same URL as shown in<br />
Fig.3.<br />
Entering the full URL for the invocation of the REST method in the URL<br />
field of the Request tab of the Request pane is convenient. However,<br />
when you later move to the REST client components in Delphi it is<br />
better to partition the pieces of the request URL between the base<br />
URL and the specific method invocation segment. Specifically, all of<br />
the methods from the DataSnap server being used in this sample have<br />
the same base URL, as shown here:<br />
https://localhost:8081/datasnap/rest/tservermethods1<br />
38<br />
MAGAZINE
DELPHI<br />
The remainder of the URL specifies the method to invoke and any<br />
required parameters. The REST Debugger can accept the method<br />
name and its parameters in a property it calls the resource, where the<br />
resource specifies the method to be invoked, and, if the method<br />
requires one or more parameters, defines named placeholders, one for<br />
each parameter. With respect to the ReverseString method being<br />
invoked in Figure 6, this resource looks something like this:<br />
ReverseString/{Value}<br />
In this resource, ReverseString specifies the method to be invoked,<br />
and the single required parameter is represented by a name within<br />
curly braces. The actual name used for a particular parameter is<br />
irrelevant, just so long as it is unique within the resource. Specifically,<br />
that I've used the name Value in the resource has nothing to do with<br />
the fact that the formal parameter name of the single parameter of the<br />
ReverseString method is called Value. I could have used something<br />
else.<br />
resource and parameter value assignments are combined with<br />
the base URL defined on the Request tab (this base URL is set to the<br />
string shown earlier in this section).<br />
The REST call shown in Figure 6 was performed against the Data-<br />
Snap server using SSL, but not authentication. (Since this DataSnap<br />
server only permits HTTPS calls (SSL), a call using HTTP would fail. If<br />
you have downloaded the code samples, you can test this for<br />
yourself.) If your REST server requires authentication, you use the<br />
Authentication tab of the Request pane to provide the require<br />
information before clicking Send Request. Figure 8 shows a username<br />
and password entered into the Authentication tab, and the resulting<br />
response from the server. The password is masked in the figure, but<br />
trust me that I entered Delphi.<br />
I've used BASIC authentication in this case, which inserts the username<br />
and password into the HTTP header. This is how the DataSnap<br />
server is expecting to receive this data when authentication is implemented.<br />
There are three additional authentication methods. SIMPLE<br />
passes the user name and password in a manner similar to how you<br />
would pass a username and password field from an HTML form. The<br />
last two, OAUTH and OAUTH2, use the corresponding protocol for<br />
OAuth. OAuth is an open standard for delegated authorization,<br />
permitting a site to accept access tokens from a third party service, for<br />
example, authorizing access to a site using the user's Facebook or<br />
Google account.<br />
The REST Client Library<br />
In addition to the REST Debugger, the release of Delphi XE5 also saw<br />
the introduction of the REST Client Library, a set of cross-platform<br />
components that you can use from any of Delphi's supported platforms.<br />
In this section I will focus on four of these: TRESTClient,<br />
TRESTRequest, and TRESTResponse. I will also talk about the<br />
authentication components, but only in passing.<br />
Fig. 7: You use the Parameters tab of the Request pane to define the<br />
resource and assign values to your named parameters<br />
If you enter a base URL in the URL field of the Request tab of the<br />
Request pane, you use the Parameters pane to enter the resource,<br />
after which you assign a value to each of the parameter placeholders<br />
appearing in the resource. This can be seen in the Figure 7, where the<br />
At a minimum, a REST request requires that you use a TRESTClient<br />
and a TRESTRequest. The TRESTClient takes responsibility for the<br />
HTTP communication to the REST server, and also holds the REST<br />
service end point, or base URL. Most applications need only one<br />
TRESTClient for each REST service to which it will connect.<br />
In most applications you will have one TRESTRequest for each<br />
method you want to execute. A given TRESTRequest object holds the<br />
resource definition for the corresponding method using the format<br />
described in Figure 7, as well as any parameters, which are used to<br />
associate values with each of the names that appear in the resource.<br />
The Client property of each TRESTRequest must point to a properly<br />
configured TRESTClient component.<br />
The use of TRESTResponse is optional. You use this component if<br />
you want to persist any data returned from a TRESTRequest. The<br />
TRESTRequest in question is the one whose Response property<br />
points to the TRESTResponse.<br />
If you execute a TRESTRequest, and its Response property does not<br />
point to a TRESTResponse, a TRESTResponse is created on-the-fly,<br />
and you can access it using the Response property of the TRESTRequest<br />
any time after the successful execution of the TRESTRequest<br />
and prior to freeing the TRESTRequest or clearing its content by calling<br />
ResetToDefaults.<br />
Fig. 8: With Authorization turned on, you need to pass a user<br />
name and password to the server<br />
The use of TRESTClient and TRESTRequest is demonstrated in the<br />
RESTClientDemo project, whose main form is shown in Figure 9. This<br />
project invokes three of the methods exported by the DataSnap REST<br />
server (the methods being invoked should be pretty obvious). There is<br />
a single TRESTClient, which points to the base URL of the DataSnap<br />
magazine voor software development 39
DELPHI<br />
server. In addition, there are three TRESTRequest objects, one for<br />
each of the methods that are invoked.<br />
RRGetCustomerCDS.Execute;<br />
cds.XMLData := RRGetCustomerCDS.Response.Content;<br />
DataSource1.DataSet := cds;<br />
end;<br />
Figure 10 shows the running application. In this figure, both the<br />
ReverseString and Get Customer Data buttons have been pressed.<br />
Fig. 9: The main form of RESTClientDemo<br />
In this particular project there was no need to employ a TREST<br />
Response component, since the returned data is already being<br />
persisted in the application's user interface. For the ReverseString and<br />
ReverseStringRaw REST calls, the data is being stored in a memo.<br />
The value returned by GetCustomerCDSRaw is being stored in a<br />
ClientDataSet.<br />
There is an additional REST client component on this form, the<br />
TRESTBasicAuthentication component. This component, and its<br />
proper configuration, is required if your REST service implements<br />
authentication.<br />
Here are the three event handlers, each one associated with one of the<br />
buttons that appear on the left side of this form. Each event handler<br />
assigns values to the named parameters in the associated<br />
TRESTRequest.Resource properties, with the exception of Get<br />
CustomerCDSRaw, which has no parameters.<br />
procedure TForm1.ReverseStringBtnClick(Sender: TObject);<br />
begin<br />
RRReverseString.Params.ParameterByName('ValueToReverse').Valu<br />
e :=<br />
ValueToReverseEdit.Text;<br />
RRReverseString.Execute;<br />
ResponseMemo.Lines.Text := RRReverseString.Response.Content;<br />
end;<br />
procedure TForm1.ReverseStringRawBtnClick(Sender: TObject);<br />
begin<br />
RRReverseStringRaw.Params.ParameterByName('ValueToReverse').Value<br />
:=<br />
ValueToReverseEdit.Text;<br />
RRReverseStringRaw.Execute;<br />
ResponseMemo.Lines.Text := RRReverseStringRaw.Response.Content;<br />
end;<br />
procedure TForm1.GetCustomerDataBtnClick(Sender: TObject);<br />
var<br />
cds: TClientDataSet;<br />
begin<br />
if DataSource1.DataSet nil then<br />
DataSource1.DataSet.Free;<br />
cds := TClientDataSet.Create(Self);<br />
Fig. 10: The running RESTClientDemo application<br />
You can download the code sample for this article from the following<br />
URL: http://www.JensenDataSystems.com/sdnmag_rest.zip<br />
Summary<br />
In this article I have introduced the REST Debugger and several of the<br />
components of the REST Client Library. In the next issue of the <strong>SDN</strong><br />
<strong>Magazine</strong> I will demonstrate more capabilities of the REST debugger,<br />
as well as show how to use the REST Debugger and REST Client<br />
Library on REST services other than DataSnap. •<br />
Cary Jensen<br />
Cary Jensen is Chief Technology<br />
Officer of Jensen Data Systems.<br />
Since 1988 he has built and<br />
deployed database applications in a<br />
wide range of industries. Cary is an<br />
Embarcadero MVP, a best selling<br />
author of more than 20 books on software development, and<br />
holds a Ph.D. in Engineering Psychology, specializing in humancomputer<br />
interaction. His latest book is Delphi in Depth: Client-<br />
DataSets 2nd Edition. You can learn more about this book at<br />
http://www.JensenDataSystems/cdsbook2.<br />
OPROEP!<br />
Lijkt het je leuk een bijdrage te leveren aan (het volgende) <strong>SDN</strong> magazine?<br />
We nodigen je van harte uit om een artikel te schrijven over je vakgebied,<br />
over ontwikkelingen en/ of achtergronden.<br />
Stuur je kopij naar redactie@sdn.nl, er zit een auteur in ons allemaal!<br />
40<br />
MAGAZINE
TFS<br />
Wouter de Kort<br />
Ken jij Microsoft Test Manager?<br />
At <strong>SDN</strong>'s Software Development Conference in Papendal this December I presented a session<br />
on DataSnap and REST using FireDAC. In that presentation I demonstrated a DataSnap server<br />
that used FireDAC FDMemTables to create special data streams that could be delivered to client<br />
applications written in Delphi, and from which specialized streams containing a user's updates<br />
to the data could be returned. Importantly, the client/server communication made use of HTTP<br />
(hypertext transfer protocol) requests and JSON (JavaScript Object Notation), two elements<br />
central to a distributed application style typically referred to as REST (REpresentational State<br />
Transfer).<br />
DevOps, Application Lifecycle Management, Agile. Het zijn termen<br />
die we allemaal kennen. Maar hoe past een tester binnen dit verhaal?<br />
We weten allemaal dat Microsoft voor developers erg goede tooling<br />
heeft. Teams gebruiken vaak versie beheer, build servers en project<br />
management tooling in TFS. Sommige teams gaan echt al richting<br />
continuous deployment door bijvoorbeeld Release Management te<br />
gebruiken. Maar hoe zit het met testers? Worden zij ook ondersteund?<br />
Vaak zie ik testers hun test cases nog bijhouden in Excel. Of ze<br />
gebruiken totaal andere tooling van bijvoorbeeld HP of Tosca zonder<br />
verder echt te integreren met de ontwikkelaars. Testers zijn veel tijd<br />
kwijt aan het handmatig uitvoeren van test cases en het bijhouden van<br />
voortgang. Maar als je echt naar continuous delivery wilt, kan een niet<br />
efficiënt test proces een steeds groter probleem worden.<br />
Fast forwarding van tests<br />
In plaats van Excel lijstjes te gebruiken laat MTM testers hun tests bijhouden,<br />
organiseren en delen met het team als een echt onderdeel<br />
van TFS. Figuur 1 laat een test case zien zoals die er in MTM uitziet.<br />
Eén van de best bewaarde geheimen van de Microsoft ALM tooling is<br />
Microsoft Test Manager (MTM). MTM is voor testers wat Visual Studio<br />
voor ontwikkelaars is. Door testers MTM te laten gebruiken integreren<br />
ze helemaal in het ALM proces.<br />
In dit artikel wil ik een paar van de mogelijkheden van MTM bespreken<br />
die mij enthousiast hebben gemaakt en die jou kunnen helpen om met<br />
testers binnen je organisatie in gesprek te gaan.<br />
Ontmoet Microsoft Test Manager<br />
Als ontwikkelaars gebruiken we Visual Studio. Project managers<br />
gebruiken de web-interface van TFS en Excel. Testers gebruiken<br />
Microsoft Test Manager. MTM is speciaal gemaakt voor testers.<br />
De applicatie is een stuk<br />
eenvoudiger te gebruiken dan<br />
Visual Studio en helpt testers<br />
echt om hun werk gedaan te<br />
krijgen.<br />
MTM is een onderdeel van Visual Studio Test Professional.<br />
Je kunt een gratis 90 dagen trial downloaden op<br />
http://www.visualstudio.com/products/visual-studio-testprofessional-with-msdn-vs<br />
Fig. 1: Een test case in MTM<br />
Hier zie je een test case met een aantal stappen en het verwachte<br />
resultaat. Als een tester deze test case nu gaat draaien verschijnt de<br />
interface in Figuur 2 bij de tester op zijn scherm. Tijdens het afspelen<br />
van de test kan de tester hierin direct bijhouden welke stappen goed<br />
gaan, eventueel commentaar toevoegen of direct een bug inschieten<br />
in TFS.<br />
Terwijl de tester zijn test case uitvoert, helpt MTM door de acties van<br />
de tester op te nemen. Stel bijvoorbeeld dat je een wizard test waarbij<br />
je verschillende velden moet invullen om door te kunnen naar de<br />
volgende stap. MTM helpt je door het invullen van de velden op te<br />
nemen en de volgende keer dat je deze test case uitvoert kun<br />
je automatisch doorspoelen en worden alle velden automatisch voor<br />
je ingevuld.<br />
Stel je eens voor hoeveel tijd dit een tester bespaart. In plaats van<br />
iedere keer handmatig alle stappen herhalen kan de tester de minder<br />
belangrijke stappen nu doorspoelen en zich focussen op de stappen<br />
die echt interessant zijn.<br />
magazine voor software development 41
TFS<br />
Dit soort opnames zijn dan weer de basis<br />
voor volledig geautomatiseerde testen die<br />
bijvoorbeeld door de build server of<br />
tijdens een automatische deployment<br />
gedraaid kunnen worden zodat er nog<br />
meer tijd bespaart wordt.<br />
plan tot je beschikking. In plaats daarvan ga je naar eigen inzicht door<br />
de applicatie heen terwijl ondertussen MTM alles bijhoud wat je doet.<br />
Vind je dus een bug, dan kun je rechtstreeks vanuit je Exploratory Testing<br />
sessie een bug aanmaken met daaraan gekoppeld de stappen<br />
die je hebt gedaan en eventueel weer info zoals een video opname,<br />
Event Log, System Information of IntelliTrace data.<br />
Fig. 2: Uitvoeren van een test<br />
case<br />
Data Collection<br />
Naast dat MTM de acties die een tester<br />
uitvoert kan bijhouden, kan er nog veel<br />
meer data automatisch verzameld<br />
worden. Standaard wordt er bijvoorbeeld<br />
bijgehouden op wat voor systeem de<br />
tester zijn werk doet zoals Windows<br />
versie, gebruikte browser en systeem<br />
specificaties. Maar zoals Figuur 3 laat zien<br />
is er veel meer mogelijk.<br />
Met één simpel vinkje kun je hier bijvoorbeeld<br />
een video opname maken van het<br />
scherm van de tester en eventueel zelfs<br />
audio opnamen. Of wat dacht je van<br />
IntelliTrace data, event logs en code<br />
coverage info? Al deze data wordt<br />
gekoppeld aan het test result en<br />
toegevoegd aan bugs die de tester<br />
inschiet. Dus als ontwikkelaar heb je nu<br />
een stappenplan van wat de tester heeft<br />
gedaan samen met allerlei data waaronder<br />
zelfs een video opname.<br />
Als je naar Figuur 4 kijkt zie je een bug die is aangemaakt vanuit een<br />
Exploratory Testing sessie. Als je kijkt naar de Steps To Reproduce zie<br />
je dat MTM precies heeft bijgehouden welke acties de gebruiker heeft<br />
uitgevoerd. De andere tabs geven extra info die allemaal in TFS wordt<br />
opgeslagen.<br />
Fig. 4: Bug vanuit Exploratory Testing<br />
MTM is cool!<br />
Dit zijn maar een paar features van MTM waar ik enthousiast van werd.<br />
Maar er zijn er nog veel meer. Denk bijvoorbeeld aan het gebruik van<br />
parameters in test cases, rapportages over je voortgang, het gebruik<br />
van verschillende systeem configuraties voor testen (bijvoorbeeld<br />
Windows 7 en 8, of IE en Chrome) en nog veel meer.<br />
Beginnen met MTM is eenvoudig. Download gewoon de trial en<br />
koppel deze aan een gratis Visual Studio Online account zodat je<br />
meteen kunt beginnen. Als je wat gerichter met MTM aan de gang wilt<br />
kun je ook de Brian Keller Virtual Machine downloaden compleet met<br />
Hands On Labs die je alles van MTM laten zien. •<br />
Fig. 3: Data Collectors<br />
Een andere optie die zeker interessant is, is Test Impact analysis.<br />
Als je je test omgevingen ook koppelt aan TFS, is TFS instaat om te<br />
analyseren welke code er tussen verschillende builds is gewijzigd en<br />
welke test cases daar dan weer bij horen. Op deze manier krijgt een<br />
tester dus een overzicht van de test cases die het belangrijkste zijn<br />
om te draaien voor een nieuwe versie van de applicatie.<br />
Exploratory Testing<br />
Tot nu toe hebben we vooral gekeken naar het gebruik van vooraf<br />
geschreven test cases. Maar wat nu als je in een Agile proces deze<br />
test cases nog niet hebt gemaakt? Of wat als je als ontwikkelaar of<br />
stakeholder gewoon even door de applicatie heen wilt gaan om te<br />
kijken of bepaalde dingen werken? En natuurlijk wil je dan, dat als het<br />
mis gaat je ook nog kunt reproduceren waar de fout zit.<br />
Dit is waar je Exploratory Testing voor gebruikt. Als je een Exploratory<br />
Testing sessie begint vanuit MTM, heb je geen voor gedefinieerd test<br />
Wouter de Kort<br />
Wouter begon met software ontwikkeling<br />
toen hij 7 was. Hij werkt nu als<br />
Lead Microsoft ALM Consultant bij<br />
Ordina waar hij leiding geeft aan een<br />
team van ALM Consultants. Wouter<br />
helpt organisaties om voorop te blijven<br />
met alle ontwikkelingen op de<br />
Microsoft Stack. Hij richt zich vooral op Application Lifecycle<br />
Management en software architectuur. Hij houdt er van om complexe<br />
problemen op te lossen en anderen nieuwe dingen te leren.<br />
Wouter heeft een paar boeken geschreven, is een Microsoft Certified<br />
Trainer en ALM Ranger. Je kunt hem vinden op Twitter<br />
(@wouterdekort) en op zijn blog http://wouterdekort.blogspot.com<br />
42<br />
MAGAZINE
CLOUD<br />
Marcel Meijer<br />
API Management<br />
Het is voor leveranciers van producten bijna onmogelijk om voor ieder platform mobiele<br />
applicaties te maken. Natuurlijk kun je dan als leverancier zorgen voor een goede responsieve<br />
mobiele website. Het nadeel van deze manier is dat je de capaciteiten en mogelijkheden van een<br />
mobiel device niet volledig uit nut.<br />
Daarom zijn er ook leveranciers die hun backoffice via API’s beschikbaar<br />
stellen aan de wereld. Meestal wil je dat niet zonder pardon doen<br />
en wil je er als leverancier wellicht geld aan verdienen. Dus je wil een<br />
Developer portal maken met verschillende groepen, help pagina’s,<br />
voorbeeldcode, monitoring, issue lijst, FAQ, maar ook malafide<br />
gebruikers/applicaties blacklisten. Kortom het vergt meer dan even<br />
het beschikbaar stellen van een paar webservicesje.<br />
Enige tijd geleden had ik ook zo’n droom. Ik wilde voor de <strong>SDN</strong> een<br />
evaluatie app maken. Bezoekers van een <strong>SDN</strong> event kunnen dan<br />
mobiel een evaluatie formulier invullen. Deze evaluatie data wordt in<br />
een data store op Azure bewaard. Uiteraard wil ik niet mijn tokens/<br />
connectionstrings/passwords etc in mijn mobiele apps opslaan.<br />
En aangezien ik niet voor elk device zelf een applicatie kan schrijven,<br />
deze gegevens delen met wildvreemde developers.<br />
Uiteraard is het dan wel verstandig om de endpoints op deze URL te<br />
beveiligen met een Certificaten, UserName/Password combinatie of<br />
via OAuth.<br />
Dit is de management portal voor de beheerder van de<br />
API(https://marcelmeijer.portal. azure-api.net/admin), voor de ontwikkelaars<br />
is er een aparte portal (https://marcelmeijer.portal.azureapi.net/).<br />
Deze kan tot op zekere hoogte ook gestyled en aangepast<br />
worden. Deze Developer portal is redelijk compleet. Alle genoemde<br />
zaken zijn hier wel te vinden.<br />
Dus bedacht ik dat ik een aantal Webapi<br />
services beschikbaar moest stellen. Maar<br />
zoals hierboven genoemd, had ik behoefte<br />
aan eer developers portal om mijn services<br />
uit te leggen en wat ze opleveren. Dat is veel<br />
werk voor zo’n API als dit. Dit is mijn landingspagina nu;<br />
http://sdnevalapp.azurewebsites.net/.<br />
Gelukkig is daar een oplossing<br />
voor op het Azure platform. De<br />
API management service (documentatie<br />
site). Als je de service<br />
gemaakt hebt, dan is er een<br />
aparte portal (https://marcelmeijer.portal.azure-api.net/<br />
admin) waar je alle instellingen<br />
doet, waar je de metrics van je API ziet, de applicaties die aangemeld<br />
zijn, welke API het vaakst aangeroepen wordt etc.<br />
Bij de settings kun je dan de<br />
webservices beschikbaar stellen.<br />
De verschillende operaties,<br />
welke http verb, welke responses<br />
er verwacht kunnen<br />
worden, welke URL, omschrijving<br />
en helpteksten. De URL<br />
naar de bron services kan ook<br />
on-premises gehost worden.<br />
Zo is er een handig overzicht van de beschikbare API’s.<br />
Van de beschikbare API kun je de beschikbare endpoints zien. Je ziet<br />
dan de omschrijving en de URL om API aan te spreken. Om het endpoint<br />
te gebruiken moet je een subscription key meegeven. Het hele<br />
idee van deze portal is dan ook<br />
om gebruik te reguleren en met<br />
behulp van de subscription key<br />
is de API per applicatie/ontwikkelaar<br />
apart. Aangezien de endpoints<br />
aan de basis beveiligd<br />
zijn met Certificaten, Username/<br />
Passwords of via OAuth, heeft<br />
het geen zin om rechtstreeks<br />
naar de bron te gaan.<br />
Op deze Developer portal kun je<br />
API methode ook uitproberen<br />
en de verschillende gedefinieerde<br />
HTTP acties uitvoeren. Je<br />
krijgt dan de trace en het resultaat<br />
te zien.<br />
Helemaal onderaan de pagina<br />
kun je per programmeertaal<br />
voorbeeldcode krijgen. Alles om<br />
de ‘klanten’ van je API te<br />
ondersteunen en te helpen.<br />
Door deze Azure service kun je je richten op het echte leuke en<br />
belangrijkste van de API, de functionaliteit. Waarom zou je het zelf<br />
doen, als je gebruik kunt maken van de expertise van andere.<br />
“You can reach further while standing on the shoulders of giants”. •<br />
magazine voor software development 43