CHAPTER  
13

Tricky Business

Cloud Implementation Practices

SUMMARY

This chapter is about the technical side of cloud applications. It discusses implementing applications and services that are to be deployed on clouds. The chapter emphasizes Infrastructure as a Service (IaaS) implementations, although much of the material applies also to Platform as a Service (PaaS) implementations. The approach is high-level, discussing architecture rather than code strategies. The strategies also apply to building Software as a Service (SaaS) applications for cloud deployment but not specific strategies, such as multitenancy, for SaaS. In addition, public clouds are assumed. Private and community implementers will also benefit from the material here, although their implementations may be somewhat simpler.

Any IT project requires collaboration between IT technologists and business management. Every project carries some risk. Cloud projects often generate more risk because the technology is new and the business model is unfamiliar. The previous chapter discussed the business aspects of cloud projects. This chapter will discuss the technical side of cloud projects.

Business and technical requirements are related closely. Both business and technology have to work together to deliver an implementation that meets expectations. Often cloud projects do not focus on new functionality. Instead, they are expected to reduce the cost of delivering the service, increase reliability and maintainability, and streamline on-premises operations and administration. Success requires some purely business initiatives, as discussed in the previous chapter, but the technical side also has to take steps to achieve these goals. Too often, moving an existing service to a cloud is seen as a port,1 similar to a port from one operating system to another. That is only partially true. Most applications built to run on-premises are not designed with cloud features in mind. They probably will port with some changes here and there in network addressing, firewalls, and perhaps strengthening security to cope with more exposed communication with the cloud. However, the resulting cost savings are likely to be less than expected, and other anticipated benefits may not materialize.

The solution is to make the investment necessary to revamp the on-premises service to one that takes advantage of the cloud or to propose a stepwise approach that will add anticipated benefits slowly over time. Both of these paths can easily become expensive. Rebuilding an application to work well on a cloud is seldom trivial. A gradual approach may have less up-front cost, but the total cost may be more. Managing and designing stepwise development is often more challenging than rebuilding from the beginning. There is no easy answer, but the pitfalls are fewer and less deep when all the parties are aware of the trade-offs.

The upside is that the techniques of cloud computing are not new. Most of them are long-standing best practices for enterprise service design that are now being applied in a new way. An application built or revised recently to follow best practices for scalability, performance, security, and accessibility is likely to transition easily to a cloud environment without excessive redesign or rewriting; this is less so for older applications.

Cloud Implementations and Technical Success

A successful cloud implementation above all must meet business requirements. The challenge to the developer is to confirm that business requirements are met before correcting the issues becomes irredeemably expensive. Some issues can be self-correcting; if business representatives become aware that a requirement is not met, they often put up such a squawk that the gap is quickly filled. Unfortunately, this does not happen as frequently as one would hope. It may be counterintuitive, but the more often the business side of the house raises issues, the more likely the project is to succeed, provided both business and IT approach the issues in a spirit of cooperation rather than antagonism.

Gaps cannot be identified if the requirements are not articulated clearly, especially to the business managers themselves. They sometimes are not aware of the reasons for a move to a cloud implementation and recognize the issue only after the project is complete. Or the project may be developed in isolation without a robust feedback loop between business and development functions. Also, the business benefits from a cloud implementation are not easily tested until after the project is deployed, which may lead to skepticism. Agile development methodology is especially helpful here. One of the basic tenets of Agile development is a sturdy feedback loop between developers and customers from beginning to end of a project. Agile development also encourages many small incremental releases that can be examined by the stakeholders and tested as they are released. For most cloud implementations, there are two customers: the consumers of the services implemented on the cloud and the business owners of the service. Success depends on a thorough mutual understanding among all parties. The previous chapter attacked these challenges from the view of the manager.

Basic Cloud Application Requirements

A successful cloud must be maintainable. It must have a convenient mechanism for applying patches and upgrades without interrupting production. When defects crop up, the system should degrade gracefully. Systems should reduce features and output rather than crashing, never corrupt or destroy data, issue helpful error messages, and write extensive internal logs for maintainers to trace the root cause of the problem. Designers must be aware that cloud-based virtual systems may require methods that are not the same as on-premises applications. For example, patching virtual machines present problems that do not exist on on-premises nonvirtual applications.

