Caching

Many times consumers request the same things, and the application returns the same information. In this scenario, caching is the solution to avoid constantly processing the same request and returning the required data faster.

Caching is used for data that does not change frequently in order to have a precalculated response without processing the request. The workflow is as follows:

  1. The first time that the consumer requests some information, the application processes the request and gets the required data.
  2. It saves the required data for that request in the cache with an expiration time that we define.
  3. It returns the data to the consumer.

Next time that a consumer requests something you need to do the following:

  1. Check whether the request is in the application cache and it has not expired.
  2. Return the data located in the cache.

So, in our example, we will use caching in the location microservice in order to avoid requesting the closest secrets multiple times.

The first thing that we need to use a cache layer for in our application is a container with Redis (you can find other cache software out there, but we decided to use Redis as it is very easy to install and use). Open the docker-compose.yml file and add the new container definition, as follows:

    microservice_location_redis:
        build: ./microservices/location/redis/
        links:
            - autodiscovery
        expose:
            - 6379
        ports:
            - 6380:6379

Once we add the container, you need to update the links section for the microservice_location_fpm definition to connect to our new Redis container as follows:

    links:
        - autodiscovery
        - microservice_location_redis

In this case, our docker/microservices/location/redis/Dockerfile file will only contain the following (feel free to add more things to the container if you want):

    FROM redis:latest

Do not forget to execute docker-compose stop to successfully kill all the containers and start them again with our changes with a docker-compose up -d. You can check whether the new container is running by executing docker ps in your terminal.

Now is time to make some changes in the source of our location microservice to use our new cache layer. The first change we need to make is on the composer.json; add the following required libraries to the "require" section:

    "predis/predis": "~1.0",
    "illuminate/redis": "5.2.*"

Once you make the changes to the composer.json file, remember to do a composer update to get the libraries.

Now, open the location microservice .env file to add the Redis setup, as follows:

    CACHE_DRIVER=redis
    CACHE_REDIS_CONNECTION=default
    REDIS_HOST=microservice_location_redis
    REDIS_PORT=6379
    REDIS_DATABASE=0

Since our environment variables are now set up, we need to create the config/database.php with the following content:

    <?php
    return [
        'redis' => [
            'client'  => 'predis',
            'cluster' => false,
            'default' => [
                'host'     => env('REDIS_HOST', 'localhost'),
                'password' => env('REDIS_PASSWORD', null),
                'port'     => env('REDIS_PORT', 6379),
                'database' => env('REDIS_DATABASE', 0),
            ],
        ]
    ];

In the preceding code, we defined how to connect to our Redis container.

Lumen comes without the cache configuration, so you can copy the vendor/laravel/lumen-framework/config/cache.php file into config/cache.php.

We will need to make some small adjustments to our bootstrap/app.php--uncomment $app->withFacades(); and add the following lines:

    $app->configure('database');
    $app->configure('cache');
    $app->register(
        IlluminateRedisRedisServiceProvider::class
    );

We will change our getClosestSecrets() method to use cache instead of calculating the closest secrets every time. Open the app/Http/Controllers/LocationController.php file and add the required use for cache:

    use IlluminateSupportFacadesCache;

        /* ... Omitted code ... */
    const DEFAULT_CACHE_TIME = 1;
    
    public function getClosestSecrets($originPoint)
    {
        $cacheKey = 'L' . $originPoint['latitude'] .                   
        $originPoint['longitude'];
        $closestSecrets = Cache::remember(
            $cacheKey,
            self::DEFAULT_CACHE_TIME,
            function () use($originPoint) {
                $calculatedClosestSecrets = [];
                $distances = array_map(
                    function($item) use($originPoint) {
                        return $this->getDistance(
                            $item['location'], 
                            $originPoint
                        );
                    }, 
                    self::$cacheSecrets
                );
                asort($distances);
                $distances = array_slice(
                    $distances, 
                    0,
                    self::MAX_CLOSEST_SECRETS, 
                    true
                );
                foreach ($distances as $key => $distance) {
                    $calculatedClosestSecrets[] = 
                    self::$cacheSecrets[$key];
                }

                return $calculatedClosestSecrets;
         });
        return $closestSecrets;
    }
    /* ... Omitted code ... */

In the preceding code, we changed the implementation of the method by adding the layer cache; so instead of always calculating the closest points, we first check on our cache with remember(). If nothing is returned from the cache, we make the calculation and store the result.

Another option for saving data in Lumen cache is to use Cache::put('key', 'value', $expirationTime); where the $expirationTime can be the time in minutes (integer) or a date object.

Tip

The key is defined by you, so a good practice is generating a key that you can remember in order to regenerate in the future. In our example, we defined the key using L (for location) and then the latitude and longitude. However, if you are going to save an ID, it should be included as part of the key.

Working with our cache layer is easy in Lumen.

To obtain elements from the cache, you can use "get". It allows two parameters--the first one is to specify the key you want (and is required), and the second one is the value to use if the key is not stored in cache (and obviously is optional):

    $value = Cache::get('key', 'default');

A similar method to store data available is Cache::forever($cacheKey, $cacheValue); this call will store the $cacheValue identified by $cacheKey in our cache layer, forever, until you delete or update it.

If you don't specify the expiration time for your stored elements, it is important to know how to remove them. In Lumen, you can do it with Cache::forget($cacheKey); if you know the $cacheKey assigned to an element. In the case of needing to remove all the elements stored in the cache, we can do this with a simple Cache::flush();.

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

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