Hero image

Software Development

How to implement CDN in a legacy system and why it’s worth the effort

Home

>

Blog

>

Software Development

>

How to implement CDN in a legacy system and why it’s worth the effort

Published: 2021/05/13

6 min read

Nowadays Content Delivery Network is almost a standard used by not only the biggest like Facebook, Netflix, or Amazon but also much smaller companies that provide their web products/services for geographically distributes users to shorten the loading times and optimize the costs related to servers maintenance. What’s more, while most newly developed systems plan to implement this solution right at the start, having a legacy app that still relies on private servers is not a road blocker that can’t be overcome. In this blog, we are going to share what CDN is, why it’s worth utilizing it, and most importantly – how it can be implemented in the legacy system to improve its operations speed and cut costs of maintenance, which we’re going to illustrate using example of one of our past cooperation.

CDN Basics

Let’s start by clarifying what CDN (Content Delivery Network) is. It is a resources delivery solution based on geographically distributed data suppliers. It provides additional servers dedicated to host static content (resources) which can be accessed by end-user. Such approach gives us possibility to host static files in few locations connected in a network and as result provide content from the one closest to customer which speeds up whole process and decrease respond time.

Having the CDN process explained, we can compare it to standard content supplier approach. Nowadays majority of applications have frontend and backend services separated. It means that the part responsible for business logic and data storage (backend) is separated from view layer (frontend). Frontend is responsible for collecting data from backend and preparing it to be displayed. In order to do this it requires static resources such as css, scripts, images etc. In standard approach those files are kept on one server with frontend application logic. In order to return view to customer our application needs to follow those steps:

  1. Collect the data (call another service)
  2. Collect resources (prepare all resources from local storage)
  3. Show data in the right view (Render the view)

After implementation of CDN approach whole process will change and look like this:

  1. Collect the data (call another service – backend)
  2. Collect resources (call another service – content delivery network)
  3. Show data in the right view (Render the view)

 

What are pros of such solution

First of all it makes our application more lightweight. Frontend part is no longer responsible for hosting anything, it is only pointing browser for content source. This gives us distribution of responsibility. What’s more resources can be heavy to load so moving it to content delivery network which will return them from server closest to end user can highly shorten the time needed to load all the resources.

 

Without CDN:

How the network works without CDN

 

 

With CDN:

How the network works with CDN

 

CDN providers

Since we got the basics covered, now comes the time to consider how to use it in our project. First of all we need to decide which provider suits us best. There are many companies offering CDN services which gives us possibility to select one with the best offer for a particular scenario. Most of them allow free limited usage to check how it works and test if their offer matches ones need. Yet in general, all of them work on same basis and differences are in details and pricing (usually calculated by monthly traffic).

Top 3 CDN providers (based on current market share) are:

Cloudflare CDN

CloudFront(AWS)

Akamai

How to use CDN in existing project?

As we announced in the beginning, now comes time for the practical part, illustrating how CDN can be implemented in a legacy system. Yet before we move to the code itself, let’s look at it from the wider perspective to see why it’s worth making such changes business-wise.

Firstly, this distributed app is being used all over the world, so the enormous distance between server and end-user slowed down its performance. Secondly, the cost of in-house servers maintenance was not only big but also growing since all the hardware had to be regularly updated due to growing business-related requirements. Last but not least, the app performance could be improved by setting more and more local servers closer to the users, yet our Client was aware that it would be financially ineffective. Therefore, they decide to deal with all these issues at once, by implementing CDN.

Our job was to implement CDN into a legacy Spring based web app with JSF view engine. We needed to support two ways of serving resources: CDN (for prod environments) and local (for development purposes)

We wanted it to be easily configurable. To achieve that, we introduced spring profile which is responsible for controlling resource serving strategy (either local or CDN). We also replaced all of the src/href attribute values with call to new path resolver component which provides appropriate path based on configuration. We also needed to externalise all of the JSF related resources. It occurred not to be as straightforward task as we thought, since some of the JSF’s statics were used by its internal templating engine. Therefore, we couldn’t fully externalise all the files. However, rest of the resources were mapped with new localisation in JSF properties files.

Another important topic we had to cover was the security. When we download resources from outside world (CDN) we need to be sure they are exactly the same as we put them there. In order to ensure this, we added integrity attribute to all imports in html files. Thanks to this we can rest assured that content delivered by CDN is exactly the same as expected by application. You can read more about how integrity works and how to implement it here.

Last thing to update was our build strategy, first of all it creates manifest file with all integrity parameters for all resources as single source of truth for them. Manifest file is being created during application build in compile phase. That was prepared as a maven plugin. Next, we had to pack all resources and upload them to cloud environment from where these were distributed to CDN provider. This was implemented by lambda which is unzipping resources and stores them in the right storage, allowing to be downloaded by clients browsers.

Manifest file example structure:

example_1.ico_hash=806c0f02d0402bffb989e5160619dabd652505f89923b4e88fdee023dd9b0324

example_1.ico_integrity=sha256-gGwPAtBAK/+5ieUWBhnavWUlBfiZI7Toj97gI92bAyQ=

example_2.css_hash=249c41abaf5404d6922e9fec38b678fe6bb85e2a2c6cc34c485ad0ecba2ecb81

example_2.css_integrity=sha256-JJxBq69UBNaSLp/sOLZ4/mu4XiosbMNMSFrQ7Louy4E=

ResourceLocationSupplier is a class responsible for providing calculated directory to html link attribute. It contains three methods for three import types:

GetScriptURL – provides scripts directory

getStylesheetURL – responsible for stylesheet directory

GetImageURL – returns image directory

All these methods expect relative path as an argument. It is used to calculate final file path by adding relative path to global one which depends on current profile. If CDN profile is enabled, returned value will be pointing to external resource provider:
{external provider utl} + {/resources/images} + {filename(relativePath variable)}

if no it will return local path:
{local storeage} + {/resources/images} + {filename(relativePath variable)}

IntegrityAttributeResolver has one method: getIntegrityAttibuteForFile(String filename).

It returns proper integrity value from manifest file. It is used by browser to verify integrity with the downloaded file. Thanks to this we can be sure files are exactly as expected.

The last step was adding junit tests which list all html files and are parsing them to check if in all places like scripts, links etc. new methods (resourceLocationSupplier and integrityAttributeResolver) were used instead of a local path what can be made by developer. Doing this we wanted to create a protection before any issues with serving resources on the higher environments.

How did it end? CDN implementation allowed us to place servers containing resources close to end-users and as result improve application performance, its responsiveness and reduce network traffic on the business side of application by diminishing system load – which was exactly what our client wanted. What’s more, due to the approach we chose, the implementation was completely transparent for both our client, their internal developers and did not interfere in any way with the application development that had been happening simultaneously.

 

If now you wonder how CDN implementation can improve your application performance and what’s the approach to make it happen don’t hesitate to use the contact form below. We are eager to share our experience and since there are no two identical projects and situations, talking through the particular scenario is best what can be done to do it right.

About the authorMateusz Mnich

Senior Software Engineer

Senior Software Engineer with more than 8 years of experience focused mainly on Java. Mateusz believes that to become the best, skills must be combined with passion, and this passion for his job is what drives him to never settle in expanding his knowledge and allows him to face and overcome the toughest challenges.

Subscribe to our newsletter

Sign up for our newsletter

Most popular posts