Buy ebook Data pipelines with apache airflow 1st edition bas p harenslak julian rutger de ruiter che

Page 1


Visit to download the full and correct content document: https://textbookfull.com/product/data-pipelines-with-apache-airflow-1st-edition-bas-p-h arenslak-julian-rutger-de-ruiter-2/

More products digital (pdf, epub, mobi) instant download maybe you interests ...

Data Pipelines with Apache Airflow 1st Edition Bas P Harenslak Julian Rutger De Ruiter

https://textbookfull.com/product/data-pipelines-with-apacheairflow-1st-edition-bas-p-harenslak-julian-rutger-de-ruiter-2/

Learning Apache Drill Query and Analyze Distributed Data Sources with SQL 1st Edition Charles Givre

https://textbookfull.com/product/learning-apache-drill-query-andanalyze-distributed-data-sources-with-sql-1st-edition-charlesgivre/

Data Pipelines Pocket Reference: Moving and Processing Data for Analytics 1st Edition James Densmore

https://textbookfull.com/product/data-pipelines-pocket-referencemoving-and-processing-data-for-analytics-1st-edition-jamesdensmore/

Azure Data Factory Cookbook: Data engineers guide to build and manage ETL and ELT pipelines with data integration , 2nd Edition Dmitry Foshin

https://textbookfull.com/product/azure-data-factory-cookbookdata-engineers-guide-to-build-and-manage-etl-and-elt-pipelineswith-data-integration-2nd-edition-dmitry-foshin/

Data Engineering with AWS: Acquire the skills to design and build AWS-based data transformation pipelines like a pro 2nd Edition Eagar

https://textbookfull.com/product/data-engineering-with-awsacquire-the-skills-to-design-and-build-aws-based-datatransformation-pipelines-like-a-pro-2nd-edition-eagar/

Watermarking Security 1st Edition Patrick Bas

https://textbookfull.com/product/watermarking-security-1stedition-patrick-bas/

Beginning Jenkins Blue Ocean: Create Elegant Pipelines

With Ease 1st Edition Nikhil Pathania

https://textbookfull.com/product/beginning-jenkins-blue-oceancreate-elegant-pipelines-with-ease-1st-edition-nikhil-pathania/

Data Protection: Ensuring Data Availability 1st Edition

Preston De Guise

https://textbookfull.com/product/data-protection-ensuring-dataavailability-1st-edition-preston-de-guise/

Data Protection: Ensuring Data Availability 2nd Edition

Preston De Guise

https://textbookfull.com/product/data-protection-ensuring-dataavailability-2nd-edition-preston-de-guise/

insidefrontcover

Data Pipelines

Tocommentgoto liveBook

Manning

Shelter Island

Formoreinformationon thisandotherManningtitlesgoto manning.com

Copyright

For online information and ordering of these and other Manning books, please visit manning.com The publisheroffersdiscountsonthesebookswhenorderedinquantity.

Formoreinformation,pleasecontact

SpecialSalesDepartment

ManningPublicationsCo

20 Baldwin Road POBox761

ShelterIsland,NY11964

Email:orders@manning.com ©2021 by Manning PublicationsCo. Allrights reserved.

No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by means electronic, mechanical, photocopying, or otherwise, without prior written permission of the publisher.

Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in the book, and Manning Publications was aware of a trademarkclaim,thedesignationshavebeenprintedininitialcapsorallcaps.

♾ Recognizing the importance of preserving what has been written, it is Manning’s policy to have the books we publish printed on acid-free paper, and we exert our best efforts to that end. Recognizing also our responsibility to conserve the resources of our planet, Manning books are printed on paper that is at least15percentrecycledandprocessedwithouttheuseofelementalchlorine.

ManningPublicationsCo.

20BaldwinRoad Technical POBox 761

Shelter Island,NY11964

Developmenteditor: Tricia Louvar

Technical development editor: ArthurZubarev

Revieweditor: Aleks Dragosavljević

Productioneditor: DeirdreS.Hiam

Copyeditor: MicheleMitchell

Proofreader: KeriHales

Technicalproofreader: AlKrinker

Typesetter: DennisDalinnik

Coverdesigner: MarijaTudor

ISBN:9781617296901

briefcontents

Part 1. Getting started

1MeetApacheAirflow

2AnatomyofanAirflowDAG

3SchedulinginAirflow

4TemplatingtasksusingtheAirflowcontext

5Definingdependenciesbetweentasks

Part 2. Beyond the basics

6Triggeringworkflows

7Communicatingwithexternalsystems

8Buildingcustomcomponents

9Testing

10Runningtasksincontainers

Part 3. Airflow in practice

11Bestpractices

12OperatingAirflowinproduction

13SecuringAirflow

14Project:FindingthefastestwaytogetaroundNYC

Part 4. In the clouds

15Airflowintheclouds

16AirflowonAWS

17AirflowonAzure

18AirflowinGCP

appendixA.Runningcodesamples

appendixB.PackagestructuresAirflow1and2 appendixC.Prometheusmetricmapping

contents

preface acknowledgments aboutthisbook abouttheauthors aboutthecoverillustration

Part 1. Getting started

1 MeetApacheAirflow

1.1 Introducingdatapipelines

Datapipelinesasgraphs

Executinga pipelinegraph

Pipelinegraphsvs.sequentialscripts

Runningpipelineusingworkflowmanagers

1.2 IntroducingAirflow

Definingpipelinesflexiblyin(Python)code

Schedulingandexecutingpipelines

Monitoringand handling failures

Incrementalloadingandbackfilling

1.3 WhentouseAirflow

ReasonstochooseAirflow

Reasonsnot tochooseAirflow

1.4 Therestofthisbook

2 AnatomyofanAirflowDAG

2.1 Collectingdatafromnumeroussources

Exploringthedata

2.2 WritingyourfirstAirflowDAG

Tasksvs. operators

RunningarbitraryPythoncode

2.3 RunningaDAGinAirflow

RunningAirflowinaPythonenvironment

RunningAirflowinDockercontainers

Inspectingthe AirflowUI

2.4 Runningatregularintervals

2.5 Handlingfailingtasks

3 SchedulinginAirflow

3.1 Anexample:Processinguserevents

3.2 Runningatregularintervals

Definingschedulingintervals

Cron-basedintervals

Frequency-basedintervals

3.3 Processingdataincrementally

Fetchingeventsincrementally

Dynamictimereferencesusingexecutiondates

Partitioningyourdata

3.4 UnderstandingAirflow’sexecutiondates

Executingwork infixed-lengthintervals

3.5 Usingbackfillingtofillinpastgaps

Executingwork backintime

3.6 Bestpracticesfordesigningtasks

Atomicity

Idempotency

4 TemplatingtasksusingtheAirflowcontext

4.1 InspectingdataforprocessingwithAirflow

Determininghow toloadincrementaldata

4.2 TaskcontextandJinjatemplating

Templatingoperatorarguments

Whatisavailablefortemplating?

TemplatingthePythonOperator

Providingvariables tothePythonOperator

Inspectingtemplatedarguments

4.3 Hookingupothersystems

5 Definingdependenciesbetweentasks

5.1 Basicdependencies

Lineardependencies

Fan-in/-outdependencies

5.2 Branching

Branching within tasks

Branching within the DAG

5.3 Conditionaltasks

Conditionswithin tasks

Makingtasks conditional

Usingbuilt-inoperators

5.4 Moreabouttriggerrules

Whatisatriggerrule?

Theeffectof failures

Othertriggerrules

5.5 Sharingdatabetweentasks

SharingdatausingXComs

When(not)touseXComs

UsingcustomXCombackends

5.6 ChainingPythontaskswiththeTaskflowAPI

SimplifyingPythontaskswiththeTaskflow API

When(not)tousetheTaskflowAPI

Part 2. Beyond the basics

6 Triggeringworkflows

6.1 Pollingconditionswithsensors

Pollingcustom conditions

Sensorsoutsidethehappy flow

6.2 TriggeringotherDAGs

Backfillingwith the TriggerDagRunOperator

PollingthestateofotherDAGs

6.3 StartingworkflowswithREST/CLI

7 Communicatingwithexternalsystems

7.1 Connectingtocloudservices

Installingextra dependencies

Developingamachine learningmodel

Developinglocally with externalsystems

7.2 Movingdatafrombetweensystems

Implementing aPostgresToS3Operator

Outsourcingtheheavywork

8 Buildingcustomcomponents

8.1 StartingwithaPythonOperator

SimulatingamovieratingAPI

FetchingratingsfromtheAPI

BuildingtheactualDAG

8.2 Buildingacustomhook

Designingacustomhook

BuildingourDAG with theMovielensHook

8.3 Buildingacustomoperator

Defininga customoperator

Buildinganoperatorforfetchingratings

8.4 Buildingcustomsensors

8.5 Packagingyourcomponents

Bootstrappinga Pythonpackage

Installingyourpackage

9 Testing

9.1 Gettingstartedwithtesting

IntegritytestingallDAGs

Settingupa CI/CDpipeline

Writingunittests

Pytestprojectstructure

Testing with filesondisk

9.2 WorkingwithDAGsandtaskcontextintests

Workingwith external systems

9.3 Usingtestsfordevelopment

Testing completeDAGs

9.4 EmulateproductionenvironmentswithWhirl

9.5 CreateDTAPenvironments

10 Runningtasksincontainers

10.1 Challengesofmanydifferentoperators

Operatorinterfacesandimplementations

Complex andconflictingdependencies

