Laravel: session persistence, caching, file upload management and logging on a load balancer
Feb 8th 21
Along with the ability for your applications to scale infinitely(literally) comes the hassle of handling some vital features that makes web applications stable and functional.
In this post, I will be highlighting some experiences I encountered while deploying a Laravel ^7.0 web applications in AWS using AWS provided platform as a service tool Elastic Beanstalk, while this will not be a handles on step by step tutorial on how to implement my solution to the situation highlighted below, being aware of the existence of the points listed later on will assist in implementing a solution for any application on any programming language or framework using language-specific features, with being said let's dive in.
In other to scale a web application to handle a growing number of visitors cost-effectively, modern computing best practices require adding more servers that can handle concurrent requests and serve users with the correct information at the right time.
For these multiple servers to effectively handle client requests, a load balancer sits between client requests and the servers as a proxy routing request across all servers capable of fulfilling those requests in a manner that maximizes speed and capacity utilization and ensures that no one server is overworked, which could degrade performance.
A load balancer efficiently ensures that:
- Client requests or network load are distributed across all servers.
- Requests are only sent to online servers
- Addition or subtraction servers are flexible.
The load balancer is an efficient software technology and an absolute necessity if at all a web application can cost-effectively deliver content, but with this amazing gain comes extra efforts and in some cases a frustrating late hour session.
Ignoring several blockers, I encountered deploying my Laravel ^7.0 application in AWS Elastic Beanstalk that is not related to load balancing;
- Session Persistence
- File upload
are to be taken into consideration when scaling application using load balancing.
Session persistence refers to directing a client’s requests to the same backend web or application server for the duration of a “session” or the time it takes to complete a task or transaction.
A session is defined as a series of related browser requests that come from the same client during a certain period. Session tracking ties together a series of browser requests—think of these requests as pages—that may have some meaning as a whole, such as a shopping cart application. sessions provide a way to store information about the user across multiple requests.
When a web application uses a load balancer to scale, multiple servers are running simultaneously and it’s not guaranteed that the server that handled the first request will handle the second request from the same client which leads to inconsistencies and weird behaviors e.g. 403 ERRTOOMANY_REDIRECTS, Internal Server errors for routes that require certain session property to exist, user logged out wrongfully.
Laravel provides several options for handling sessions but defaults to use the file session driver which works well for most applications. But for a web application on a load balancer is not an option.
Database drivers are a good option to persist session on a load balancer, though slower compared to Redis or Memcached.
Caching helps relieve web application servers of CPU intense processes by storing heavy data closer to the client computer.
When a cache client needs to access data, it first checks the cache. When the requested data is found in a cache, it's called a cache hit. The percent of attempts that result in cache hits is known as the cache hit rate or ratio.
Laravel recommends the use of decoupled caching systems like Redis or Memcached or maybe a database driver, using a decoupled caching system improves the cache hit rates which improves your application speed and user experience.
By default, Laravel file uploads are the store and managed within the public folder of the web application of a particular server, except that a load balancer spins up several servers with a replica of your web application file system, which means the files uploaded in one server is not available to other servers within your infrastructure.
Another issue with using a local filesystem driver is the loss of uploaded files when a server is destroyed or fails data that is stored on the server that is not distributed on other servers to be lost.
Laravel also supports an s3 filesystem driver which ensures the all-file upload within your application is store in a centralized storage bucket in AWS, Laravel makes migrating from a local driver to an s3 driver easy, switching from a local driver to an s3 driver is probably the easiest of fixes you can make among the above-mentioned points above depending on the way your application code is written.
Many cloud infrastructure companies provide technologies for monitoring and tracking your load balancer health, a large web application which is distributed across multiple servers can utilize these technologies to assemble internal application logs, failed request, warnings and crashes, these help in debugging and helps DevOps to better manage and maintain the web application.
Directing all application logs to a central infrastructure ensures that all bugs, causes, and all needed pieces of information to fix a bug is in a central location which is useful for developers and DevOps engineers managing the application.
Luckily, Laravel provides tons of logging channel which makes centralizing logs relatively an easy tasks to handle, Laravel provides several logging channels which assist in ensuring logs from server end in a single file and offers a lot of flexibility on how to go about it, there is no best solution. I chose to go with a database log solution that stores all application logs in a database that is decoupled from my web application environment.
Managing a web application on a load balancer is not the easiest of tasks, especially for first-timers, but can be an interesting task in a long run,
Session persistence, caching, file upload, and logging will not be the only tweak to be made to your application if it was built without a load balancer in mind or decision to be made when kick starting any web application that will run on a load balancer.
As time passes load may be able to handle some of the points automatically, already AWS Classic Load Balancer supports sticky sessions which is close to a solving session persistence automatically.
Hope this helps you build a better and scalable web application.