When possible, processes should be tunable; that is, the operating parameters of a system can be changed to match the circumstances of the workload. For example, systems are usually conservative about starting and stopping new virtual machines in response to fluctuating workloads. Starting and stopping virtual machines is slow and consumes system resources. Therefore, adjusting their number too quickly can cause the system to waste resources by responding to minor fluctuations in the load. However, in some situations, a more liberal policy of starting new processes quickly provides superior performance and justifies the use of resources. If an administrator can adjust the starting and stopping of parameters, the process can be tuned to the workload with superior results. The use of containers provides further opportunities for tuning. Since several containers can run on the same VM, new containers can be launched without the overhead of a full VM launch.

It’s often said that the only constant in business is change. A cloud system ought to be built as flexibly as possible to ensure that it can be modified and reused in the future as the business and technical environments change. It also must scale both up and down and meet basic security requirements and the special requirements of the business.

Cloud applications usually depend on networks more than on-premises applications. Therefore, cloud applications should be built with the network in mind. For example, backups and failover are likely to involve the network. Designers must assume all components, especially the network, may be unreliable.

Finally, the system must be usable. Visual displays should not be difficult to interpret or use. Consumers should have convenient access to the data they need, and the appearance should be aesthetically pleasing. In addition, displays should be easily ported to new display devices, perhaps smartwatches or other wearable computing devices.

These characteristics mark any successful system, not just a cloud system. In cloud implementations, these characteristics make successful systems both easier and more difficult to implement.

CLOUD APPLICATION IMPERATIVES

  • Maintainable: Include maintainability features, such as supporting patching without interrupting production.
  • Tunable: Design applications for adjustment to workloads and the environment without patching or rebuilding.
  • Flexible: Support easy modification to conform to changing business conditions and environment.
  • Network aware and fault-tolerant: Design applications to tolerate unreliable networks and components that may fail.
  • Usable: Provide customers with convenient and effective access to the system.

Cloud Implementation Principles

Cloud configurations can be changed quickly without the costs and delays associated with purchasing, leasing, and re-cabling physical servers. Additional virtual servers can be launched with a few keyboard strokes instead of waiting for the hardware to be delivered from a supplier or warehouse and installing it in the datacenter. Unlike physical assets, cloud implementations can be scaled up and down quickly and easily because the changes are all in the software, not in the physical hardware. From the cloud consumer’s view, virtual assets are reconfigured in software, but on the provider’s level, physical computing resources are acquired and relinquished. This activity can be carried out almost entirely automatically but only if the consumer’s applications running in the implementation are designed to reconfigure and scale well in a virtual environment. Other advantages to cloud implementations, such as resilience, are similar, but only when the consumer’s implementation is designed to use cloud facilities efficiently. Developers should be aware of a number of concepts for building cloud applications that deliver on the cloud’s promise.

Avoid Monoliths

In the early stages of computing, all programs were single, stand-alone entities, now often called monoliths or monolithic applications. A monolith is an application in which all functionality is built into a single self-contained process. When a monolith is up and running, it does not depend on any processes other than the operating system. All the code for the application is coded, compiled, and linked into a single entity. This approach worked well on mainframes, and some mainframe programs are still monoliths.

A monolith is the most natural architecture for an application. When developers begin with a set of requirements and start writing code without much thought to the overall system or its behavior in production, chances are good that a single large component, a monolith, will be the result. How the system will scale, how it will be maintained, how will it behave when a defect appears, and how it will support a large geographic area will all be afterthoughts.

If there is more than a single developer, the code of a monolith may be separated into libraries and code modules to clarify the organization of the code and make it easier for developers to code simultaneously, but the executable runtime module will still be linked together into a single runnable entity. Programs like this can be well-designed and efficient, but they seldom have characteristics that take advantage of the strengths of cloud deployment.

A monolith usually scales up vertically by running on higher-capacity processors at increased processing cycles per second, with faster data buses, more and faster random access memory, and faster input and output.2 It can scale down by running on a smaller processor with fewer resources. This is often the only alternative because the monolith is not designed to increase capacity by adding new processes to divide the load.

