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:
Next time that a consumer requests something you need to do the following:
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.
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();
.
18.227.111.33