Movingtowardagenericoperator

10.2 Introducingcontainers

Whatarecontainers?

RunningourfirstDockercontainer

Creatinga Dockerimage

Persistingdatausingvolumes

10.3 ContainersandAirflow

Tasksin containers

Whyusecontainers?

10.4 RunningtasksinDocker

IntroducingtheDockerOperator

Creatingcontainerimagesfortasks

Buildinga DAG with Dockertasks

Docker-basedworkflow

10.5 RunningtasksinKubernetes

IntroducingKubernetes

SettingupKubernetes

UsingtheKubernetesPodOperator

DiagnosingKubernetes-relatedissues

Differenceswith Docker-basedworkflows

Part 3. Airflow in practice

11 Bestpractices

11.1 WritingcleanDAGs

Usestyleconventions

Manage credentialscentrally

Specifyconfigurationdetailsconsistently

Avoid doinganycomputationinyourDAG definition

Usefactoriesto generatecommonpatterns

Group relatedtasksusingtaskgroups

CreatenewDAGsforbig changes

11.2 Designingreproducibletasks

Alwaysrequiretasksto beidempotent

Task resultsshould bedeterministic

Designtasksusingfunctionalparadigms

11.3 Handlingdataefficiently

Limittheamountof data beingprocessed

Incrementalloading/processing

Cache intermediatedata

Don’tstoredata onlocalfilesystems

Offloadwork toexternal/sourcesystems

11.4 Managingyourresources

Managingconcurrencyusingpools

Detectinglong-runningtasks usingSLAsandalerts

12 OperatingAirflowinproduction

12.1 Airflowarchitectures

Whichexecutor is right forme?

Configuring ametastoreforAirflow

A closerlookatthescheduler

12.2 Installingeachexecutor

SettinguptheSequentialExecutor

SettinguptheLocalExecutor

SettinguptheCeleryExecutor

SettinguptheKubernetesExecutor

12.3 CapturinglogsofallAirflowprocesses

Capturingthewebserveroutput

Capturingthescheduleroutput

Capturingtasklogs

Sendinglogsto remotestorage

12.4 VisualizingandmonitoringAirflowmetrics

Collecting metricsfromAirflow

Configuring Airflowtosendmetrics

Configuring Prometheustocollectmetrics

CreatingdashboardswithGrafana

Whatshouldyou monitor?

12.5 Howtogetnotifiedofafailingtask

Alertingwithin DAGs andoperators

Definingservice-levelagreements

Scalabilityandperformance

Controllingthemaximumnumber ofrunningtasks

System performanceconfigurations

Runningmultipleschedulers

13 SecuringAirflow

13.1 SecuringtheAirflowwebinterface

AddinguserstotheRBACinterface

Configuring the RBACinterface

13.2 Encryptingdataatrest

Creatinga Fernet key

13.3 ConnectingwithanLDAPservice

Understanding LDAP

Fetchingusersfroman LDAPservice

13.4 Encryptingtraffictothewebserver

Understanding HTTPS

Configuring acertificate forHTTPS

13.5 Fetchingcredentialsfromsecretmanagementsystems

14 Project:FindingthefastestwaytogetaroundNYC

14.1 Understandingthedata

YellowCabfileshare

CitiBikeRESTAPI

Deciding on aplanofapproach

14.2 Extractingthedata

DownloadingCitiBikedata

DownloadingYellowCab data

14.3 Applyingsimilartransformationstodata

14.4 Structuringadatapipeline

14.5 Developingidempotentdatapipelines

Part 4. In the clouds

15 Airflowintheclouds

15.1 Designing(cloud)deploymentstrategies

15.2 Cloud-specificoperatorsandhooks

15.3 Managedservices

Astronomer.io

Google CloudComposer

Amazon ManagedWorkflowsforApacheAirflow

15.4 Choosingadeploymentstrategy

16 AirflowonAWS

16.1 DeployingAirflowinAWS

Pickingcloudservices

Designingthenetwork

AddingDAGsyncing

Scalingwith the CeleryExecutor

Furthersteps

16.2 AWS-specifichooksandoperators

16.3 Usecase:ServerlessmovierankingwithAWSAthena Overview

Settingupresources

BuildingtheDAG

Cleaning up

17 AirflowonAzure

17.1 DeployingAirflowinAzure

Pickingservices

Designingthenetwork

Scalingwith the CeleryExecutor

Furthersteps

17.2 Azure-specifichooks/operators

17.3 Example:ServerlessmovierankingwithAzureSynapse Overview

Settingupresources

BuildingtheDAG

Cleaning up

18 AirflowinGCP

18.1 DeployingAirflowinGCP

Pickingservices

DeployingonGKEwith Helm

Integratingwith Googleservices

Designingthenetwork

Scalingwith the CeleryExecutor

18.2 GCP-specifichooksandoperators

18.3 Usecase:ServerlessmovierankingonGCP

Uploading toGCS

GettingdataintoBigQuery

Extractingtopratings

appendixA. Runningcodesamples

appendixB. PackagestructuresAirflow1and appendixC. Prometheusmetricmapping

index

frontmatter

preface

We’ve both been fortunate to be data engineers in interesting and challenging times. For better or worse, many companies and organizations are realizing that data plays a key role in managing and improving their operations. Recent developments in machine learning and AI have opened a slew of new opportunities to capitalize on. However, adopting data-centric processes is often difficult, as it generally requires coordinating jobs across many different heterogeneous systems and tying everything togetherinanice,timelyfashionforthenextanalysisorproductdeployment.

In 2014, engineers at Airbnb recognized the challenges of managing complex data workflows within the company. To address those challenges, they started developing Airflow: an open source solution that allowed them to write and schedule workflows and monitor workflow runs using the built-in web interface.

The success of the Airflow project quickly led to its adoption under the Apache Software Foundation, first as an incubator project in 2016 and later as a top-level project in 2019. As a result, many large companiesnowrelyonAirflowfororchestratingnumerouscriticaldataprocesses.

Working as consultants at GoDataDriven, we’ve helped various clients adopt Airflow as a key component in projects involving the building of data lakes/platforms, machine learning models, and so on. In doing so, we realized that handing over these solutions can be challenging, as complex tools like Airflow can be difficult to learn overnight. For this reason, we also developed an Airflow training program at GoDataDriven, and have frequently organized and participated in meetings to share our knowledge, views, and even some open source packages. Combined, these efforts have helped us explore the intricacies of working with Airflow, which were not always easy to understand using the documentation availabletous.

In this book, we aim to provide a comprehensive introduction to Airflow that covers everything from building simple workflows to developing custom components and designing/managing Airflow deployments. We intend to complement many of the excellent blogs and other online documentation by bringing several topics together in one place, using a concise and easy-to-follow format. In doing so, we hope to kickstart your adventures with Airflow by building on top of the experience we’ve gained throughdiversechallengesoverthepastyears.

acknowledgments

This book would not have been possible without the support of many amazing people. Colleagues from GoDataDriven and personal friends supported us and provided valuable suggestions and critical insights. Inaddition,ManningEarlyAccessProgram(MEAP)readerspostedusefulcommentsintheonlineforum.

Reviewers from the development process also contributed helpful feedback: Al Krinker, Clifford Thurber, Daniel Lamblin, David Krief, Eric Platon, Felipe Ortega, Jason Rendel, Jeremy Chen, Jiri Pik, Jonathan Wood, Karthik Sirasanagandla, Kent R. Spillner, Lin Chen, Philip Best, Philip Patterson, Rambabu Posa, Richard Meinsen, Robert G. Gimbel, Roman Pavlov, Salvatore Campagna, Sebastián Palma Mardones, ThorstenWeber,UrsinStauss,andVladNavitski.

At Manning, we owe special thanks to Brian Sawyer, our acquisitions editor, who helped us shape the initial book proposal and believed in us being able to see it through; Tricia Louvar, our development

editor, who was very patient in answering all our questions and concerns, provided critical feedback on each of our draft chapters, and was an essential guide for us throughout this entire journey; and to the rest of the staff as well: Deirdre Hiam, our project editor; Michele Mitchell, our copyeditor; Keri Hales, ourproofreader;andAlKrinker,ourtechnicalproofreader

BasHarenslak

I would like to thank my friends and family for their patience and support during this year-and-a-half adventure that developed from a side project into countless days, nights, and weekends. Stephanie, thank you for always putting up with me working at the computer. Miriam, Gerd, and Lotte, thank you for your patience and belief in me while writing this book. I would also like to thank the team at GoDataDriven for their support and dedication to always learn and improve, I could not have imagined beingtheauthorofabookwhenIstartedworkingfiveyearsago.

JuliandeRuiter

First and foremost, I’d like to thank my wife, Anne Paulien, and my son, Dexter, for their endless patience during the many hours that I spent doing “just a little more work” on the book. This book would not have been possible without their unwavering support. In the same vein, I’d also like to thank our family and friends for their support and trust. Finally, I’d like to thank our colleagues at GoDataDriven for their advice and encouragement, from whom I’ve also learned an incredible amount in thepastyears.

aboutthisbook

Data Pipelines with Apache Airflow was written to help you implement data-oriented workflows (or pipelines) using Airflow. The book begins with the concepts and mechanics involved in programmatically building workflows for Apache Airflow using the Python programming language. Then the book switches to more in-depth topics such as extending Airflow by building your own custom components and comprehensively testing your workflows. The final part of the book focuses on designing and managing Airflow deployments, touching on topics such as security and designing architectures for several cloud platforms.