Scaling up and down by varying the size of the virtual machine to another is seldom practical. Moving to different CPUs is easier in a cloud environment than a physical environment, but both scaling up and scaling down monoliths tends to be disruptive because monoliths are seldom designed with starting, stopping, and transferring workloads in mind. Users may have to restart transactions that are interrupted before they complete. If the monolith is not built with well-designed threads, the application may not gain much capacity when moved to a virtual machine with more cores rather than greater clock speed and a faster bus. Unless the application underwent testing with multicore systems with scaled-up loads that drove the threading hard, hidden defects are hard to avoid in the complex code that monoliths often exhibit.

There are some benefits from a multicore processor that do not require well-designed threads that are derived from parallel processing in the operating system and compilers that can produce parallel code automatically, but many applications, especially older applications, do not gain much capacity from multicore processing. This is unfortunate because cloud providers tend to provide more cores and processors than faster CPUs and buses in their larger virtual machines. This reflects the fact that most cloud providers build their datacenters from many identical and relatively simple generic computers rather than larger and large servers. In addition, chip manufacturers now usually increase the capacity of their chips by adding cores.

Applications that use more than one process can be distributed over multiple CPUs and cores to take greater advantage of the added capacity.

Further, a single monolithic process can be difficult to maintain in a high-production environment. It is difficult to make a single process degrade gracefully. Most often, when a fault occurs, the entire service crashes. Keeping a single process running when part of it is no longer functioning is not impossible but difficult.

An application that consists of several asynchronously communicating processes is more difficult to code, but degradation is easily managed and scaling is much simpler. At its simplest, when a process fails, processes sending messages to a failing process begin to queue messages, waiting for the failed process to begin to receive messages. Processes that expect messages to wait, presumably will do useful work until the messages arrive. If the failing process is not restored, eventually the system will probably stop, but there is time to put up informative error messages, repair, or restart the failed process before damage is done.

There are many elaborations and variations on this pattern. In the best scenarios, the faulty process is automatically restarted or redundant processes simply take over for the weak sister.

Threads can increase the resiliency of a monolith because the failure of a thread will not halt the process, but there are trade-offs. Threads, especially when indiscriminately used without due regard for reentrancy, increase the complexity of a system and multiply opportunities for defects. In addition, a thread is not isolated from the overall process. When the process fails or degrades, all threads fail or degrade. Generally, threads can make some aspects of a system, such as asynchronous messaging, easier to code, but an application that uses multiple processes can be more resilient.

Applications that use more than one process are also often easier to maintain because processes can be stopped and replaced with patched versions without bringing down the whole application. A typical action performed while maintaining a process is to stop the process, apply patches, and restart the process.

A further refinement on multiprocess applications is multiple parallel processes. Parallel processes do the same thing. Instead of sending all requests of a given type to the same process, the request can be sent to any number of processes. This can be done in a simple round-robin that distributes messages without regard to the load on the receiving process. Another possibility is distribution to the process with the shortest input queue. More sophisticated algorithms are also used. Applications like this are well-suited to a virtual cloud environment. They scale up and down by adding or removing virtual machines. For an application that consists of a number of parallel processes on virtual machines, all doing the same thing, patches that require shutting the process down can be performed without interrupting production. The virtual machines are patched one at a time, keeping the others running to support the production workload. Each virtual machine is shut down and patched and then restarted. Patching this way is frequently scripted and automated.

Using these techniques, rolling releases become attractive. A rolling release updates an application or system in increments rather than massive installations that replace the entire application. A rolling release introduces change gradually and aligns with the small and frequent releases of the Agile methodology and DevOps practice.

Horizontal Scalability

Horizontal scalability is not a new concept in this book, but developers must realize how crucial horizontal scaling is to building robust cloud applications. Without horizontal scaling, many of the technical and business advantages of cloud computing are compromised. Without horizontal scalability, as discussed earlier, automated up and down scaling is difficult. Costs are likely to stay constant as usage declines, and performance is likely to degrade as usage increases.

