Skip to content

Case 3.3

Xapp73 edited this page Jul 24, 2020 · 11 revisions

Case 3.3 Pick the best performance provider for visitor's country

The Case. In fact, this is one of the most popular cases: select the CDN with the best performance for user's country. It is very useful and not complicated at all.

First goes our configuration:

const configuration = {
    /** List of  providers configuration*/
    providers: [
        {
            name: ('akamai' as TCDNProvider), // CDN Provider alias to work with
            cname: 'my-akamai.origin.cdn.com' // cname to pick as a result
        },
        {
            name: ('cloudflare' as TCDNProvider),
            cname: 'my-cloudflare.origin.cdn.com' // cname to pick as a result
        },
        {
            name: ('aws-cloudfront' as TCDNProvider),
            cname: 'my-cloudfront.origin.cdn.com' // cname to pick as a result
        },
        {
            name: ('verizon-edgecast-cdn' as TCDNProvider),
            cname: 'my-edgecast.origin.cdn.com' // cname to pick as a result
        },
        {
            name: ('g-core-labs' as TCDNProvider),
            cname: 'my-gcore.origin.cdn.com' // cname to pick as a result
        }
    ],
    defaultTtl: 10 // The DNS TTL to be applied to DNS responses in seconds.
};

We simply list our providers candidates, their TCDNProvider-type names and the desired answers.

Then, we define our functions, we need those to determine the lowest array index and the lowest property (it will be performance, remember, The lower value - the better performance.)

/**
 * Returns index of lowest number in array
 */
const getLowest = (array: number[]): number => array.indexOf(Math.min(...array));
/**
 * Picks item with lowest value in property
 */
const getLowestByProperty = <T>(array: T[], property):T => array[getLowest(array.map(item => item[property]))];

Now, the main part, our onRequest block. Let's parse the configuration, try to figure out user country with PerfOps lookupCountry function, and if it is set - get ISO code of that country. Notice, that in some cases country can not be determined, so let's also declare new country variable that will either contain ISO code or be null.

function onRequest(req: IRequest, res: IResponse) {
    const { providers, defaultTtl } = configuration;
    let countryInfo = lookupCountry(req.ip);
    let country: TCountry | null =  null;
    if (countryInfo) {
        country = countryInfo.isoCode;
    }

Now, let's get the array of objects with our providers and their performance. If country is not null - we will get CDN RUM performance per provider for that country, otherwise we use the world RUM performance. In both cases we use fetchCdnRumPerformance function that can take either one argument for the world performance, or three arguments for a particular location performance.

    // get Providers performances
    const perfProvidersData = providers.map(
        (provider) => ({
            provider,
            perf: country && 
            fetchCdnRumPerformance(provider.name, 'country', country) || 
            fetchCdnRumPerformance(provider.name)
        })
    );

And the last touch: we get the cname for the best-performance-provider and set it as our answer. That's it!

    const {provider} = getLowestByProperty(perfProvidersData, 'perf');
    res.setCNAMERecord(provider.cname);
    res.setTTL(defaultTtl);
    return;

The whole script looks like:

const configuration = {
    /** List of  providers configuration*/
    providers: [
        {
            name: ('akamai' as TCDNProvider), // CDN Provider alias to work with
            cname: 'my-akamai.origin.cdn.com' // cname to pick as a result
        },
        {
            name: ('cloudflare' as TCDNProvider),
            cname: 'my-cloudflare.origin.cdn.com' // cname to pick as a result
        },
        {
            name: ('aws-cloudfront' as TCDNProvider),
            cname: 'my-cloudfront.origin.cdn.com' // cname to pick as a result
        },
        {
            name: ('verizon-edgecast-cdn' as TCDNProvider),
            cname: 'my-edgecast.origin.cdn.com' // cname to pick as a result
        },
        {
            name: ('g-core-labs' as TCDNProvider),
            cname: 'my-gcore.origin.cdn.com' // cname to pick as a result
        }
    ],
    defaultTtl: 10 // The DNS TTL to be applied to DNS responses in seconds.
};
/**
 * Returns index of lowest number in array
 */
const getLowest = (array: number[]): number => array.indexOf(Math.min(...array));
/**
 * Picks item with lowest value in property
 */
const getLowestByProperty = <T>(array: T[], property):T => array[getLowest(array.map(item => item[property]))];

function onRequest(req: IRequest, res: IResponse) {
    const { providers, defaultTtl } = configuration;
    let countryInfo = lookupCountry(req.ip);
    let country: TCountry | null =  null;
    if (countryInfo) {
        country = countryInfo.isoCode;
    }
    // get Providers performances
    const perfProvidersData = providers.map(
        (provider) => ({
            provider,
            perf: country && 
            fetchCdnRumPerformance(provider.name, 'country', country) || 
            fetchCdnRumPerformance(provider.name)
        })
    );
    const {provider} = getLowestByProperty(perfProvidersData, 'perf');
    res.setCNAMERecord(provider.cname);
    res.setTTL(defaultTtl);
    return;
}
Clone this wiki locally