Whoshouldreadthisbook

Data Pipelines with Apache Airflow is written both for scientists and engineers who are looking to develop basic workflows in Airflow, as well as engineers interested in more advanced topics such as building custom components for Airflow or managing Airflow deployments. As Airflow workflows and components are built in Python, we do expect readers to have intermediate experience with programming in Python (i.e., have a good working knowledge of building Python functions and classes, understanding concepts such as *args and **kwargs, etc.). Some experience with Docker is also beneficial, as most of our code examples are run using Docker (though they can also be run locally if youwish).

Howthisbookisorganized:Aroadmap

Thebookconsistsoffoursectionsthatcoveratotalof18chapters.

Part1focusesonthebasicsofAirflow,explainingwhatAirflowisandoutliningitsbasicconcepts.

Chapter 1 discusses the concept of data workflows/pipelines and how these can be built using Apache Airflow. It also discusses the advantages and disadvantages of Airflow compared to other

solutions,includinginwhichsituationsyoumightnotwanttouseApacheAirflow.

Chapter 2 goes into the basic structure of pipelines in Apache Airflow (also known as DAGs), explainingthedifferentcomponentsinvolvedandhowthesefittogether.

Chapter 3 shows how you can use Airflow to schedule your pipelines to run at recurring time intervals so that you can (for example) build pipelines that incrementally load new data over time. The chapter also dives into some intricacies in Airflow’s scheduling mechanism, which is often a sourceofconfusion.

Chapter 4 demonstrates how you can use templating mechanisms in Airflow to dynamically include variables in your pipeline definitions. This allows you to reference things such as schedule execution dateswithinyourpipelines.

Chapter 5 demonstrates different approaches for defining relationships between tasks in your pipelines, allowing you to build more complex pipeline structures with branches, conditional tasks, andsharedvariables.

Part 2 dives deeper into using more complex Airflow topics, including interfacing with external systems, buildingyourowncustomcomponents,anddesigningtestsforyourpipelines.

Chapter 6 shows how you can trigger workflows in other ways that don’t involve fixed schedules, suchasfilesbeingloadedorviaanHTTPcall.

Chapter 7 demonstrates workflows using operators that orchestrate various tasks outside Airflow, allowingyoutodevelopaflowofeventsthroughsystemsthatarenotconnected.

Chapter 8 explains how you can build custom components for Airflow that allow you to reuse functionality across pipelines or integrate with systems that are not supported by Airflow’s built-in functionality.

Chapter 9 discusses various options for testing Airflow workflows, touching on several properties of operatorsandhowtoapproachtheseduringtesting.

Chapter 10 demonstrates how you can use container-based workflows to run pipeline tasks within Docker or Kubernetes and discusses the advantages and disadvantages of these container-based approaches.

Part 3 focuses on applying Airflow in practice and touches on subjects such as best practices, running/securingAirflow,andafinaldemonstrativeusecase.

Chapter 11 highlights several best practices to use when building pipelines, which will help you to designandimplementefficientandmaintainablesolutions.

Chapter 12 details several topics to account for when running Airflow in a production setting, such asarchitecturesforscalingout,monitoring,logging,andalerting.

Chapter 13 discusses how to secure your Airflow installation to avoid unwanted access and to minimizetheimpactinthecaseabreachoccurs.

Chapter 14 demonstrates an example Airflow project in which we periodically process rides from New York City’s Yellow Cab and Citi Bikes to determine the fastest means of transportation between neighborhoods.

Part 4 explores how to run Airflow in several cloud platforms and includes topics such as designing Airflow deployments for the different clouds and how to use built-in operators to interface with different cloudservices.

Chapter 15 provides a general introduction by outlining which Airflow components are involved in (cloud) deployments, introducing the idea behind cloud-specific components built into Airflow, and weighingtheoptionsofrollingoutyourownclouddeploymentversususingamanagedsolution.

Chapter 16 focuses on Amazon’s AWS cloud platform, expanding on the previous chapter by designing deployment solutions for Airflow on AWS and demonstrating how specific components canbeusedtoleverageAWSservices.

Chapter 17 designs deployments and demonstrates cloud-specific components for Microsoft’s Azure platform.

Chapter18addressesdeploymentsandcloud-specificcomponentsforGoogle’sGCPplatform.

People new to Airflow should read chapters 1 and 2 to get a good idea of what Airflow is and what it can do. Chapters 3–5 provide important information about Airflow’s key functionality. The rest of the book discusses topics such as building custom components, testing, best practices, and deployments andcanbereadoutoforder,basedonthereader’sparticularneeds.

Aboutthecode

All source code in listings or text is in a fixed-width font like this to separate it from ordinary text. Sometimes code is also in bold to highlight code that has changed from previous steps in the chapter,suchaswhenanewfeatureaddstoanexistinglineofcode.

In many cases, the original source code has been reformatted; we’ve added line breaks and reworked indentation to accommodate the available page space in the book. In rare cases, even this was not enough, and listings include line-continuation markers (➥). Additionally, comments in the source code have often been removed from the listings when the code is described in the text. Code annotations accompanymanyofthelistings,highlightingimportantconcepts.

References to elements in the code, scripts, or specific Airflow classes/variables/values are often in italicstohelpdistinguishthemfromthesurroundingtext.