As desirable as horizontally scalable services are, they are more complex to build than vertically scalable services. A fundamental example is based on the common architecture in which a web server receives Hypertext Transmission Protocol (HTTP) messages from remote processes, usually either browsers or mobile apps.3 There may be multiple web servers, as in Figure 13-1. A load balancer distributes connections among the web servers. The web server breaks the message down and passes subrequests to the message to the application server. A load balancer distributes messages among the application servers. If the remote processes are stateless (in other words, the reply to the request does not depend on state from previous requests stored on the server), the load balancer for the application servers can pass the message to any available application server. If the requests sent to the application server have state, the load balancer must maintain connections between each application server and the end consumers it is supporting. On both the web server level and the application server level in this example, the number of servers can be extended automatically by management processes built into the cloud.

9781430261667_Fig13-01.jpg

Figure 13-1. A service designed to scale horizontally often scales on more than one level

Stateless Services

Services that do not rely on state are easier to build, are usually more reliable, and scale better. At the same time, they usually require more planning for performance and usability. If application server processes are not stateless, information on what has happened in previous transactions with the application must be preserved. This can be accomplished in several ways. One way is for the application server to store a record of previous transactions with the end user. The load balancer must also keep track in some way of which application server was used to service which users. The requests from the same user go to the application server, and the application server holds the state of the interaction with the user. This method requires that a client session always reattach to the same server. A much better approach allows a client to attach to any server. A central repository for state that all the servers can access supports clients reattaching to any server. A central repository can increase robustness but adds another component to build and maintain and another potential source of latency.

HTTP is designed to be stateless. HTTP does not require that a server ever keep track of previous messages from a sender. For example, when basic authentication is used, the user must send a valid username and password with each message. If the server does maintain an authenticated state between pages, it is done over HTTP without relying on the protocol to support the state.

Compared to a stateless service, a stateful service is complicated. The store of state information has to be managed. When transactions complete normally, problems may be few, but that is not nearly adequate for a production service. Devices overheat. Disks fail. Browsers crash. Users click the wrong button or are distracted and walk away. Administrators make mistakes. Especially in cloud implementations, network connections fail or time out. When a transaction is interrupted, the server must decide when to kill the transaction, how much of the transaction to roll out, and what to do with store of state information—delete it all, save some, leave it intact, or reconstruct the transaction from the log when the user returns. Each alternative is appropriate in some situations. To gain the information necessary to decide, the state store must be examined, and the state of the transaction must be determined. After evaluating the state, action choices depend on the business use of the application as well as software engineering. Developers cringe at coding for these situations because unwinding those state stacks often lead to surprising and anomalous situations that are seldom addressed in the specifications. Developers, and often the quality assurance team, are left to muddle through to a solution that is often an unsatisfactory and uninformed compromise. Pickles like this are not unique to unwinding the transactions stack, but stateless servers remove one source of the issues.

Business and technology are always mutually dependent and require mutual understanding. Stateless services are one way of relaxing that binding. In the case of horizontal scaling, maintaining stateless where possible eases the job of software designers and, at the same time, makes the design of the application more transparent to the users.

Sometimes stateless transactions are not possible, but when they are possible, they result in more robust and reliable systems.

Service-Oriented Architecture

Service-oriented architecture (SOA) is an elegant and efficient way to build applications that works well in cloud computing. Many large enterprises have invested heavily in SOA. An SOA designer decomposes applications into a hierarchy of services. All services and subservices have their own addressable APIs. When a service is needed, its API is called, and the implementation of the service responds. A service implementation may be shared between several services, or services can be implemented independently. Applications are constructed by combining and composing services.

Several architectural concepts are closely related to SOA and more suited to smaller installations. The fundamental concept is to decompose architectures into granular services and objects that can be accessed independently. Access is built on web services. Microservices emphasize granular services. Resource-oriented architecture (ROA) focuses on granular access to application resource objects.

SOAP and Representational State Transfer (REST)

Two types of SOA interfaces are common: REST and SOAP.4 Both interfaces usually use HTTP as their transport protocol, although both are transport protocol independent and can be used with other protocols. SOAP implementation stacks are readily available, but some developers find them overly complex and irksome. REST interfaces do not require an elaborate software stack, but the REST architecture is based on document exchange on the World Wide Web. Consequently, supporting some applications, such as transactional applications that involve interaction with several data services, can be more difficult with REST. SOAP interfaces are likely to be found inside enterprise implementations, while REST is more prevalent in widely accessible Internet applications. Often applications combine REST and SOAP, using REST for browser to web server activity and SOAP in the back end.

