Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Info

The first thing we are going to do is run and examine a simple application. You are not expected to write any code, but we will be looking at Dockerfiles and Docker-Compose files.

The purpose of the exercise is to help you understand the structure of the application, capture it using C4, and ask architecturally significant questions.

01 The Monolith Application

Docker is an ideal tool for understanding the nature of monolithic applications without the need to have numerous physical nodes (a node is a piece of hardware)

...

  • Containers can be considered lightweight VMs

  • They are self-contained

  • Hermetically sealed

  • They expose their services through ports

  • They can share a common network and volume

...

02 Running the Monolith

  1. Using the Gitbash terminal, navigate to /c/work

  2. Clone down the following projects

    1. https://bitbucket.org/stream2stream/react_app-vat_calculator/src/main/

    2. https://bitbucket.org/stream2stream/vat_calculator_service/src/main/

  3. Start Docker

  4. Open Windows' terminal in Admin mode (right-click on Windows Start, and select Terminal (Admin)

  5. Navigate to c:\work\vat_calculator_service

  6. Enter the command mvn package, this will build the binary for the calculator service. A number of files will have been created in the target folder. You will need the file called vat_calculator_service-0.0.1-SNAPSHOT-spring-boot.jar

  7. Navigate to c:\work\react_app-vat_calculator

  8. Create a folder called target

  9. Copy the file vat_calculator_service-0.0.1-SNAPSHOT-spring-boot.jar into the target folder

  10. Run the command docker build --tag=vat_calculator_service:latest .

    1. the full stop is important

  11. Run the command docker run -p 3000:3000 -p 8080:8080 --name vatc_fe --rm vat_calculator_service this will create a single docker container containing the 3 applications that are all wired together

03 Understanding the Monolith

Run the following commands

...

Tip

Model what you have learnt using C4.

So what are the things that you notice and architecturally what are the PROs and CONs?

04 Monolith Breakdown

...

05 Monolith to Docker

...

06 PROs and CONs of the Monolith

07 Breaking up the Monolith

We are now going to run each component of the system as separate services

...

Tip

Model what you have learnt using C4.

08 Cloud Computing Architecture

Info

Cloud computing allows us to

  • transfer our physical technical stacks onto someone else's physical stack

  • represent hardware as code (as you’ve seen with Docker containers)

  • manage our tech stacks in a more technically and finally productive way

All the major cloud providers; Amazon Web Services, Google Cloud Platform, Microsoft Azure, Alibaba Cloud, IBM Cloud, DigitalOcean Cloud, Salesforce Cloud, Tencent Cloud, Oracle Cloud Infrastructure, Huawei Cloud (https://www.cloudzero.com/blog/cloud-service-providers/ ), provide the three core elements of cloud services

  • IaaS (Infrastructure as a Service)

  • PaaS (Platform as a Service)

  • SaaS (Software as a Service)

Giving you

  • Low capital outlay

  • Faster time to market

  • Agility

  • Optimal cloud delivery models

  • Pay-as-you-go pricing

  • Managed services

  • More opportunities to build better disaster recovery into your organisation’s day-to-day operations

  • More opportunities to build better business continuity into your organisation’s day-to-day operations

09 AWS Example with Docker Containers

...

We could use a computer engine, but this would require us to select the OS (infrastructure platform) and then install all the necessary applications and libraries to run our container on that compute engine

...

We’ve also highlighted Red Hat OpenShift as an alternative approach. OpenShift® gives a one-stop shop to access the services of any number of cloud providers, it’s a unified platform to build, modernize, and deploy applications at scale

...

10 Quality of Service Attributes Gained

Info

There are clearly some gains to be had by splitting our applications into these micro-services

  1. More scaleable

  2. Less brittle

  3. More maintainable

  4. Easier to secure

  5. More performant

  6. If managed well more cost-efficient

  7. More fault-tolerant

  8. Higher availability

  9. More extensible

10-01 Scaleability

When you ran the monolith VAT application one of the main issues was its inability to scale. Whether we wanted to scale it horizontally or vertically was an issue

...

Tip

Here we we demonstrate horizontal scaling

Vertical Scaling

Modify the Node by adding more RAM, Upgrading the CPU, and adding more Disk space. All of these options require the system to be shut down, the hardware to be installed and the system to be rebooted. After this, you could have too much capacity or too little capacity.

Horizontal Scaling

Replicate a service, and distribute the workload amongst the distributed services You would make use of something like a load balancer to ensure that traffic is evenly sent to all replicated nodes/services (the cluster).

10-01 Demo Time

The trainer will demonstrate a Docker Image being deployed onto an AWS container service. They will also show horizontal scaling at work.

10-02 Less Brittle Architecture

Info

We are going to steal a concept from the world of software engineering - “Brittle Code”

The concept is very simple, how much collateral damage is there to a codebase being changed?

The scope of that damage is relative. However, the scale of the effect of change should have been considered during the design and development of the codebase that’s being changed. Unfortunately, many of these design decisions are not captured in the completed codebase, leading to another issue; technical debt. In a sense, what we are describing here is risk and levels of risk.

An example of this would be the very small change to the name of a field in a class. The surrounding codebase should have no knowledge of this change because access to this field should only be through setters and getters (encapsulation). Suppose a change to this field causes other classes to have to be modified. In that case, this is clearly brittle code (we’re not including the idea of refactoring to clean up the codebase, making names more readable and appropriate to their purpose).

We can use the same idea in architecture. Does the change in one component or service require the complete rebuild of the entire system? We saw that with the monolith application.

10-03 Maintainability

How much effort is required to maintain the system, modify it, and integrate it with other systems?

...

If you have to butcher the code to make it realize new scenarios whilst continuing to be what it was intended for, then it’s not maintainable

10-04 Security

A system is the sum of its parts. If each service can have its level of security (different set of security constraints), it becomes easier to secure the whole. But if the whole is a monolith, inevitably it becomes more difficult to apply security constraints around the parts.

10-05 Performance

You tune the whole by tuning the parts. That’s a basic engineering principle.

Formula 1 teams spend vast amounts of money capturing data from all the components of the car, as well as the performance of the driver. The car and driver only hit optimal performance when everything is functioning in harmony.

10-06 Cost Efficiency

The problem with the monolithic approach is that you have to tune the whole even though your intention may be to only effect a part. It then becomes very difficult to target the tuning for a single part without affecting the whole. So you end up spending money where it’s not needed. The tuning and cost management becomes much easier by componentising the system and using a micro-service architecture.

10-07 More fault-tolerant

The requirement is to make the whole fault-tolerant, but each component has different requirements for achieving fault tolerance. By tackling each part, you are tackling the whole.

10-08 Higher availability

The requirement to make the entire system highly available can only be achieved by tuning thr parts and making them highly available. If you’re dealing with a monolith, then if one part fails, then the whole fails. But if we compartmentalise the system, and reduce the coupling, then if one part fails, strategies can be put in place to ensure that the whole is not compromised.

10-09 More extensible

A system is only extensible if it is designed to be extensible. If you have a monolithic piece of code, then by it’s very nature it is not extensible. Likewise if you have a system that is comprised of many parts but the coupling between those parts is tight, then a change in one component will impact on other components. Testing one component would require testing of adjacent components etc. This is a bad design.