DistributedSystems Ed2023 Ch01
DistributedSystems Ed2023 Ch01
INTRODUCTION
2 CHAPTER 1. INTRODUCTION
The pace at which computer systems change was, is, and continues to be
overwhelming. From 1945, when the modern computer era began, until about
1985, computers were large and expensive. Moreover, lacking a way to connect
them, these computers operated independently of one another.
Starting in the mid-1980s, however, two advances in technology began to
change that situation. The first was the development of powerful microproces-
sors. Initially, these were 8-bit machines, but soon 16-, 32-, and 64-bit CPUs
became common. With powerful multicore CPUs, we now are again facing
the challenge of adapting and developing programs to exploit parallelism. In
any case, the current generation of machines have the computing power of the
mainframes deployed 30 or 40 years ago, but for 1/1000th of the price or less.
The second development was the invention of high-speed computer net-
works. Local-area networks or LANs allow thousands of machines within a
building to be connected in such a way that small amounts of information can
be transferred in a few microseconds or so. Larger amounts of data can be
moved between machines at rates of billions of bits per second (bps). Wide-area
network or WANs allow hundreds of millions of machines all over the earth
to be connected at speeds varying from tens of thousands to hundreds of
millions bps and more.
Parallel to the development of increasingly powerful and networked ma-
chines, we have also been able to witness miniaturization of computer systems,
with perhaps the smartphone as the most impressive outcome. Packed with
sensors, lots of memory, and a powerful multicore CPU, these devices are
nothing less than full-fledged computers. Of course, they also have network-
ing capabilities. Along the same lines, so-called nano computers have become
readily available. These small, single-board computers, often the size of a
credit card, can easily offer near-desktop performance. Well-known examples
include Raspberry Pi and Arduino systems.
And the story continues. As digitalization of our society continues, we
become increasingly aware of how many computers are actually being used,
regularly embedded into other systems such as cars, airplanes, buildings,
bridges, the power grid, and so on. This awareness is, unfortunately, increased
when such systems suddenly turn out to be hackable. For example, in
2021, a fuel pipeline in the United States was effectively shut down by a
ransomware attack. In this case, the computer system consisted of a mix
of sensors, actuators, controllers, embedded computers, servers, etc., all
brought together into a single system. What many of us do not realize, is that
vital infrastructures, such as fuel pipelines, are monitored and controlled by
networked computer systems. Along the same lines, it may be time to start
realizing that a modern car is actually an autonomously operating, mobile
networked computer. In this case, instead of the mobile computer being
carried by a person, we need to deal with the mobile computer carrying
people.
organized as a huge tree, where each path from the root to a leaf node represents
a fully qualified name, such as www.distributed-systems.net. It would be a
mistake to think that the root node is implemented by just a single server. In
fact, the root node is implemented by 13 different root servers, each server, in
turn, implemented as a large cluster computer. The physical organization of DNS
also shows that the root is not a single point of failure. Being highly replicated, it
would take serious efforts to bring that root down and so far, all attempts to do
so have failed.
Centralized solutions are not bad just because they seem to be centralized.
In fact, as we shall encounter many times throughout this book, (logically, and
even physically) centralized solutions are often much better than distributed
counterparts for the simple reason that there is a single point of failure. It makes
them much easier to manage, for example, and certainly in comparison where
there may be multiple points of failures. Moreover, that single point of failure
can be hardened against many kinds of failures as well as many kinds of security
attacks. When it comes to being a performance bottleneck, we will also see
that many things can be done to ensure that even that cannot be held against
centralization.
In this sense, let us not forget that centralized solutions have even proven to
be extremely scalable and robust. They are called cloud-based solutions. Again,
their implementations can make use of very sophisticated distributed solutions,
yet even then, we shall see that even those solutions may sometimes need to rely
on a small set of physical machines, if only to guarantee performance.
• The fact that distributed and decentralized systems are networked, used
by many users and applications, and often cross multiple administra-
tive boundaries, make them particularly vulnerable to security attacks.
Therefore, understanding these systems and their behavior, requires
that we understand how they can be, and are secured. Unfortunately,
understanding security is not that easy.
Our distinction is one between sufficiency and necessity for spreading processes
and resources across multiple computers. Throughout this book, we take
the standpoint that decentralization can never be a goal in itself, and that it
should focus on the sufficiency for spreading processes and resources across
computers. In principle, the less spreading, the better. Yet at the same time,
we need to realize that spreading is sometimes truly necessary, as illustrated
by the examples of decentralized systems. From this point of sufficiency, the
book is truly about distributed systems and where appropriate, we shall speak
of decentralized systems.
Along the same lines, considering that distributed and decentralized
systems are inherently complex, it is equally important to consider solutions
that are as simple as possible. Therefore, we shall hardly discuss optimizations
to solutions, firmly believing that the impact of their negative contribution to
increased complexity outweighs the importance of their positive contribution
to an increase of any type of performance.
• To make distributed systems work, what happens under the hood on top
of which applications are executed, is that processes coordinate things.
They jointly coordinate, for example, to compensate for the lack of global
clock, for realizing mutual exclusive access to shared resources, and so
on. The coordination perspective describes a number of fundamental
coordination tasks that need to be carried out as part of most distributed
systems.
special shared folder that is maintained by a third party somewhere on the In-
ternet. Using special software, the shared folder is barely distinguishable from
other folders on a user’s computer. In effect, these services replace the use of
a shared directory on a local distributed file system, making data available
to users independent of the organization they belong to, and independent of
where they are. The service is offered for different operating systems. Where
exactly data are stored is completely hidden from the end user.
Transparency Description
Access Hide differences in data representation and how an object is
accessed
Location Hide where an object is located
Relocation Hide that an object may be moved to another location while
in use
Migration Hide that an object may move to another location
Replication Hide that an object is replicated
Concurrency Hide that an object may be shared by several independent
users
Failure Hide the failure and recovery of an object
are actually moving, mobile phones will allow them to continue their con-
versation. Other examples that come to mind include online tracking and
tracing of goods as they are being transported from one place to another,
and teleconferencing (partly) using devices that are equipped with mobile
Internet.
1.2.3 Openness
Another important goal of distributed systems is openness. An open dis-
tributed system is essentially a system that offers components that can easily
be used by, or integrated into other systems. At the same time, an open
distributed system itself will often consist of components that originate from
elsewhere.
together with types of the parameters, return values, possible exceptions that
can be raised, and so on. The hard part is specifying precisely what those
services do, that is, the semantics of interfaces. In practice, such specifications
are given in an informal way by natural language.
If properly specified, an interface definition allows an arbitrary process
that needs a certain interface, to talk to another process that provides that
interface. It also allows two independent parties to build entirely different
implementations of those interfaces, leading to two separate components that
operate in exactly the same way.
Proper specifications are complete and neutral. Complete means that
everything that is necessary to make an implementation has indeed been
specified. However, many interface definitions are not at all complete, so
that it is necessary for a developer to add implementation-specific details.
Just as important is the fact that specifications do not prescribe what an
implementation should look like; they should be neutral.
As pointed out in Blair and Stefani [1998], completeness and neutrality are
important for interoperability and portability. Interoperability characterizes
the extent by which two implementations of systems or components from
different manufacturers can co-exist and work together by merely relying
on each other’s services as specified by a common standard. Portability
characterizes to what extent an application developed for a distributed system
A can be executed, without modification, on a different distributed system B
that implements the same interfaces as A.
Another important goal for an open distributed system is that it should
be easy to configure the system out of different components (possibly from
different developers). Moreover, it should be easy to add new components or
replace existing ones without affecting those components that stay in place.
In other words, an open distributed system should also be extensible. For
example, in an extensible system, it should be relatively easy to add parts that
run on a different operating system, or even to replace an entire file system.
Relatively simple examples of extensibility are plug-ins for Web browsers, but
also those for Websites, such as the ones used for WordPress.
Exemption: When the cache fills up, which data is to be removed so that
newly fetched pages can be stored?
1.2.4 Dependability
As its name suggests, dependability refers to the degree that a computer
system can be relied upon to operate as expected. In contrast to single-
computer systems, dependability in distributed systems can be rather intricate
due to partial failures: somewhere there is a component failing while the
system as a whole still seems to be living up to expectations (up to a certain
point or moment). Although single-computer systems can also suffer from
failures that do not appear immediately, having a potentially large collection
of networked computer systems complicates matters considerably. In fact, one
should assume that at any time, there are always partial failures occurring.
An important goal of distributed systems is to mask those failures, as well as
mask the recovery from those failures. This masking is the essence of being
able to tolerate faults, accordingly referred to as fault tolerance.
Basic concepts
Dependability is a term that covers several useful requirements for distributed
systems, including the following [Kopetz and Verissimo, 1993]:
• Availability
• Reliability
• Safety
• Maintainability
Note that these metrics make sense only if we have an accurate notion of
what a failure actually is. As we will encounter in Chapter 8, identifying the
occurrence of a failure may actually not be so obvious.
1.2.5 Security
A distributed system that is not secure, is not dependable. As mentioned,
special attention is needed to ensure confidentiality and integrity, both of
which are directly coupled to authorized disclosure and access of information
and resources. In any computer system, authorization is done by checking
whether an identified entity has proper access rights. In turn, this means
that the system should know it is indeed dealing with the proper entity. For
this reason, authentication is essential: verifying the correctness of a claimed
identity. Equally important is the notion of trust. If a system can positively
authenticate a person, what is that authentication worth if the person cannot
be trusted? For this reason alone, proper authorization is important, as it
may be used to limit any damage that a person, who could in hindsight not
be trusted, can cause. For example, in financial systems, authorization may
limit the amount of money a person is allowed to transfer between various
accounts. We will discuss trust, authentication, and authorization at length in
Chapter 9.
Note that in a symmetric cryptosystem, the key will need to be kept secret by
all parties that are authorized to encrypt or decrypt data. In an asymmetric
cryptosystem, the keys used for encryption and decryption are different.
In particular, there is a public key PK that can be used by anyone, and a
secret key SK that is, as its name suggests, to be kept secret. Asymmetric
cryptosystems are also called public-key systems.
Bi (for example, as the result of an attack), will require that the attacker also
changes the stored hash value in Bi+1 . However, because the successor of
Bi+1 contains the hash computed over the data in Bi+1 , and thus including
the original hash value of Bi , the attacker will also have to change the new has
value of Bi as stored in Bi+1 . Yet changing that value, also means changing the
hash value of Bi+1 , and thus the value stored in Bi+2 , in turn, requiring that
a new hash value is to be computed for Bi+2 , and so on. In other words, by
securely linking blocks into a chain, any successful change to a block requires
that all successive blocks be modified as well. These modifications should go
unnoticed, which is virtually impossible.
Cryptography is also used for another important mechanism in distributed
systems: delegating access rights. The basic idea is that Alice may want to
delegate some rights to Bob, who, in turn, may want to pass some of those
rights on to Chuck. Using appropriate means (which we discuss in Chapter 9, a
service can securely check that Chuck has indeed been authorized to perform
certain operations, without the need for that service to check with Alice
whether the delegation is in place. Note that delegation is something we are
now used to: many of us delegate access rights that we have as a user to
specific applications, such as an e-mail client.
An upcoming distributed application of cryptography is so-called multi-
party computation: the means for two or three parties to compute a value
for which the data of those parties is needed, but without having to actually
share that data. An often-used example is computing the number of votes
without having to know who voted for whom.
We will see many more examples of security in distributed systems in the
following chapters. With the brief explanations of the cryptographic basis,
it should suffice to see how security is applied. We shall consistently use
the notations as shown in Figure 1.4. Alternatively, security examples can be
skipped until having studied Chapter 9.
Notation Description
KA,B Secret key shared by A and B
PKA Public key of A
SKA Private (secret) key of A
EK (data) Encryption of data using key EK (or key K)
DK (data) Decryption of (encrypted) data using key DK (or key K)
H (data) The hash of data computed using function H
1.2.6 Scalability
For many of us, worldwide connectivity through the Internet is as common as
being able to send a package to anyone anywhere around the world. Moreover,
where until recently, we were used to having relatively powerful desktop
computers for office applications and storage, we are now witnessing that
such applications and services are being placed in what has been coined “the
cloud,” in turn leading to an increase of much smaller networked devices such
as tablet computers or even cloud-only laptops such as Google’s Chromebook.
With this in mind, scalability has become one of the most important design
goals for developers of distributed systems.
Scalability dimensions
Scalability of a system can be measured along at least three different dimen-
sions (see [Neuman, 1994]):
Size scalability: A system can be scalable regarding its size, meaning that
we can easily add more users and resources to the system without any
noticeable loss of performance.
Geographical scalability: A geographically scalable system is one in which
the users and resources may lie far apart, but the fact that communication
delays may be significant is hardly noticed.
Administrative scalability: An administratively scalable system is one that
can still be easily managed even if it spans many independent adminis-
trative organizations.
Let us take a closer look at each of these three scalability dimensions.
Size scalability When a system needs to scale, very different types of prob-
lems need to be solved. Let us first consider scaling regarding size. If more
users or resources need to be supported, we are often confronted with the
limitations of centralized services, although often for very different reasons.
For example, many services are centralized in the sense that they are imple-
mented by a single server running on a specific machine in the distributed
system. In a more modern setting, we may have a group of collaborating
servers co-located on a cluster of tightly coupled machines physically placed
at the same location. The problem with this scheme is obvious: the server, or
group of servers, can simply become a bottleneck when it needs to process
an increasing number of requests. To illustrate how this can happen, let us
assume that a service is implemented on a single machine. In that case, there
are essentially three root causes for becoming a bottleneck:
Let us first consider the computational capacity. Just imagine a service for
computing optimal routes taking real-time traffic information into account. It
is not difficult to imagine that this may be primarily a compute-bound service,
requiring several (tens of) seconds to complete a request. If there is only a
single machine available, then even a modern high-end system will eventually
run into problems if the number of requests increases beyond a certain point.
Likewise, but for different reasons, we will run into problems when having
a service that is mainly I/O bound. A typical example is a poorly designed
centralized search engine. The problem with content-based search queries is
that we essentially need to match a query against an entire data set. Even
with advanced indexing techniques, we may still face the problem of having
to process a huge amount of data exceeding the main-memory capacity of
the machine running the service. As a consequence, much of the processing
time will be determined by the relatively slow disk accesses and transfer of
data between disk and main memory. Simply adding more or higher-speed
disks will prove not to be a sustainable solution as the number of requests
continues to increase.
Finally, the network between the user and the service may also be the cause
of poor scalability. Just imagine a video-on-demand service that needs to
stream high-quality video to multiple users. A video stream can easily require
a bandwidth of 8 to 10 Mbps, meaning that if a service sets up point-to-point
connections with its customers, it may soon hit the limits of the network
capacity of its own outgoing transmission lines.
There are several solutions to attack size scalability, which we discuss
below after having looked into geographical and administrative scalability.
Often, we may assume that the queue has an infinite capacity, meaning that
there is no restriction on the number of requests that can be accepted for further
processing. Strictly speaking, this means that the arrival rate of requests is not
influenced by what is currently in the queue or being processed. Assuming that
the arrival rate of requests is l requests per second, and that the processing
capacity of the service is µ requests per second, one can compute that the fraction
of time pk that there are k requests in the system is equal to:
l l k
pk = 1
µ µ
If we define the utilization U of a service as the fraction of time that it is busy,
then clearly,
l
U= Â pk = 1 p0 = ) p k = (1 U )U k
k >0
µ
( 1 U )U U
N= Â k · p k = Â k · (1 U )U k = ( 1 U) Â k · Uk = = .
k 0 k 0 k 0
(1 U )2 1 U
What we are truly interested in, is the response time R: how long does it take
before the service to process a request, including the time spent in the queue.
To that end, we need the average throughput X. Considering that the service is
“busy” when at least one request is being processed, and that this then happens
with a throughput of µ requests per second, and during a fraction U of the total
time, we have:
l
X= U·µ + (1 U ) · 0 = · µ = l
| {z } | {z } µ
server at work server idle
Using Little’s formula [Trivedi, 2002], we can then derive the response time as
N S R 1
R= = ) =
X 1 U S 1 U
where S = µ1 , the actual service time. Note that if U is small, the response-
to-service time ratio is close to 1, meaning that a request is virtually instantly
processed, and at the maximum speed possible. However, as soon as the utilization
comes closer to 1, we see that the response-to-server time ratio quickly increases to
very high values, effectively meaning that the system is coming close to a grinding
halt. This is where we see scalability problems emerge. From this simple model,
we can see that the only solution is bringing down the service time S. We leave it
as an exercise to the reader to explore how S may be decreased.
that were designed for local-area networks is that many of them are based
on synchronous communication. In this form of communication, a party
requesting a service, generally referred to as a client, blocks until a reply is
sent back from the server implementing the service. More specifically, we often
see a communication pattern consisting of many client-server interactions, as
may be the case with database transactions. This approach generally works
fine in LANs, where communication between two machines is often at worst
a few hundred microseconds. However, in a wide-area system, we need to
consider that interprocess communication may be hundreds of milliseconds,
three orders of magnitude slower. Building applications using synchronous
communication in wide-area systems requires a great deal of care (and not
just a little patience), notably with a rich interaction pattern between client
and server.
Another problem that hinders geographical scalability is that communica-
tion in wide-area networks is inherently much less reliable than in local-area
networks. In addition, we generally also need to deal with limited bandwidth.
The effect is that solutions developed for local-area networks cannot always
be easily ported to a wide-area system. A typical example is streaming video.
In a home network, even when having only wireless links, ensuring a stable,
fast stream of high-quality video frames from a media server to a display is
quite simple. Simply placing that same server far away and using a standard
TCP connection to the display will surely fail: bandwidth limitations will
instantly surface, but also maintaining the same level of reliability can easily
cause headaches.
Yet another issue that pops up when components lie far apart is the
fact that wide-area systems generally have only very limited facilities for
multipoint communication. In contrast, local-area networks often support
efficient broadcasting mechanisms. Such mechanisms have proven to be
extremely useful for discovering components and services, which is essential
from a management perspective. In wide-area systems, we need to develop
separate services, such as naming and directory services, to which queries
can be sent. These support services, in turn, need to be scalable as well and
often no obvious solutions exist as we will encounter in later chapters.
Scaling techniques
Client Server
M
FIRST NAME MAARTEN A
LAST NAME VAN STEEN A
E-MAIL R
[email protected] T
E
N
Client Server
Figure 1.6: The difference between letting (a) a server or (b) a client check
forms as they are being filled.
A much better solution is to ship the code for filling in the form, and possibly
checking the entries, to the client, and have the client return a completed
form, as shown in Figure 1.6(b). This approach of shipping code is widely
supported by the Web through JavaScript.
Z1
int com edu gov mil org net jp us nl
sun yale Z2
acm ieee ac co oce vu
robot pc24
Figure 1.7: An example of dividing the (original) DNS name space into zones.
it may even appear as if there is only a single server. However, the Web
is physically partitioned and distributed across a few hundreds of millions of
servers, each handling often a number of Websites, or parts of Websites. The
name of the server handling a document is encoded into that document’s
URL. It is only because of this distribution of documents that the Web has
been capable of scaling to its current size. Yet, note that finding out how many
servers provide Web-based services is virtually impossible: A Website today
is so much more than a few static Web documents.
Discussion When considering these scaling techniques, one could argue that
size scalability is the least problematic from a technical perspective. Often,
increasing the capacity of a machine will save the day, although perhaps
there is a high monetary cost to pay. Geographical scalability is a much
tougher problem, as network latencies are naturally bound from below. As
a consequence, we may be forced to copy data to locations close to where
clients are, leading to problems of maintaining copies consistent. Practice
shows that combining distribution, replication, and caching techniques with
different forms of consistency generally leads to acceptable solutions. Finally,
administrative scalability seems to be the most difficult problem to solve,
partly because we need to deal with nontechnical issues, such as politics of or-
ganizations and human collaboration. The introduction and now widespread
use of peer-to-peer technology has successfully demonstrated what can be
achieved if end users are put in control [Lua et al., 2005; Oram, 2001]. How-
ever, peer-to-peer networks are obviously not the universal solution to all
administrative scalability problems.
(a) (b)
Its essence is that multiple threads of control are executing at the same time,
while all threads have access to shared data. Access to that data is controlled
through well-understood synchronization mechanisms like semaphores (see Ben-
Ari [2006] or Herlihy et al. [2021] for more information on developing parallel
programs). Unfortunately, the model does not easily scale: so far, machines have
been developed in which only a few tens (and sometimes hundreds) of CPUs
have efficient access to shared memory. To a certain extent, we are seeing the
same limitations for multicore processors.
To overcome the limitations of shared-memory systems, high-performance
computing moved to distributed-memory systems. This shift also meant that many
programs had to make use of message passing instead of modifying shared data as
a means of communication and synchronization between threads. Unfortunately,
message-passing models have proven to be much more difficult and error-prone
compared to the shared-memory programming models. For this reason, there
has been significant research in attempting to build so-called distributed shared-
memory multicomputers, or simply DSM systems [Amza et al., 1996].
In essence, a DSM system allows a processor to address a memory location
at another computer as if it were local memory. This can be achieved using
existing techniques available to the operating system, for example, by mapping
all main-memory pages of the various processors into a single virtual address
space. Whenever a processor A addresses a page located at another processor B,
a page fault occurs at A allowing the operating system at A to fetch the content of
the referenced page at B in the same way that it would normally fetch it locally
from disk. At the same time, the processor B would be informed that the page is
currently not accessible.
Cluster computing
Cluster computing systems became popular when the price/performance
ratio of personal computers and workstations improved. At a certain point, it
became financially and technically attractive to build a supercomputer using
off-the-shelf technology by simply hooking up a collection of relatively simple
computers in a high-speed network. In virtually all cases, cluster computing is
used for parallel programming, in which a single (compute intensive) program
is run in parallel on multiple machines. The principle of this organization is
shown in Figure 1.9.
This type of high-performance computing has evolved considerably. As
discussed extensively by Gerofi et al. [2019], the developments of supercom-
puters organized as clusters have reached a point where we see clusters with
more than 100,000 CPUs, with each CPU having 8 or 16 cores. There are mul-
tiple networks. Most important is a network formed by dedicated high-speed
interconnects between the various nodes (in other words, there is often no
such thing as a shared high-speed network for computations). A separate
management network, as well as nodes, are used to monitor and control
Grid computing
A characteristic feature of traditional cluster computing is its homogeneity.
In most cases, the computers in a cluster are largely the same, have the
same operating system, and are all connected through the same network.
However, as we just discussed, there is a continuous trend toward more
hybrid architectures in which nodes are specifically configured for certain
tasks. This diversity is even more prevalent in grid-computing systems: no
assumptions are made concerning similarity of hardware, operating systems,
networks, administrative domains, security policies, etc. [Rajaraman, 2016].
A key issue in a grid-computing system is that resources from different
organizations are brought together to allow the collaboration of a group of
people from different institutions, indeed forming a federation of systems.
Such a collaboration is realized in the form of a virtual organization. The
processes belonging to the same virtual organization have access rights to the
The architecture consists of four layers. The lowest fabric layer provides
interfaces to local resources at a specific site. Note that these interfaces are
tailored to allow sharing of resources within a virtual organization. Typically,
they will provide functions for querying the state and capabilities of a resource,
along with functions for actual resource management (e.g., locking resources).
The connectivity layer consists of communication protocols for supporting
grid transactions that span the usage of multiple resources. For example,
protocols are needed to transfer data between resources, or to simply access
a resource from a remote location. In addition, the connectivity layer will
contain security protocols to authenticate users and resources. Note that in
many cases, human users are not authenticated; instead, programs acting on
behalf of the users are authenticated. In this sense, delegating rights from
a user to programs is an important function that needs to be supported in
the connectivity layer. We return to delegation when discussing security in
distributed systems in Chapter 9.
The resource layer is responsible for managing a single resource. It uses the
functions provided by the connectivity layer and calls directly the interfaces
made available by the fabric layer. For example, this layer will offer functions
for obtaining configuration information on a specific resource, or, in general,
to perform specific operations such as creating a process or reading data. The
resource layer is thus seen to be responsible for access control, and hence will
rely on the authentication performed as part of the connectivity layer.
The next layer in the hierarchy is the collective layer. It deals with handling
access to multiple resources and typically consists of services for resource
discovery, allocation and scheduling of tasks onto multiple resources, data
replication, and so on. Unlike the connectivity and resource layer, each
consisting of a relatively small, standard collection of protocols, the collective
layer may consist of many protocols reflecting the broad spectrum of services
it may offer to a virtual organization.
Finally, the application layer consists of the applications that operate
within a virtual organization and which make use of the grid computing
environment.
Typically, the collective, connectivity, and resource layer form the heart of
what could be called a grid middleware layer. These layers jointly provide
access to and management of resources that are potentially dispersed across
multiple sites.
An important observation from a middleware perspective is that in grid
computing, the notion of a site (or administrative unit) is common. This
prevalence is emphasized by the gradual shift toward a service-oriented ar-
chitecture in which sites offer access to the various layers through a collection
of Web services [Joseph et al., 2004]. This, by now, has led to the definition of
an alternative architecture known as the Open Grid Services Architecture
(OGSA) [Foster et al., 2006]. OGSA is based upon the original ideas as for-
mulated by Foster et al. [2001], yet having gone through a standardization
process makes it complex, to say the least. OGSA implementations generally
follow Web service standards.
Primitive Description
BEGIN_TRANSACTION Mark the start of a transaction
END_TRANSACTION Terminate the transaction and try to commit
ABORT_TRANSACTION Kill the transaction and restore the old values
READ Read data from a file, a table, or otherwise
WRITE Write data to a file, a table, or otherwise
Server
Reply
Transaction Request
Requests
Request
Client Server
TP monitor
application
Reply
Reply
Request
Server
Reply
• File format and layout: text, binary, its structure, and so on. Nowadays,
the extended markup language (XML) has become popular as its files
are, in principle, self-describing.
• File management: where are they stored, how are they named, who is
responsible for deleting files?
• Update propagation: When an application produces a file, there may
be several applications that need to read that file to provide the view
of a single coherent system. As a consequence, sometimes separate
programs need to be implemented that notify applications of file
updates.
Shared database: Many of the problems associated with integration through files
are alleviated when using a shared database. All applications will have
access to the same data, and often through a high-level database language
such as SQL. Furthermore, it is easy to notify applications when changes
occur, as triggers are often part of modern databases. There are, however,
two major drawbacks. First, there is still a need to design a common
data schema, which may be far from trivial if the set of applications that
need to be integrated is not completely known in advance. Second, when
there are many reads and updates, a shared database can easily become a
performance bottleneck.
Remote procedure call: Integration through files or a database implicitly as-
sumes that changes by one application can easily trigger other applications
to act. However, practice shows that sometimes small changes should
actually trigger many applications to take actions. In such cases, it is not
really the change of data that is important, but the execution of a series of
actions.
Series of actions are best captured through the execution of a procedure
(which may, in turn, lead to all kinds of changes in shared data). To prevent
that every application needs to know all the internals of those actions (as
implemented by another application), standard encapsulation techniques
should be used, as deployed with traditional procedure calls or object
invocations. For such situations, an application can best offer a procedure
to other applications in the form of a remote procedure call, or RPC. In
essence, an RPC allows an application A to make use of the information
available only to the application B, without giving A direct access to that
information. There are many advantages and disadvantages to remote
procedure calls, which are discussed in depth in Chapter 4.
Messaging: A main drawback of RPCs is that caller and callee need to be up
and running at the same time in order for the call to succeed. However, in
many scenarios, this simultaneous activity is often difficult or impossible
Ad. 3: Context awareness Reacting to the sensory input, but also the explicit
input from users, is more easily said than done. What a ubiquitous computing
system needs to do, is to take the context in which interactions take place
into account. Context awareness also differentiates ubiquitous computing
systems from the more traditional systems we have been discussing before,
and is described by Dey and Abowd [2000] as “any information that can be
used to characterize the situation of entities (i.e., whether a person, place, or
object) that are considered relevant to the interaction between a user and an
application, including the user and the application themselves.” In practice,
context is often characterized by location, identity, time, and activity: the where,
who, when, and what. A system will need to have the necessary (sensory) input
to determine one or several of these context types. As discussed by Alegre
et al. [2016], developing context-aware systems is difficult, if only for the
reason that the notion of context is difficult to grasp.
What is important, from a distributed-systems perspective, is that raw
data as collected by various sensors is lifted to a level of abstraction that can
be used by applications. A concrete example is detecting where a person is,
Admittedly, these are simple examples, but the picture should be clear that
manual intervention is to be kept to a minimum. We will be discussing many
techniques related to self-management in detail throughout the book.
intelligence. What this means, is that often a wide range of advanced algo-
rithms and models need to be deployed to handle incomplete input, quickly
react to a changing environment, handle unexpected events, and so on. The
extent to which this can or should be done in a distributed fashion is cru-
cial from the perspective of distributed systems. Unfortunately, distributed
solutions for many problems in the field of artificial intelligence are yet to
be found, meaning that there may be a natural tension between the first
requirement of networked and distributed devices, and advanced distributed
information processing.
et al. [2019]). Practice has shown over and over again that voluntarily making
resources available is not something users are willing to do, even if they have
resources in abundance. The effect is that in the case of mobile computing,
we generally see single mobile devices setting up connections to stationary
servers. Changing locations then simply means that those connections need
to be handed over by routers on the path from the mobile device to the
server. Mobile computing is then brought back to its essence: a mobile device
connected to a server (and nothing else). In practice, this means that mobile
computing is all about mobile devices making use of cloud-based services, as
sketched in Figure 1.15(a).
(a)
(b)
Figure 1.15: (a) Mobile Cloud Computing versus (b) Mobile Edge Computing.
Sensor networks
1 region = k_nearest_region.create(8);
2 reading = get_sensor_reading();
3 region.putvar(reading_key, reading);
4 max_id = region.reduce(OP_MAXID, reading_key);
In line 1, a node first creates a region of its eight nearest neighbors, after which
it fetches a value from its sensor(s). This reading is subsequently written to
the previously defined region to be defined using the key reading_key. In
line 4, the node checks whose sensor reading in the defined region was the
largest, which is returned in the variable max_id.
When considering that sensor networks produce data, one can also focus
on the data-access model. This can be done directly by sending messages to
and between nodes, or either moving code between nodes to locally access
data. More advanced is to make remote data directly accessible, as if variables
and such were available in a shared data space. Finally, and also quite popular,
is to let the sensor network provide a view of a single database. Such a
view is easy to understand when realizing that many sensor networks are
deployed for measurement and surveillance applications [Bonnet et al., 2002].
In these cases, an operator would like to extract information from (a part of)
the network by simply issuing queries such as “What is the northbound traffic
load on highway 1 at Santa Cruz?” Such queries resemble those of traditional
databases. In this case, the answer will probably need to be provided through
collaboration of many sensors along highway 1, while leaving other sensors
untouched.
To organize a sensor network as a distributed database, there are essentially
two extremes, as shown in Figure 1.16. First, sensors do not cooperate but
simply send their data to a centralized database located at the operator’s site.
The other extreme is to forward queries to relevant sensors and to let each
compute an answer, requiring the operator to aggregate the responses.
Neither of these solutions is very attractive. The first one requires that
sensors send all their measured data through the network, which may waste
network resources and energy. The second solution may also be wasteful,
as it discards the aggregation capabilities of sensors, which would allow
much fewer data to be returned to the operator. What is needed are facilities
for in-network data processing, similar to the previous example of abstract
regions.
In-network processing can be done in numerous ways. One obvious way
is to forward a query to all sensor nodes along a tree encompassing all nodes
and to subsequently aggregate the results as they are propagated back to the
root, where the initiator is located. Aggregation will take place where two
or more branches of the tree come together. As simple as this scheme may
sound, it introduces difficult questions:
• How do we (dynamically) set up an efficient tree in a sensor network?
• How does aggregation of results take place? Can it be controlled?
(a)
(b)
Figure 1.16: Organizing a sensor network database, while storing and process-
ing data (a) only at the operator’s site or (b) only at the sensors.
Figure 1.17: A hierarchical view from clouds to devices (adapted from Yousef-
pour et al. [2019]).
As may have become clear by now, distributed systems span a huge range of
different networked computer systems. Many of such systems operate in a
setting in which the various computers are connected through a local-area
network. Yet with the growth of the Internet-of-Things and the connectivity
with remote services offered through cloud-based systems, new organizations
across wide-area networks are emerging. Figure 1.17 presents this more
hierarchical approach.
Typically, higher up the hierarchy we see that typical qualities of dis-
tributed systems improve: they become more reliable, have more capacity,
and, in general, perform better. Lower in the hierarchy, we see that location-
related aspects are easier facilitated, as well as performance qualities related to
latencies. At the same time, the lower parts show in an increase in the number
of devices and computers, whereas higher up, the number of computers
becomes less.
1.4 Pitfalls
It should be clear by now that developing a distributed system is a formidable
task. As we will see many times throughout this book, there are so many
issues to consider, while it seems that only complexity can be the result.
Note how these assumptions relate to properties that are unique to dis-
tributed systems: reliability, security, heterogeneity, and topology of the
network; latency and bandwidth; transport costs; and finally administrative
domains. When developing nondistributed applications, most of these issues
will most likely not show up.
Most of the principles we discuss in this book relate immediately to these
assumptions. In all cases, we will be discussing solutions to problems that
are caused by the fact that one or more assumptions are false. For example,
reliable networks simply do not exist and lead to the impossibility of achieving
failure transparency. We devote an entire chapter to deal with the fact that
networked communication is inherently insecure. We have already argued
that distributed systems need to be open and take heterogeneity into account.
Likewise, when discussing replication for solving scalability problems, we
are essentially tackling latency and bandwidth problems. We will also touch
upon management issues at various points throughout this book.
1.5 Summary
A distributed system is a collection of networked computer systems in which
processes and resources are spread across different computers. We make a
distinction between sufficiently and necessarily spread, where the latter relates
to decentralized systems. This distinction is important to make, as spreading
processes and resources cannot be considered to be a goal by itself. Instead,
most choices for coming to a distributed system come from the need to im-
prove the performance of a single computer system in terms of, for example,
reliability, scalability, and efficiency. However, considering that most cen-
tralized systems are still much easier to manage and maintain, one should
think twice before deciding to spread processes and resources. There are also
cases when there is simply no choice, for example when connecting systems
belonging to different organizations, or when computers simply operate from
different locations (as in mobile computing).
Design goals for distributed systems include sharing resources and ensur-
ing openness. Increasingly important is designing secure distributed systems.
In addition, designers aim at hiding many of the intricacies related to the
distribution of processes, data, and control. However, this distribution trans-
parency not only comes at a performance price, in practical situations it can
never be fully achieved. The fact that trade-offs need to be made between
achieving various forms of distribution transparency is inherent to the design
of distributed systems, and can easily complicate their understanding. One
specific difficult design goal that does not always blend well with achieving
distribution transparency is scalability. This is particularly true for geographi-
cal scalability, in which case hiding latencies and bandwidth restrictions can
turn out to be difficult. Likewise, administrative scalability, by which a system
is designed to span multiple administrative domains, may easily conflict with
goals for achieving distribution transparency.
Different types of distributed systems exist which can be classified as
being oriented toward supporting computations, information processing, and
pervasiveness. Distributed computing systems are typically deployed for
high-performance applications, often originating from the field of parallel
computing. A field that emerged from parallel processing was initially grid
computing with a strong focus on worldwide sharing of resources, in turn
leading to what is now known as cloud computing. Cloud computing goes
beyond high-performance computing and also supports distributed systems
found in traditional office environments, where we see databases playing
an important role. Typically, transaction processing systems are deployed
in these environments. Finally, an emerging class of distributed systems is
where components are small, the system is composed in an ad hoc fashion,
but most of all is no longer managed through a system administrator. This last
class is typically represented by pervasive computing environments, including
mobile-computing systems as well as sensor-rich environments.
Matters are further complicated by the fact that many developers initially
make assumptions about the underlying network that are fundamentally
wrong. Later, when assumptions are dropped, it may turn out to be difficult
to mask unwanted behavior. A typical example is assuming that network
latency is not significant. Other pitfalls include assuming that the network is
reliable, static, secure, and homogeneous.