Occasionally the SOAP and REST advocates seem to be armed camps in opposition. Each side has its strength. The SOAP stack is complex, but developers can install it as a black box and not worry about its inner workings. However, tuning and debugging a service when the stack is a black box can be difficult. REST does away with stack complexity, but complexity re-appears when applications are not easily expressed in the REST model.

The decision to go with REST or SOAP frequently depends on the familiarity of the development team with the two approaches. A team that is expert with SOAP and comfortable with its stack will produce a more robust application with SOAP. A REST team can produce a more compact and performant application building on REST. Neither is likely to do well with an unfamiliar technology.

SOAP and REST have many significant differences, but a major difference is that REST is stateless; SOAP is stateful. In addition, SOAP is a protocol that can be used with many architectures. REST, on the other hand, is an architecture that enables a protocol. Stateless SOAP-based services are possible, and it is possible to implement the equivalent of a stateful service with REST.

SOA in the Cloud

Whether based on SOAP or REST, SOA, along with microservices and ROA, is well suited to cloud implementations. Applications implemented with SOA typically can be made to scale well in a cloud with load-balanced parallel service implementations. An application that exposes SOA services as its public interface can be used by browsers and other graphic interfaces such as mobile apps. In addition, such an application can be used by “headless” processes such as those used in the Internet of Things. The “mix-and-match” style of SOA also promotes flexibility and rapid development of services created from new groupings of existing services.5 SOA also contributes to ease of enterprise integration by providing SOA interfaces as a natural means of connecting enterprise applications.

Figure 13-2 illustrates an SOA cloud implementation of two applications that share services. The upper application, A, is highly scalable with both web servers and application servers automatically replicated as the load increases. On the SOA service level, services 1 and 3 are replicated and load balanced. Services 2 and 4 are not, probably because they are not likely to cause performance issues. Perhaps the services are infrequently used or they are lightweight and execute rapidly.

9781430261667_Fig13-02.jpg

Figure 13-2. An SOA architecture decomposes business functions into services that can be used by more than one application

Application B is not designed to scale, except when necessary to cope with application A’s load. Notice that the B application server goes through the load balancers for services 1 and 3. This means that loads coming from application B are in the same pool of loads as those coming from application A. If the B loads were to go directly to one of the instances of service 1 or 3, the instance of the service used by B could be overwhelmed by loads from A. By going through the load balancer, B loads are always directed to the optimum service instance.

Asynchrony and Responsiveness Principles

Asynchronous communication is a type of message protocol that has been discussed before in these pages. However, asynchronous communication is a cornerstone of all efficient cloud applications. Without asynchrony, processes are held in lockstep. If a process must stop processing and wait for a reply, such as calling a function from a statically linked library, the calling process is blocked by the called process until it is complete. Asynchronous messaging deals with this problem. The cost of avoiding blocking is the overhead of callback and wait mechanisms. Usually, this is an acceptable trade-off.

Synchronous dependency can be acceptable in a low-volume environment where communication is not subject to variations in network latency and bandwidth and variable loads on different parts of the system. In a low-volume system, a synchronous wait typically results in a pause for one user, which is undesirable but tolerable. In a high-volume system, the same wait will stop many users, which can easily become intolerable. Public clouds that rely on the Internet are always subject to network variations, which can be slowdowns or flat-out interruptions. A synchronous wait caused by a network failure can bring an application to a halt. Wireless connections add another element of variability.

Asynchronous communication is usually used in conjunction with message queuing in basic web application architecture. A browser sends an HTTP request to an HTTP server6 running on a cloud, which calls an application layer to perform an operation. If the browser waits synchronously for a reply from the server, the user may end up staring at an hourglass while the browser waits for a reply from a busy application server. A much more suitable approach is to use asynchronous messaging with queuing. Operating in this manner, the users send their requests, and the HTTP server immediately replies, acknowledging that the message has been received but nothing more. The HTTP server passes the message to the application server queue. The message stays in the queue until the application server is ready to process it. When the message is processed, the application server sends a message back to the HTTP server. The HTTP server then passes the message to the user.