Source code for all examples and instructions to run them using Docker and Docker Compose are available in our GitHub repository (https://github.com/BasPH/data-pipelines-with-apache-airflow) and can be downloaded via the book’s website (www.manning.com/books/data-pipelines-with-apacheairflow).

NOTE AppendixAprovidesmoredetailedinstructionsonrunning thecodeexamples.

All code samples have been tested with Airflow 2.0. Most examples should also run on older versions of Airflow (1.10), with small modifications. Where possible, we have included inline pointers on how to do so. To help you account for differences in import paths between Airflow 2.0 and 1.10, appendix B providesanoverviewofchangedimportpathsbetweenthetwoversions.

LiveBookdiscussionforum

Purchase of Data Pipelines with Apache Airflow includes free access to a private web forum run by Manning Publications where you can make comments about the book, ask technical questions, and receive help from the author and other users. To access the forum and subscribe to it, go to https://livebook.manning.com/#!/book/data-pipelines-with-apache-airflow/discussion. This page provides information on how to get on the forum once you’re registered, what kind of help is available, anditsrulesofconduct.

Manning’s commitment to our readers is to provide a venue where a meaningful dialogue between individual readers and between readers and the authors can take place. It is not a commitment to any specific amount of participation on the part of the authors, whose contribution to the forum remains voluntary (and unpaid). We suggest you try asking the authors some challenging questions lest their interest stray! The forum and the archives of previous discussions will be accessible from the publisher’s websiteaslongasthebookisinprint.

abouttheauthors

Bas Harenslak is a data engineer at GoDataDriven, a company developing data-driven solutions located in Amsterdam, Netherlands. With a background in software engineering and computer science, he enjoys working on software and data as if they are challenging puzzles. He favors working on open source software, is a committer on the Apache Airflow project, and is co-organizer of the Amsterdam Airflowmeetup.

Julian de Ruiter is a machine learning engineer with a background in computer and life sciences and has a PhD in computational cancer biology. As an experienced software developer, he enjoys bridging the worlds of data science and engineering by using cloud and open source software to develop productionready machine learning solutions. In his spare time, he enjoys developing his own Python packages, contributingtoopensourceprojects,andtinkeringwithelectronics.

aboutthecoverillustration

The figure on the cover of Data Pipelines with Apache Airflow is captioned “Femme de l’Isle de Siphanto,” or Woman from Island Siphanto. The illustration is taken from a collection of dress costumes from various countries by Jacques Grasset de Saint-Sauveur (1757–1810), titled Costumes de Différents Pays, published in France in 1797. Each illustration is finely drawn and colored by hand. The rich variety of Grasset de Saint-Sauveur’s collection reminds us vividly of how culturally apart the world’s towns and regions were just 200 years ago. Isolated from each other, people spoke different dialects and languages. In the streets or in the countryside, it was easy to identify where they lived and what their tradeorstationinlifewasjustbytheirdress.

The way we dress has changed since then and the diversity by region, so rich at the time, has faded away. It is now hard to tell apart the inhabitants of different continents, let alone different towns, regions, or countries. Perhaps we have traded cultural diversity for a more varied personal life—certainly foramorevariedandfast-pacedtechnologicallife.

At a time when it is hard to tell one computer book from another, Manning celebrates the inventiveness and initiative of the computer business with book covers based on the rich diversity of regional life of twocenturiesago,broughtbacktolifebyGrassetdeSaint-Sauveur’spictures.

Part1. Gettingstarted

This part of the book will set the stage for your journey into building pipelines for all kinds of wonderful data processes using Apache Airflow. The first two chapters are aimed at giving you an overviewofwhatAirflowisandwhatitcandoforyou.

First, in chapter 1, we’ll explore the concepts of data pipelines and sketch the role Apache Airflow plays in helping you implement these pipelines. To set expectations, we’ll also compare Airflow to several other technologies, and discuss when it might or might not be a good fit for your specific use case. Next, chapter 2 will teach you how to implement your first pipeline in Airflow. After building the pipeline, we’llalsoexaminehowtorunthispipelineandmonitoritsprogressusingAirflow’swebinterface.

Chapters 3–5 dive deeper into key concepts of Airflow to give you a solid understanding of Airflow’s underpinnings.

Chapter 3 focuses on scheduling semantics, which allow you to configure Airflow to run your pipelines at regular intervals. This lets you (for example) write pipelines that load and process data efficiently on a daily, weekly, or monthly basis. Next, in chapter 4, we’ll discuss templating mechanisms in Airflow, which allow you to dynamically reference variables such as execution dates in your pipelines. Finally, in chapter 5, we’ll dive into different approaches for defining task dependencies in your pipelines, which allowyoutodefinecomplextaskhierarchies,includingconditionaltasks,branches,andsoon.

If you’re new to Airflow, we recommend making sure you understand the main concepts described in chapters 3–5, as these are key to using it effectively. Airflow’s scheduling semantics (described in chapter 3) can be especially confusing for new users, as they can be somewhat counterintuitive when firstencountered.

After finishing part 1, you should be well-equipped to write your own basic pipelines in Apache Airflow andbereadytodiveintosomemoreadvancedtopicsinparts2–4.

1MeetApacheAirflow

This chapter covers

Showinghowdatapipelinescanberepresentedinworkflowsasgraphsoftasks

UnderstandinghowAirflowfitsintotheecosystemofworkflowmanagers

DeterminingifAirflowisagoodfitforyou

People and companies are continuously becoming more data-driven and are developing data pipelines as part of their daily business. Data volumes involved in these business processes have increased substantially over the years, from megabytes per day to gigabytes per minute. Though handling this data deluge may seem like a considerable challenge, these increasing data volumes can be managed withtheappropriatetooling.

This book focuses on Apache Airflow, a batch-oriented framework for building data pipelines. Airflow’s key feature is that it enables you to easily build scheduled data pipelines using a flexible Python framework, while also providing many building blocks that allow you to stitch together the many differenttechnologiesencounteredinmoderntechnologicallandscapes.

Airflow is best thought of as a spider in a web: it sits in the middle of your data processes and coordinates work happening across the different (distributed) systems. As such, Airflow is not a data processing tool in itself but orchestrates the different components responsible for processing your data indatapipelines.

In this chapter, we’ll first give you a short introduction to data pipelines in Apache Airflow Afterward, we’ll discuss several considerations to keep in mind when evaluating whether Airflow is right for you and demonstratehowtomakeyourfirststepswithAirflow.

1.1Introducingdatapipelines

Data pipelines generally consist of several tasks or actions that need to be executed to achieve the desired result. For example, say we want to build a small weather dashboard that tells us what the weather will be like in the coming week (figure 1.1). To implement this live weather dashboard, we needtoperformsomethinglikethefollowingsteps:

1. FetchweatherforecastdatafromaweatherAPI.

2. Clean or otherwise transform the fetched data (e.g., converting temperatures from Fahrenheit to Celsiusorviceversa),sothatthedatasuitsourpurpose.

3. Pushthetransformeddatatotheweatherdashboard.

Figure 1.1 Overview of the weather dashboard use case, in which weather data is fetched from an external API and fed into a dynamicdashboard

As you can see, this relatively simple pipeline already consists of three different tasks that each perform part of the work. Moreover, these tasks need to be executed in a specific order, as it (for example) doesn’t make sense to try transforming the data before fetching it. Similarly, we can’t push any new data to the dashboard until it has undergone the required transformations. As such, we need to make surethatthisimplicittaskorderisalsoenforcedwhenrunningthisdataprocess.

1.1.1Datapipelinesasgraphs

One way to make dependencies between tasks more explicit is to draw the data pipeline as a graph. In this graph-based representation, tasks are represented as nodes in the graph, while dependencies between tasks are represented by directed edges between the task nodes. The direction of the edge indicates the direction of the dependency, with an edge pointing from task A to task B, indicating that task A needs to be completed before task B can start. Note that this type of graph is generally called a directedgraph,duetothedirectionsinthegraphedges.

Applying this graph representation to our weather dashboard pipeline, we can see that the graph provides a relatively intuitive representation of the overall pipeline (figure 1.2). By just quickly glancing at the graph, we can see that our pipeline consists of three different tasks, each corresponding to one of the tasks outlined. Other than this, the direction of the edges clearly indicates the order in which the tasksneedtobeexecuted:wecansimplyfollowthearrowstotracetheexecution.

Figure 1.2 Graph representation of the data pipeline for the weather dashboard. Nodes represent tasks and directed edges represent dependencies between tasks (with an edge pointing from task Ato task B, indicatingthattaskA needs to be run before task B).

This type of graph is typically called a directed acyclic graph (DAG), as the graph contains directed edges and does not contain any loops or cycles (acyclic). This acyclic property is extremely important, as it prevents us from running into circular dependencies (figure 1.3) between tasks (where task A depends on task B and vice versa). These circular dependencies become problematic when trying to execute the graph, as we run into a situation where task 2 can only execute once task 3 has been completed, while task 3 can only execute once task 2 has been completed. This logical inconsistency leads to a deadlock type of situation, in which neither task 2 nor 3 can run, preventing us from executingthegraph.

Figure 1.3 Cycles in graphs prevent task execution due to circular dependencies. In acyclic graphs (top), there is a clear path to execute the three different tasks. However, in cyclic graphs (bottom), there is no longer a clear execution path due to the interdependency between tasks 2 and 3.

Note that this representation is different from cyclic graph representations, which can contain cycles to illustrate iterative parts of algorithms (for example), as are common in many machine learning applications. However, the acyclic property of DAGs is used by Airflow (and many other workflow managers)toefficientlyresolveandexecutethesegraphsof tasks.

1.1.2Executingapipelinegraph

A nice property of this DAG representation is that it provides a relatively straightforward algorithm that wecanuseforrunningthepipeline.Conceptually,thisalgorithmconsistsofthefollowingsteps:

1. Foreachopen(=uncompleted)taskinthegraph,dothefollowing:

For each edge pointing toward the task, check if the “upstream” task on the other end of the edgehasbeencompleted.

If all upstream tasks have been completed, add the task under consideration to a queue of taskstobeexecuted.

2. Execute the tasks in the execution queue, marking them completed once they finish performing theirwork.

3. Jumpbacktostep1andrepeatuntilalltasksinthegraphhavebeencompleted.

To see how this works, let’s trace through a small execution of our dashboard pipeline (figure 1.4). On our first loop through the steps of our algorithm, we see that the clean and push tasks still depend on upstream tasks that have not yet been completed. As such, the dependencies of these tasks have not been satisfied, so at this point they can’t be added to the execution queue. However, the fetch task does not have any incoming edges, meaning that it does not have any unsatisfied upstream dependenciesandcanthereforebeaddedtotheexecutionqueue.

Figure 1.4 Using the DAG structure to execute tasks in the data pipeline in the correct order: depicts each task’s state during each of the loops through the algorithm, demonstrating how this leads to the completedexecution of the pipeline (end state)

After completing the fetch task, we can start the second loop by examining the dependencies of the clean and push tasks. Now we see that the clean task can be executed as its upstream dependency (the fetch task) has been completed. As such, we can add the task to the execution queue. The push task can’tbeaddedtothequeue,asitdependsonthecleantask,whichwehaven’trunyet.

In the third loop, after completing the clean task, the push task is finally ready for execution as its upstream dependency on the clean task has now been satisfied. As a result, we can add the task to the execution queue. After the push task has finished executing, we have no more tasks left to execute, thusfinishingtheexecutionoftheoverall pipeline.

1.1.3Pipelinegraphsvs. sequentialscripts

Although the graph representation of a pipeline provides an intuitive overview of the tasks in the pipeline and their dependencies, you may find yourself wondering why we wouldn’t just use a simple script to run this linear chain of three steps. To illustrate some advantages of the graph-based approach, let’s jump to a slightly bigger example. In this new use case, we’ve been approached by the owner of an umbrella company, who was inspired by our weather dashboard and would like to try to use machine learning (ML) to increase the efficiency of their operation. To do so, the company owner

would like us to implement a data pipeline that creates an ML model correlating umbrella sales with weather patterns. This model can then be used to predict how much demand there will be for the company’s umbrellas in the coming weeks, depending on the weather forecasts for those weeks (figure 1.5).

Figure 1.5 Overview of the umbrella demand use case, in which historical weather and sales data are used to train a model that predicts future sales demands depending on weather forecasts

TobuildapipelinefortrainingtheMLmodel,weneedtoimplementsomethinglikethefollowingsteps:

1. Preparethesalesdatabydoingthefollowing:

Fetchingthesalesdatafromthesourcesystem

Cleaning/transformingthesalesdatatofitrequirements

2. Preparetheweatherdatabydoingthefollowing:

FetchingtheweatherforecastdatafromanAPI

Cleaning/transformingtheweatherdatatofitrequirements

3. Combine the sales and weather data sets to create the combined data set that can be used as inputforcreatingapredictiveMLmodel.

4. TraintheMLmodelusingthecombineddataset.

5. DeploytheMLmodelsothatitcanbeusedbythebusiness.

This pipeline can be represented using the same graph-based representation that we used before, by drawingtasksasnodesanddatadependenciesbetweentasksasedges.

One important difference from our previous example is that the first steps of this pipeline (fetching and clearing the weather/sales data) are in fact independent of each other, as they involve two separate data sets. This is clearly illustrated by the two separate branches in the graph representation of the pipeline (figure 1.6), which can be executed in parallel if we apply our graph execution algorithm, making better use of available resources and potentially decreasing the running time of a pipeline comparedtoexecutingthetaskssequentially

Figure 1.6 Independence between sales and weather tasks in the graph representation of the data pipeline for the umbrella demand forecast model. The two sets of fetch/cleaning tasks are independent as they involve two different data sets (the weather and sales data sets). This independence is indicated by thelack ofedges between the two sets of tasks.

Another useful property of the graph-based representation is that it clearly separates pipelines into small incremental tasks rather than having one monolithic script or process that does all the work. Although having a single monolithic script may not initially seem like that much of a problem, it can introduce some inefficiencies when tasks in the pipeline fail, as we would have to rerun the entire script. In contrast, in the graph representation, we need only to rerun any failing tasks (and any downstream dependencies).

1.1.4Runningpipelineusingworkflowmanagers

Of course, the challenge of running graphs of dependent tasks is hardly a new problem in computing. Over the years, many so-called “workflow management” solutions have been developed to tackle this problem,whichgenerallyallowyoutodefineandexecutegraphsoftasksasworkflowsorpipelines.

Somewell-knownworkflowmanagersyoumayhaveheardofincludethoselistedintable1.1.

Table 1.1 Overview of several well-known workflow managers and their key characteristics.

Although each of these workflow managers has its own strengths and weaknesses, they all provide similar core functionality that allows you to define and run pipelines containing multiple tasks with dependencies.

One of the key differences between these tools is how they define their workflows. For example, tools such as Oozie use static (XML) files to define workflows, which provides legible workflows but limited

flexibility. Other solutions such as Luigi and Airflow allow you to define workflows as code, which provides greater flexibility but can be more challenging to read and test (depending on the coding skills ofthepersonimplementingtheworkflow).

Other key differences lie in the extent of features provided by the workflow manager. For example, tools such as Make and Luigi do not provide built-in support for scheduling workflows, meaning that you’ll need an extra tool like Cron if you want to run your workflow on a recurring schedule. Other tools may provide extra functionality such as scheduling, monitoring, user-friendly web interfaces, and so on built into the platform, meaning that you don’t have to stitch together multiple tools yourself to get these features.

All in all, picking the right workflow management solution for your needs will require some careful consideration of the key features of the different solutions and how they fit your requirements. In the next section, we’ll dive into Airflow—the focus of this book and explore several key features that make itparticularlysuitedforhandlingdata-orientedworkflows or pipelines.

1.2IntroducingAirflow

In this book, we focus on Airflow, an open source solution for developing and monitoring workflows. In this section, we’ll provide a helicopter view of what Airflow does, after which we’ll jump into a more detailedexaminationofwhetheritisagoodfitforyourusecase.

1.2.1Definingpipelinesflexiblyin(Python)code

Similar to other workflow managers, Airflow allows you to define pipelines or workflows as DAGs of tasks. These graphs are very similar to the examples sketched in the previous section, with tasks being definedasnodesinthegraphanddependenciesasdirectededgesbetweenthetasks.

In Airflow, you define your DAGs using Python code in DAG files, which are essentially Python scripts that describe the structure of the corresponding DAG. As such, each DAG file typically describes the set of tasks for a given DAG and the dependencies between the tasks, which are then parsed by Airflow to identify the DAG structure (figure 1.7). Other than this, DAG files typically contain some additional metadata about the DAG telling Airflow how and when it should be executed, and so on. We’ll dive into thisschedulingmoreinthenextsection.

Figure 1.7 Airflow pipelines are defined as DAGs using Python code in DAG files. Each DAG file typically defines one DAG, which describes the different tasks and their dependencies. Besides this, the DAG also defines a schedule interval that determines when the DAG is executed by Airflow.

One advantage of defining Airflow DAGs in Python code is that this programmatic approach provides you with a lot of flexibility for building DAGs. For example, as we will see later in this book, you can use Python code to dynamically generate optional tasks depending on certain conditions or even generate entire DAGs based on external metadata or configuration files. This flexibility gives a great deal of customization in how you build your pipelines, allowing you to fit Airflow to your needs for building arbitrarilycomplexpipelines.

In addition to this flexibility, another advantage of Airflow’s Python foundation is that tasks can execute any operation that you can implement in Python. Over time, this has led to the development of many Airflow extensions that enable you to execute tasks across a wide variety of systems, including external databases, big data technologies, and various cloud services, allowing you to build complex data pipelinesbringingtogetherdataprocessesacrossmanydifferent systems.

1.2.2Schedulingandexecutingpipelines

Once you’ve defined the structure of your pipeline(s) as DAG(s), Airflow allows you to define a schedule interval for each DAG, which determines exactly when your pipeline is run by Airflow This way, you can tell Airflow to execute your DAG every hour, every day, every week, and so on, or even use more complicatedscheduleintervalsbasedonCron-likeexpressions.

To see how Airflow executes your DAGs, let’s briefly look at the overall process involved in developing andrunningAirflowDAGs.Atahighlevel,Airflowisorganizedintothreemaincomponents(figure1.8):

The Airflow scheduler —Parses DAGs, checks their schedule interval, and (if the DAGs’ schedule has passed)startsschedulingtheDAGs’tasksforexecutionbypassingthemtotheAirflowworkers.

The Airflow workers —Pick up tasks that are scheduled for execution and execute them. As such, theworkersareresponsibleforactually“doingthework.”

The Airflow webserver Visualizes the DAGs parsed by the scheduler and provides the main interfaceforuserstomonitorDAGrunsandtheirresults.

Figure 1.8 Overview of the main components involved in Airflow (e.g., the Airflow webserver, scheduler, and workers)

The heart of Airflow is arguably the scheduler, as this is where most of the magic happens that determines when and how your pipelines are executed. At a high level, the scheduler runs through the followingsteps(figure1.9):

1. Once users have written their workflows as DAGs, the files containing these DAGs are read by the schedulertoextractthecorrespondingtasks,dependencies,andscheduleintervalofeachDAG.

2. For each DAG, the scheduler then checks whether the schedule interval for the DAG has passed sincethelasttimeitwasread.Ifso,thetasksintheDAGarescheduledforexecution.

3. For each scheduled task, the scheduler then checks whether the dependencies (= upstream tasks) ofthetaskhavebeencompleted.Ifso,thetaskisaddedtotheexecutionqueue.

4. Theschedulerwaitsforseveralmomentsbeforestartinganewloopbyjumpingbacktostep1.

Figure 1.9 Schematic overview of the process involved in developing and executing pipelines as DAGsusingAirflow

The astute reader might have noticed that the steps followed by the scheduler are, in fact, very similar to the algorithm introduced in section 1.1. This is not by accident, as Airflow is essentially following the samesteps,addingsomeextralogicontoptohandleitsschedulinglogic.

Once tasks have been queued for execution, they are picked up by a pool of Airflow workers that execute tasks in parallel and track their results. These results are communicated to Airflow’s metastore so that users can track the progress of tasks and view their logs using the Airflow web interface (providedbytheAirflow webserver).

1.2.3Monitoringandhandlingfailures

In addition to scheduling and executing DAGs, Airflow also provides an extensive web interface that can be used for viewing DAGs and monitoring the results of DAG runs. After you log in (figure 1.10), the main page provides an extensive overview of the different DAGs with summary views of their recent results(figure1.11).

Figure 1.10 The login page for the Airflow web interface. In the code examples accompanying this book, a default user “admin” isprovided with the password “admin.”

Figure 1.11 The main page of Airflow’s web interface, showing an overview of the available DAGs and their recentresults

For example, the graph view of an individual DAG provides a clear overview of the DAG’s tasks and dependencies (figure 1.12), similar to the schematic overviews we’ve been drawing in this chapter. This view is particularly useful for viewing the structure of a DAG (providing detailed insight into dependenciesbetweentasks),andforviewingtheresultsofindividualDAGruns.

Another random document with no related content on Scribd:

woord hem bespookt in zijn droomen; maar nooit als de uitdrukking van zulk een denkbeeld als thans.…

’t Was dan zoover gekomen met hem.… Paula hield hem voor gek, en liet hem terughalen.… O maar, dat kon niet.… dat zou opgehelderd worden.… hij zou ’t zelf ophelderen, dadelijk!

En hij zag de nutteloosheid van tegenweer in.

„Dokter,” zei hij somber, op heel andere toon dan te voren, „ik begrijp volkomen wat u bedoelt. De zaak zal terechtkomen. U heeft er geen schuld aan.” [220]

De goede Esculaap haalde de schouders en de wenkbrauwen op, en spreidde zijn tien vingers welsprekend uit: h ij kon ’t niet helpen.…

„Ik vind ’t onaangenaam genoeg, professor,” zei hij meewarig. Hij was innig voldaan dat de zaak die wending nam. Hij was een man des vredes, hield niet van heftige tooneelen.

„U gaat dus mee, nie’waar,” liet hij volgen. Zijn toon had iets van dien van iemand, die vervuld van medelijden tot een kind spreekt. Larsen voelde ’t als een beleediging, maar onderwierp zich gelaten. Wat gaf het hier en thans die man uit de waan te willen helpen? Iedere krankzinnige beweerde immers het niet te wezen?

Intusschen stond Didi met verbaasde oogen naar die beiden te kijken. Ze begreep er niets van. Ging vader weer terug, gingen ze n i e t naar Engeland? Wat kwam die nare man hier stoornis brengen in vaders plannen? De tranen drongen naar haar oogen; maar ze zweeg. Later zou vader alles wel uitleggen. Evenals hij schikte ze zich in ’t onvermijdelijke. Ze boog haar kopje, en ’t mondje pruilde even op.

„Kom, kind,” zei haar vader. En tot de dokter: „Ik ben tot uw beschikking. Met welke trein gaat u?”

„Iets over vijven, ik zal ’t ’s nazien,” antwoordde Dr. Brakel in gedachten. „Vindt u goed dat ik hier even wacht tot u uw zaakjes geregeld heeft?” [221]

„Goed.” Larsen was volkomen kalm, en zonder verder een woord verliet hij met zijn kind het vertrek.

Toen alle drie tien minuten later bij de voordeur waren, stond Dr. Brakel even stil.

„Een oogenblik,” zei hij. „Ik moet nog even iets vragen.”

Een glimlach vloog over Larsen’s gebaard gelaat.

De dokter ging naar binnen, en Didi maakte van de gelegenheid gebruik om zenuwachtig en haast fluisterend te zeggen:

„Vadertje.”

„Ja, mijn kind?”

„Gaan we nu n i e t naar Engeland?”

„Vandaag niet, schattemeid. Over een paar dagen.”

„Hè, gelukkig!”

Ze was voldaan, en zuchtte diep: de voornaamste zorg was uit haar gemoed weggenomen.

Toen Dr. Brakel eenige oogenblikken later weer naar voren kwam overdacht hij zijn allerlaatste zielkundige waarneming: ’t was toch vreemd met die krankzinnigen: ze konden zoo zot doen, en toch ook

weer zoo heel gewoon verstandig handelen! De hotelhouder had „niks niemendal” gemerkt: meneer had behoorlijk afgerekend ook en gewoon afscheid genomen, en de kelner ook behoorlijk bedacht! Vreemd, vreemd.… Een lastige studie, die p s y c h i a t r i e , en men leerde telkens wat nieuws, merkte telkens [222]wat verrassends op.… Maar de zaak was gezond: Larsen ging gewillig mee

„Stakkert!” mompelde de goede geneesheer nog in de gang, terwijl hij zijn versleten gekleede jas toeknoopte, en de kraag van zijn overjas opsloeg.

„Komaan, Didi, we gaan, nie’waar, kind?” zeî hij vriendelijk tot Didi, die hem zag aankomen, en hem aanstaarde met haar sprekende sprookjes-oogen.

Didi greep haar vaders hand, toen ze zag dat de dokter haar bij de hand wilde nemen. Hè nee, ze wilde niet aan zijn hand loopen!

En de drie stapten de straat op.

Een eindje verder kwamen twee mannen, forschgebouwde kerels in een gelijke donkere kleeding uit een huis. De dokter keek om. Ze gaven hem zijn blik terug en volgden op een kleine afstand. [223]

[Inhoud]

XVI.

Larsen was merkwaardig veranderd. De verandering in hem openbaarde zich ook in zijn kijk op menschen en dingen. Hij was geen droomer, geen fantast, geen man van oorspronkelijke gedachten of geniale invallen, geen Faust, maar een Wagner, al was ’t van de goede soort. Wetenschap en boek waren bij hem onafscheidelijk; zoodat hij in zijn denkleven steeds daardoor beheerscht werd: zijn geest had jaren en jaren achtereen in een denkbeeldige atmosfeer verkeerd, en was daarin volkomen bevredigd geweest. Zijn gevoelsleven had als onbewust daarnaast bestaan. Nooit had het hem verontrust, geen oogenblik in al die jaren had hij ernstig nagedacht over eenige gemoedsvraag. De liefde voor Paula, die alles aangrijpende drijfkracht van zijn wezen, was als de klop van zijn hart, even natuurlijk, onwillekeurig, buiten alle beheer van zijn denkvermogen.

Thans d a c h t hij aan die hartslag; want er was stoornis in zijn zielsorganisme. [224]

En hoe meer hij dacht, hoe ellendiger hij zich voelde, hoe meer hij besefloos toegaf aan de verwarring, het verlies van evenwicht in zijn denkbeelden. ’t Eerste gevolg der groote stoornis was angst geweest. Die angst had hem vervolgd, opgejaagd totdat hij geen ander heil verwachtte dan wat de vlucht hem schenken zou. En ’t vooruitzicht op rust had hem reeds toegeblonken: ’t had hem gesust, ’t had zijn zielebrand voor een wijl gedoofd.

En nu? Nauwelijks was hij thuis of de a n g s t kwam terug! Wat hem voorgekomen was als makkelijk te overwinnen, misverstand, bleek thans een weldoordacht plan: niet dat hij er ’t ware besef van had—

hoe kon dat in de geschokte toestand waarin hij verkeerde?—maar juist deed zijn overspannen verbeelding hem bedrog en verraad zien waar het niet was. Was werkelijk hier zijn vrouw alleen de schuldige; het duurde niet lang of hij verdacht de huisdokter van gemeene samenspanning. En van de eene verdenking kwam hij op de andere, en telkens werd de strijd, die hij er tegen voerde, zwakker

Op reis naar huis terug had hij nog de kracht gehad angstaanvechtingen terug te dringen: zijn vrouw had hem willen dwingen terug te keeren, zeker—waarom anders dat bevelschrift?—maar wat ’n dwaasheid te denken dat zulk een komediespel van haar vol te houden was! Och kom, hij zou [225]wel heel spoedig ’t zaakje in orde hebben. En hij was begonnen met dood-bedaard—hij deed zijn best het te wezen—in gedachten de goede Dr. Brakel nog eens al zijn bewijzen vóor te leggen, dat hier een betreurenswaardige dwaling in ’t spel was.

De heele weg over, tot aan ’t oogenblik dat Larsen met zijn geleider en de kleine Didi in de trein stapten, hadden ze nauwelijks een woord gewisseld. Larsen stapte voort met gefronste wenkbrauwen en saamgeknepen lippen, Didi naast hem, schuchtere blikken werpend op haar vader, terwijl de huisarts in vreedzaam gepeins, voldaan, maar schijnbaar onverschillig, met kleine pasjes de stoere schreden van zijn patiënt trachtte bij te houden.

In de coupé zette Larsen zich als een zak in een hoek, Didi schoof naar hem toe, greep zijn hand en keek hem met groote oogen aan, met de bezorgdheid van een klein moedertje dat troosten wil.

Larsen, die reeds de oogen gesloten hield, sloeg ze op, en voelde al de streeling die van Didi’s blik uitging. Een warme opwelling van teederheid deed hem zijn arm om haar heen slaan, en zijn ruige baard raakte haar zachte wang.

„Vadertje,” zei ’t kind alleen, maar er was een wereld van hartelijkheid en belangstelling in haar toon.

Dr. Brakel keek toe. Er was niets dan medelijden in zijn blik, en toch was ’t Larsen of hij er spot in [226]las, of hij met een zweepslag opgeschrikt werd. Driftig wendde hij zich half om:

„Doe me genoegen, dokter,” zei hij scherp, „en kijk me niet zoo.… vreemd aan! Ik weet waaraan u denkt. Bewaar in Godsnaam uw observaties voor later.…”

De toegesprokene raakte even de klus kwijt—hij was een schuchter, weinig imponeerend man—maar herstelde zich dadelijk. De meewarige uitdrukking in zijn oogen werd nog sterker en hij antwoordde op gemaakt luchtige toon:

„Maar professor, ik denk er niet aan.…”

Larsen wilde uitbarsten, maar bedwong zich. Ongemakkelijk verschoof hij zich op zijn plaats. Hij vergenoegde zich met een blik vol misnoegdheid; thuis, wanneer de tegenwoordigheid van ’t kind hem niet langer zou storen, zou hij die onzin wel wegpraten: zóo en zóo en zóo.… Als hij nu toegaf aan zijn drift en hevigheid, zou de zaak er zeker eer slechter dan beter door worden.

Toen de trein aankwam, stond een rijtuig te wachten, door Paula afgezonden. Larsen merkte met verbeten ergernis op dat er een voorzorgsmaatregel genomen was: er zat een man naast de koetsier op de bok. Zijn verlangen naar huis werd haast onduldbaar, die komedie moest zoo gauw mogelijk uit wezen! [227]

Nauwelijks zijn voordeur binnen, vroeg hij naar Paula. Het welbekende gezicht van Pietje vertoonde een vreemde, medelijdende verwondering.

„Mevrouw?.… Dat weet ik.… heusch niet, meneer,” zei ze met een kleur.

Larsen voelde weer zijn bloed koken: hij, de kalme, zelden kregelige man, had nu telkens moeite om zijn drift te bedwingen.

„Is ze uit?” vroeg hij stuursch.

De dokter nam de verlegen Pietje even apart, fluisterde haar een paar woorden in, waarop ze, eveneens fluisterend, zenuwachtig antwoordde.

Larsen, die ’t zag, wendde zich kort om, streelde zijn kind, dat zich schuchter tegen hem aan drong; en verborg zoo zijn wrevel zoo goed hij kon.

Dr. Brakel zeide daarop:

„Mevrouw is niet dadelijk te spreken, professor. Ik moet haar voorbereiden. Ik zou u raden voorloopig naar uw kamer te gaan.”

Daarna gaf hij een teeken aan ’t dienstmeisje en wees op Didi. Zijn heele optreden had iets autoritairs, iets korts en afdoends, als gold het hier een weloverdacht plan van handelen.

De anders zoo zachtmoedige professor kon zich niet meer inhouden.

„Ik moet mevrouw spreken, versta je dat, Pietje?” riep hij woedend, niet lettend op de dokter. „Zeg me onmiddellijk waar mevrouw is.” En hij ging [228]eenige schreden de gang in, in de richting van de trap.

„Ik.… weet.… ’t niet,” stamelde de verschrikte Pietje, wie de angst om ’t hart sloeg: je kon nooit weten, nu meneer gek was.… En haar voorschoot aan de oogen brengend, begon ze te schreien.

Haar vrees dat „meneer” haar aanpakken zou werd niet bewaarheid, tot haar groote verlichting; want ze zag hem met ongekende haast de trap opgaan, nog voordat de dokter een woord van protest kon uitbrengen. Bij wijze van schrik-afleider nam ze Didi bij de hand, en troonde haar met zich mee naar achteren: de dokter moest ’t maar verder klaarspelen met meneer, zij moest er niks van hebben, hoor!

En de dokter vond het geraden Larsen zijn gang te laten gaan. Zijn vrouw zou hem toch wel in geen geval ontvangen. Dr. Brakel dacht aan de afspraak, die ze vóor zijn vertrek naar Vlissingen, met hem gemaakt had, en rekende op haar voorzichtigheid. ’t Was Paula makkelijk gevallen hem te overtuigen dat ze bang voor haar man was, nu hij „zoo vreemd” was, en hij had haar dan ook de raad gegeven hem onder geen voorwendsel bij zich toe te laten: hij, Dr. Brakel, zou dan alles wel kalmpjes afdoen. Paula had het hem vast beloofd, met groote voldoening dat ze zóo een lastig tooneel met Larsen vermeed: wie weet wat de man anders in zijn razernij tegen haar zeggen zou, afgezien nog van lichamelijk letsel dat [229]hij haar zou kunnen doen: hu, zoo’n gek!—want dat wàs hij immers nu bepaald—’t was beter alle contact te ontloopen, dan was er geen kans op geklets van de meiden ook, en—de zaak zou op rolletjes gaan.…

Zoo had Paula zich dan reeds uren te voren boven in haar kleedkamer opgesloten, en iedere keer was ze naar het venster geloopen, wanneer ze meende ’t gedruisch van wielen te hooren. Over de tuinmuur heen kon ze een strook van de straat overzien. En toen eindelijk ’s avonds vrij laat ’t verwachte rijtuig langs de muur reed, stond ze weer achter ’t gordijn, en kon ze bij ’t schijnsel van een straatlantaarn aan de twee gestalten op de bok merken dat Larsen wel binnen enkele oogenblikken thuis zou wezen. Toen nog even geluisterd aan de deur, die ze met de hand aan de knop

openhield: jawel, daar hoorde ze zijn stem in de gang! En ijlings sloot ze de deur, weer op slot.

Paula voelde zich zenuwachtig: zou Larsen misschien tòch trachten tot haar door te dringen? Als de dokter eens.… Ze zette zich op een fauteuil bij haar kaptafel, en wachtte af, de ooren gespitst. Het gerucht van stemmen beneden kwam flauw tot haar. Pietje of de dokter zou wel spoedig boven komen.

Daar werd aan de deur geklopt, met vrij hevige tikken. [230]

Dat moest Larsen zelf zijn! Ze voelde ’t, ofschoon de vlugge schreden op de trap en op den overloop evengoed op een ander hadden kunnen duiden; want men zou haar immers dadelijk verwittigen, wanneer de verwachte er wezen zou.

Een oogenblik bleef ze in beraad.

Nog eens hevig kloppen, vrij onmiddellijk na ’t eerste.

„Paula, mag ik binnen?” klonk het ongeduldig en gejaagd, zonder eenige inleiding.

De aangesprokene was ten hoogste ontroerd: ze beefde over haar heele lijf. Ze moest een besluit nemen: niet binnenlaten, in geen geval.… Maar dan.… als hij eens de deur forceerde?

Haastig sprong ze op, liep naar de schel en deed er drie of vier zenuwachtige rukken aan.

Larsen hoorde de beweging in de kamer en ’t geluid van de schel. O, hij begreep het: Paula was b a n g voor hem! Deze ontdekking die hij deed was weinig geschikt om hem tot bedaren te brengen. ’t Speet hem nu dat hij maar niet dadelijk naar binnen was gegaan. Hij had ’t niet gedaan, omdat de veranderde omstandigheden hem dwongen

tot grootere vormelijkheid.… De deur zou wel open zijn.… hij moest onmiddellijk aan dien onzin een eind maken.

„Wat is dat?” riep hij buiten zich zelven toen hij merkte dat de deur op slot was. „Paula! Ik moet [231]even bij je zijn. Ik moet je spreken. Wat is dat nu voor een komedie? Laat me binnen!”

Geen antwoord.

„Paula! Hoor je me niet?”

Hij luisterde even: ’t was muisstil in de kamer. „Paula!”

Daar kwam iemand de trap op. O, de dokter. Wat had die hier te maken?

„Wat moet u hier?” vroeg Larsen.

De dokter trad op hem toe en leî een hand op zijn schouder. Larsen weerde hem driftig af:

„Dat is onuitstaanbaar! Ik heb u niet noodig.…”

„Ik u wel,” zei Dr. Brakel kalm en met beteekenis. Weer ging de bel in Paula’s kamer.

„Wacht u dan beneden op me. Ik kom bij u in de voorkamer, straks. Ik moet even mijn vrouw spreken. Dat wil u me toch niet beletten?”

Merkwaardig stak de drift van de eene bij de kalmte van de ander af. Dr. Brakel waagde nog een poging tot overreding. Vriendelijk vervolgde hij:

„Ik heb u immers gezegd dat uw vrouw u niet dadelijk ontvangen kan. Ze komt misschien straks beneden. Ga nu met me mee, of ga naar uw kamer. Daar doet u heusch verstandiger aan. U begrijpt

toch dat uw vrouw na ’t gebeurde.… niet opeens begrijpt.… wat ze aan u heeft.”

Misschien zou Larsen voor die zachte drang [232]gezwicht zijn, als niet juist op dat oogenblik iets voorviel dat zijn reeds bedarende drift heviger dan ooit deed opvlammen.

De man op de bok, op wie Larsen bij ’t thuiskomen in zijn staat van afgetrokkenheid niet meer gelet had, was een kameraad gaan halen en beiden bleven buiten wachten nadat het rijtuig weggereden was. Pietje had van mevrouw de uitdrukkelijke last gekregen ze in te laten zoodra de dokter ’t noodig oordeelde, en als dat gebleken was voorloopig niet het geval te wezen, zou ze hun dit aan de deur zeggen. De politie-mannen—want dit waren zij, al verraadde niets in hun kleeding hun kwaliteit—wandelden op en neer vlak vóor ’t huis. Pietje, die op mevrouw’s bellen de oude dokter naar boven had zien „hollen”, vond ’t geraden naar hulp uit te kijken: wie weet wat er anders gebeurde! Ze was anders juist bezig Didi allerlei vragen te doen, en had zoo graag wat meer uit haar gekregen—Didi was uit haar humeur geweest, had nauwelijks bij Pietje willen blijven, en toch had deze dit noodig gevonden „in de omstandigheden”. En Pietje stoof de gang in, terwijl ze Didi in de keuken sloot, keek schuw links en rechts uit de voordeur, wenkte met hevig gebaar toen ze de twee gestalten gewaar werd.

„Doet-i vreemd?” vroeg de een, die ’t zaakje niet onaardig vond. Mevrouw van de Prefesser was al [233]zoo gul geweest. ’t Was daar ’n goeie boel in huis: cognac en sigaren, asjeblief en fijn, hoor!

„Ja, kom gauw,” zei Pietje zenuwachtig, en keek nog eens of er ook menschen op straat waren.

En de beide mannen kwamen stil binnen. Pietje sloot de voordeur, met bevende vingers, en ze deed zich pijn aan de koperen knop. Ze

stak haar duim in haar mond—hè, dat lamme ding aan die deur!

„Mevrouw is boven,” stamelde ze.

„Ja, en?” De gebaarde politie-agent met het blozende gezicht, die iets Duitsch krijgshaftigs in zijn uiterlijk bewaard had, al was hij ook reeds tien jaar „uit dienst”, had zijn minder militair uitziende kameraad—een bleek, beenig stadsmensch met kaal gezicht, iets ouder en minder stevig—met een wenk duidelijk gemaakt dat hij wachten moest: hij had in dienst manieren geleerd, wat blief je.…

„Meneer.… is ook boven. En de dokter is ook boven. Ga maar ’s kijken.”

De Germaan van de twee glimlachte goedig over Pietje’s zenuwachtigheid.

„Blijf jij maar hier wachten, Van Turnhout,” zeî hij op gedempte toon tot de ander. „Ik zal je wel roepen als ’t noodig is. Ik zal wel alleen gaan.”

„Gauw dan toch!” jengelde Pietje zoo zacht als haar angst toeliet. Mevrouw had haar weer gebeld.…

En zoo kwam ’t dat er zich een ruige krijgsmanstronie [234]boven de trap vertoonde, juist toen Larsen die kant uitkeek, en er reeds aan dacht toe te geven aan de aandrang van Dr. Brakel.

Het kinderlijk, kalm jongensgezicht met de groot-starende, blauwe kijkers had op Larsen een wonderlijke uitwerking. Zonder zich rekenschap te geven van wat hij deed—de impulsies namen meer en meer de overhand in zijn handelen—vloog hij op de verschijning toe.

„Mijn trap af.… Mijn huis uit, zeg ik je!” bulderde hij vlak bij hem.

Weer dat starende blauw, zonder spoor van verbazing; dat massieve geheel van bewuste kracht.

Larsen weifelde. Meteen was onze Germaan boven, en stond nu naast de woedende. Hij wierp even een blik naar de deur aan ’t einde van de overloop, die van Paula’s kamer. Dat was in orde: de dokter stond ervoor, en die wenkte: hij kon zijn gang gaan.

Larsen zag en begreep zijn blik. En smartelijker, honender dan ooit flikkerde dit angstbeeld vóor zijn geest op: Paula wilde hem verwijderen, naar ’t gekkenhuis laten brengen, zonder hem een oogenblik gelegenheid te laten het misverstand uit de weg te ruimen, en de dokter en zijn heele huis spanden samen in een duivelsch komplot!

Dat zou niet, bij God! Hij was nog meester in zijn huis.… Maar ’t bevelschrift dat de oude Brakel [235]hem te Vlissingen had laten zien? ’t Mocht wat! ’t Was al mooi dat hij daarom gewillig mee was gegaan, terug naar zijn huis! ’t Was immers schreeuwend onrecht iemand zoo maar weg te willen halen zonder een woord van explicatie! Dat was Paula’s toeleg: een machinatie zonder naam, op touw gezet omdat ze haar kansen anders tegenover hem verloren zag. Daar zou hij zich tegen verzetten, en hij wou wel ’s zien, of hij zich geen recht zou weten te verschaffen tegenover dat wijf!!

En er niets van beseffende hoe hij hier juist bezig was zijn eigen spel voor goed te bederven, liet hij zich blindelings voortsleepen door zijn toorn.

„Versta je me niet?” riep hij weer tot de agent met gebalde vuisten en vlammende oogen. „Onmiddellijk naar beneden!”

De ander zweeg, maar de dreiging in Larsen’s blik en gebaar ziende, bracht hij snel een fluitje voor den dag, en blies er even met kracht

op. Had hij geroepen, dan was er kans geweest dat zijn kameraad beneden een minder gunstig denkbeeld van zijn correct militair optreden gekregen had.

Bij Larsen deed dit de maat overloopen. Met zijn groote kracht, vroeger ondanks al zijn ingespannen studie steeds onderhouden en geoefend door dagelijksche huis-gymnastiek, ’s morgens na ’t bad, en thans nog wonderlijk vermeerderd door zijn dolle [236]woede, greep hij de agent bij zijn schouder, en duwde hem in de richting van de trap, slechts enkele schreden daarvandaan. De man was een oogenblik overbluft door de vlugheid van Larsen’s optreden. Doch zich dadelijk herstellende, wist hij met groote tegenwoordigheid van geest bovenaan de leuning te grijpen, en zoo een anders zekere val te stuiten, toen zijn eene voet reeds van ’t portaal af op de bovenste trede der trap was gegleden. Nauw zijn evenwicht herkregen, zette hij zich schrap. ’t Massieve eikenhout der leuning kraakte bedenkelijk door de forsche druk van die athleten-arm; doch ’t was maar éen oogenblik; want de onbesuisde tegenstander was bedwongen voordat hij nog recht wist wat er gebeurde: de ander had hem met de eene vrije arm en zijn eene knie achteruit gedrongen, was een ommezien later weer op het portaal, en had Larsen de handboeien aangelegd.

„’t Spijt me, meneer,” zei de handige politie-agent met kranig geaffecteerde bedaardheid—hij was blij dat ’t zoo goed afgeloopen was, nou; want de perfesser was niet meegevallen, om de dood nie! —„maar u zal me moeten volgen. Als u zich kalm houdt wil ik u straks die boeien wel afdoen, in ’t rijtuig misschien al.”

De gevangene stond wezenloos, verlamd. Met uitpuilende oogen staarde hij de agent aan, zijn neusvleugels [237]trilden, uit zijn open mond kwamen benauwde ademschokken. Een akelig geluid, half snik, half kreunen ontwrong zich aan zijn borst, en hij zakte in elkaar.

Een wit gipsen beeld achter hem wankelde en viel van zijn voetstuk met een harde slag.

Met goedige verbazing in zijn blik ondersteunde de agent het slappe lichaam van Larsen. De dokter schoot toe, gaf orders. Inmiddels was de tweede agent bovengekomen.

En Pietje schichtig daarachter, op de trap nog, aarzelend, nieuwsgierig, bang.

„Zal ik koud water halen?” riep ze.

Larsen werd naar een bank geleid bij een raam op de overloop. De dokter liet hem zitten, maakte zijn vest los. De eene agent ontdeed hem van zijn boeien, de ander haalde wat water: de duinwaterkraan was vlak bij de hand. Hij nam ’t zeepbakje weg en vulde dat.

„Daar neerzetten,” zeî Dr. Brakel, toen de agent terugkwam. En dan tot de schichtige Pietje:

„Breng even een spons, Pietje.” En toen Pietje de trap weer af wilde:

„Uit mevrouws kamer maar.”

Paula, die achter haar deur had staan luisteren, een en al beving en schrik, vermoedde wat er gaande was. Ze liet Pietje dadelijk binnen, toen deze met huilerige stem om toegang vroeg. [238]

De dokter had intusschen zijn patiënt een flacon met „vlugzout” onder de neus gehouden—hij had het bij zich genomen voor alle gebeurlijkheden; daarna het voorhoofd wat gebet, met zijn zakdoek. Larsen opende flauw de oogen.

Toen Pietje terugkwam, stak haar meesteres ’t hoofd uit de deur van haar kamer.

„Dokter!” riep ze zacht.

De geroepene belastte Pietje met het toezicht over zijn patiënt.

„Ja?” antwoordde hij bijna fluisterend.

„Hoe is ’t, dokter? Hij komt bij, nie’waar?”

„O ja, dat gaat al. Maak u maar niet ongerust.”

„Moet hij niet naar zijn bed?”

„Ja, dat zal wel ’t beste zijn. Waar zal ik hem laten brengen?”

„Och.… wat dunkt u?.… Heeft hij daar ook niet een goed bed?”

„Daar.… Wat bedoelt u?”

„In.… in ’t gesticht.”

„O, jawel. Maar woû u?.…”

Paula hield even op. Toen nog zachter dan te voren:

„Ik ben zoo bang.… voor hem, dokter. Voor hèm, ziet u? Als u toch verzekert dat ze hem daar goed behandelen. Zou ’t heusch niet beter zijn?”

„Och, eigenlijk wel.…”

„Doet u ’t maar. Wacht, ik zal Pietje om een [239]rijtuig laten telefoneeren.… U vindt ’t immers goed zoo, nie’waar, dokter?”

„O zeker, zeker, u heeft gelijk. Beter zoo.”

Hij ging naar Larsen terug, loste de bevende Pietje af van haar akelige taak: och, meneer zag zoo wit als een doek, en dan die natte haren vóor zijn oogen!

Beneden in de gang gekomen, hoorde ze Didi weeklagen in de keuken. ’t Kind was buiten zichzelve. „Ik wil naar vader, ik wil naar vader!” kreet ze telkens tusschen zenuwachtig snikken in.

Pietje gebood haar gevoelig hart te zwijgen, en hanteerde het spreekwerktuig met zenuwachtige haast.

Een half uur later—’t was half twaalf in de nacht—reed op de weg naar Den Haag met eenzame wielrateling een dicht rijtuig in de richting der hofstad. Op de bok zat ditmaal alleen de koetsier met nog een man; op de achterbank binnen het korte lichaam van Dr. Brakel, met gekruiste armen achterover leunend, en tegenover hem Larsen in kussens half weggezakt, in doffe onverschilligheid. [240]

[Inhoud]

XVII.

„Wat nu al weer? Binnen!!” riep Larsen, die op een lederen leuningstoel ineengedoken zat, kin op de borst, handen en voeten over elkaar. Hij d a c h t n a . ’t Was onaangenaam dat men hem nooit behoorlijk tijd liet om n a t e d e n k e n : iedere keer werd hij gestoord!

De deur ging open. Larsen keek niet op. Met gefronste wenkbrauwen bleef hij vóor zich kijken.

„Goeie morgen, Willem!” zeide de binnentredende vroolijk en hartelijk. „Hoe staat het leven?” Hij ging naar de zittende toe, en klopte hem op de schouder.

„O, ben jij ’t.…?” Wantrouwig blikten Larsen’s oogen. Dan opeens met veranderde toon, maar nòg gemelijk: „Kruyt.… Albert.”

„Zeker, amice, ik kom ’s kijken hoe je ’t maakt, net als de vorige keer.…” Medelijdend keek de bezoeker de ander aan.

Hij was ongeveer van diens leeftijd, had een gladgeschoren [241]rondblozend gelaat, zwartglanzig spaarzaam haar met lichte kroezing boven de kleine platte ooren, half dichtgeknepen grijze oogjes, gebogen, maar fraai gevormde neus, streepmond met een zelden verdwijnend vleugje van ironie, door rooken eenigszins zwartachtig geworden gave kleine tanden, waarvan zich alleen de onderste rij bij een kort kramplachje liet zien; verder een spoor van onderkin, en in hals en overige lichaamsdeelen iets welgedaans, dat evenwel aan ’t geheel zijner verschijning eer voor- dan nadeelig was: ’t gaf hem bij de ongedwongenheid en evenredigheid zijner bewegingen een waas van priesterlijke waardigheid en deftigheid,

Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.