Handling the message queue has complications. If, for example, the application server fails before the incoming message is properly processed, the request should remain on the queue to be picked up by the next available application server. Commercial queue-handling products devote substantial effort to resolving complex queue handling issues.

Idempotency and Message Handling

An idempotent message can be repeated arbitrarily, and the effect is as if the message was delivered only once. A simple request for information is idempotent. The request can be repeated many times, but the result will not change. A less trivial example is an update to a relational database row. A simple update is idempotent. If the same row is updated and then updated again with the same values, the row will be the same as if it had been updated only once. On the other hand, a request that updates a numeric value using a database-stored subroutine to increment and update the value is not idempotent. With each repeated request, the value increases. Several requests are not the equivalent of one request.

Idempotent commands are easier to manage than nonidempotent commands. In the user interface, consumers are inclined to push a button repeatedly if the interface does not respond immediately with an acknowledgment. Warning messages cautioning users to wait after issuing a nonidempotent request are easily ignored or confused. Asking the user to compensate for a weakness in the interface courts user errors, especially when the interface is used continually by thousands of users.

More important for cloud applications, idempotent commands are much easier to manage internally when communications are interrupted or delayed.

If a command is not idempotent, it may be impossible to determine whether a command should be repeated. For example, a user issues a nonidempotent message to place an order; that is, repeating the request will generate two order records. The browser begins to wait for an acknowledgment. An accidental partitioning of the network blocks communication between the browser and the server. If the block occurred before the server received the message to place the order, the order request must be repeated. If the break occurred after the server received the order but before the acknowledgment was sent, the order request must not be repeated.

This dilemma for the browser and the end user is more difficult than a problematic message. The problem can be remediated, but the solution usually involves sorting out message sequences on both the browser and the server. Rolling back transactions may require complex logic. These solutions are best avoided if possible.

An idempotent order request is easier to manage. No harm is done if the browser or end user repeats the request until an acknowledgment arrives.

In the simplest case, using the idempotent HTTP PUT method rather than the nonidempotent POST is all that is necessary for idempotence. However, simply changing POST to PUT is seldom all that is necessary. A PUT targets a specific object. If the object does not exist, the server must create it with the values in the PUT body. If the object exists, the server must replace the object with the values in the PUT body. Calling the same PUT repeatedly has no effect because the contents of the PUT body do not change and the target object does not change.

POST is different. Usually, a POST targets a process that processes the POST body. The process may create a new object, modify an existing object, or do other actions. The effect of sending the same POST repeatedly depends on the process. If the process is to increment a value, the value will be nonidempotently incremented again. If the process does the equivalent of a PUT, the POST is idempotent. When a process must be involved, it can be designed to be idempotent. For example, an increment process can use data in the HTTP header to determine whether the POST is a repeat and not increment on subsequent calls.

Idempotency can be important to horizontally scalable cloud installations. These systems are dependent on communications between processes that are distributed over multiple interconnected nodes. Although many of these nodes may be within a single datacenter and less likely to fail than networks that depend on remote routers and communication links, they are nonetheless subject to accidental partitions, such as a connector pulled out of its socket when a technician trips over a cable. If requests are idempotent, recovering from a network failure is simply repeating the request. With load-balancing code to route the repeated request to an alternate node, the application is resilient to this kind of system fault. For large-scale, critical production applications, resiliency to network failures is extremely important, and time devoted to designing idempotency into interprocess communication can provide substantial return on the investment.

Consistency, Availability, and Network Partitions

One of the basic principles of distributed system design is the impossibility of a distributed system in which the data on every node is always consistent, the system is always available, and the system is never affected by network failures. The Consistency, Availability, and Network Partitions (CAP) principle asserts that only two of the three properties can be maintained at any one time. Since network partitions (failures in which one part of the network becomes isolated from the rest) are unavoidable in practice on the Internet, designers must always choose between consistency and availability.7

The ideal for data transactions is Atomicity, Consistency, Isolation, Durability (ACID). Without going into the details of ACID, it is an ideal that the CAP theorem shows is an unattainable goal in a distributed system that relies on an unreliable network. A basic challenge to cloud computing, and any other network dependent distributed system, is to cope with the reality of CAP.

Although a cloud implementation could occasionally be deployed on a single node and therefore not be distributed, cloud designers always have to assume that CAP applies. The choice between availability and consistency may be more subtle than it first appears.

Usually, it is an important business decision. Consistency is often thought of in conjunction with accounting. The accounts must always be consistent. However, most people have real-world experience with deposits, especially large deposits, that do not appear in their account until several hours—even days—after the deposit was made. Financial institutions often build latency into their systems to vet for mistakes and fraud. Instant consistency is not so important to them. This is the case for many systems.

On the other hand, availability may appear to be less important. A site that is unavailable for a short time may not seem to be important. But ask a large online retailer about sales sites that are unavailable. They may say that every minute of downtime costs them many dollars in sales.

The balance between consistency and availability is critical to many businesses. When shifting from an on-premises application where network failure within the enterprise perimeter is rare to a cloud implementation that is more exposed to network failure, cloud architects have to keep the consistency-availability trade-off in mind. They must also realize that the terms of the trade-off are critical to business, not just engineering. Most of the time, an adequate solution is a guarantee that, like the check that eventually shows up in your account, the system will eventually become consistent and availability will not be compromised to attain consistency.

Containers

Containers are an alternative to hypervisor-based virtualization that has gathered attention and favor recently. The concept behind containers was discussed in Chapter 11. Containers can be considerably smaller than a corresponding virtual machine image because they contain only the application, not the virtual machine that runs the application. When a container is launched, the operating system rather than the hypervisor manages processing and prevents mutual interference between containers.

The fundamental container abstraction is an application that can easily be deployed into an identical environment on a number of machines. In contrast, virtual machines are abstract machines on which applications are pre-installed. The abstract machine with the installed application can then be deployed identically many times. Applications deployed in containers and applications on virtual machines can be spun up with identical configurations and operating environments, but the two operate on different layers. Awareness of this distinction is important when deciding whether a container or a virtual machine will be more appropriate for a cloud deployment.

There are advantages to containers over virtual machines. Containers are lighter weight than virtual machines. A container usually has a much smaller disk footprint than a virtual machine because it uses more functionality from the underlying operating system. Using containers, fewer of the computing cycles of the underlying hardware are consigned to overhead, so more containers can be run on the same processor. This is because some operating system functionality is shared between containers running on the same node. In addition, lightweight containers usually start up faster than virtual machines.

On the downside, a holder of root privilege on the underlying operating system has access to the contents of the container, unlike a virtual machine, which can be made inaccessible without credentials for the specific virtual machine. This can be an issue in high-security and mission-critical scenarios. In addition, tooling and management facilities for hypervisor-based systems are more available, and expertise in developing and managing is well-established, although this situation is rapidly changing with increased interest in containers.

Containers are not an all-or-nothing choice. A container can be launched on a virtual machine. The combination of containers and virtual machines on hybrid Linux and Windows platforms may prove to be the most viable architecture in the future.8

Plan for New Interfaces

The appearance of handheld devices, smartphones, and tablets has transformed enterprise computing in many ways, and the change promises to continue. Wearable computers (such as wrist monitors and other wearable devices) and the Internet of Things are adding new devices such as security and utility controllers to enterprise networks, and they all promise to place new demands on enterprise IT services.

These are new interfaces to computing systems. Mobile computing has changed the enterprise perimeter, and you can expect new devices to change perimeters unpredictably. Already, mechanical control systems attached to the enterprise network have become a vector for malicious exploits. Mobile apps have driven new ways in which employees and customers communicate with enterprise systems. Cloud-deployed applications are often the back end to these interfaces. Back ends tend to remain stable longer than front-end interfaces. Cloud architects and designers should plan for front-end change. That means carefully thinking through the separation between the functionality of the service and the presentation of the service. Because I do not know what these transformations will require, specific recommendations are difficult. However, the principle of separation of presentation and functionality (which made it possible for a back end to weather the change from thick to thin clients and from thin web clients to mobile apps) has a good chance to aid in the transformations to come.

Store Freely

Storage used to be expensive. Now it’s relatively cheap. In several decades of building and designing enterprise applications, one observation has been consistently true: every decision made to reduce the volume of data stored or to store data more compactly at the expense of losing information or decreasing the ease and speed of access eventually turns into a blunder. That observation is not a license to waste capacity by storing identical data repeatedly or bloating files with gigabytes of nulls from memory dumps. However, cloud storage is much cheaper now than storage has ever has been. In addition, the techniques for manipulating and analyzing large quantities of data have evolved to the point that masses of data have become assets instead of burdens. The value of data has increased in direct proportion to the capacity to store it and analyze it efficiently. Masses of data that would have been on a list for purging a decade ago have become enterprise treasures.

Therefore, architects should not skimp on storing additional data in the form of more detailed logs, storing records that might have been treated as temporary before, and storing data incidental to transactions. Predicting what will become important as the analysis proceeds is difficult, but decreasing costs have made it more practical to err on the side of storing more, not less.

The cloud is the perfect place to take advantage of masses of data because big data analysis requires monumental computing capacity, but only for a relatively short time, and it works best with expanding numbers of parallel processes, which are exactly suited to a cloud architecture. This is another argument for storing data freely.

Conclusion

Building efficient cloud applications that will contribute enduring value to the enterprise is not easy. Cloud implementations can be more efficient and perform better than on-premises applications, but only if good practices are followed. Some of these practices, such as horizontal scalability, SOA, microservices, and ROA may be unfamiliar, but they are easier to implement in a cloud environment where they are the expected architecture.

Most important, by following healthy cloud-oriented architectural practices, applications that deliver on the promises of cloud are possible.

EXERcISES

  1. Name three basic cloud application requirements.
  2. What is a monolithic application? Explain why it may not be suitable for cloud deployment.
  3. Differentiate between SOAP and REST. Which is more suitable for cloud deployments?
  4. What are containers?

_______________

1Porting software means to modify a piece of software to execute in a different environment. Ported software’s operation is expected to be identical to its operation in the old environment. Usually, porting changes as little of the original code as possible.

2The terms CPU, processor, and core are similar and often used interchangeably, and meanings have shifted with the progress of hardware. However, they are not strictly the same. Central processing unit (CPU) traditionally has referred to a collection of chips and other components that process instructions and data. These consist of arithmetic and logic evaluation, instruction fetching, interrupt handling, and input and output. All these components eventually shrank to a single chip called a CPU or a processor. As chips became denser, more and more functionality crowded onto single chips. Eventually, additional arithmetic and logic evaluation units, cores, appeared on single CPU chips. These cores are not full CPUs because they share functionality with other cores on the same chip, but they have many of the capabilities of a complete CPU. Servers often have several processor chips each with multiple cores. Mobile devices are usually limited to a single processor chip that may have many cores. Sometimes the word processor refers to the entire processing capability of a virtual or physical computer, which may include several processing chips with multiple cores. You should be aware that the terms are used loosely.

3An HTTP server is a more precise name for a server that receives and replies to HTTP. A web server could, conceivably, be based on a non-HTTP protocol, but that happens rarely, if ever.

4SOAP used to be an acronym for Simple Object Access Protocol, but the SOAP authors came to realize that the protocol is for service messaging that often does not involve objects. Also, although the committee did not mention it, most developers say SOAP is far from simple. To avoid misconceptions, the committee declared that SOAP is just a name, not an acronym. For more details, see http://lists.w3.org/Archives/Public/xmlp-comments/2005Sep/0002.html. Accessed June 2015.

5The Internet of Things (IoT) refers to the appearance of things, such as heating and ventilation controls or security cameras, on the network. Many people project rapid growth in the IoT in the next few years and the integration of the IoT with traditional applications.

6An HTTP server is also a web server. Here, when HTTP is important in the discussion, I use the term HTTP server. When HTTP fades into the background, I use the more common term, web server. An Internet web server that does not use HTTP is possible, but it would not work with most of the World Wide Web.

7For a full discussion of CAP, see Marvin Waschke, Cloud Standards. Apress, 2012, pp. 124–131.

8Docker is the most mentioned container project today. It is an open source Linux-based project that is supported by a company named Docker. See https://www.docker.com/, accessed July 2015. A widely supported group has formed to write an operating system and platform–independent standard for containers. See www.infoworld.com/article/2938638/application-virtualization/docker-donates-its-container-specs-for-opc-open-standard.html, accessed July 2015.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset