The essential news about content management systems and mobile technology. Powered by Perfect Publisher and XT Search for Algolia.
The News Site publishes posts to the following channels: Facebook, Instagram, Twitter, Telegram, Web Push, Tumblr, and Blogger.
Kubernetes is an excellent option for scaling Laravel applications. Kubernetes offers scalability, high availability, service discovery, and load balancing. Specifically for Laravel deployments, Kubernetes can help with stateless horizontal scaling, easy management of background processing, and storage flexibility.
But it can come at a cost. The ephemerality of Kubernetes pods and the way they scale makes session management in Laravel difficult. Using the default file session driver can lead to lost data if the pod restarts or is replaced, so developers must shift to a different mechanism.
Here, we want to take you through some of the gotchas in Laravel session management you’ll experience as you move to a Kubernetes deployment. The good news is that they are all fixable with an understanding of the internal workings of containerization.
This article is sponsored by Scout APM.
Let’s start with why you might want to do this. You can deploy Laravel applications in myriad different ways, so why choose one that will immediately give you this session headache? Well, the core benefits of deploying a Laravel application on Kubernetes are:
However, while Kubernetes offers these benefits, it also introduces complexity, with session management being a casualty of this complexity. One of the benefits above is a primary culprit in causing session management problems–stateless horizontal scaling. This causes session management problems by introducing multiple replicas of your Laravel application, which may not inherently share session state.
In traditional single-server setups, a user's session data is typically stored locally, making it instantly available for subsequent requests from that user. In Kubernetes, with multiple replicas handling requests, a user may be served by a different replica with each request.
So, the challenge of session management comes from three factors integral to how Kubernetes works.
First, there is a need for session persistence. When sessions are stored locally within a pod, a request that goes to a different replica will not have access to previous session data, leading to a broken user experience. This inconsistency can lead to issues like users being logged out randomly or needing help retaining application state.
Second is the ephemeral nature of pods. Pods in Kubernetes can be terminated and replaced at any time, especially if they become unhealthy or during updates. If a session is stored locally within a pod, and that pod gets terminated, the session data is lost, affecting user experience.
Third, while Kubernetes does provide load balancing across pods, without session affinity configuration, subsequent requests from the same user can land on different replicas. Without a centralized session store, this can lead to unpredictable behavior.
These all lead to data synchronization overhead and increased latency, as attempting to manage sessions through synchronization or other non-central methods can introduce latency into requests. This detracts from the user experience, especially in applications where response time is critical.
To counter these challenges, Laravel developers deploying Kubernetes have two options:
Let’s go through each option and how they work with Laravel.
Session affinity, also known as "sticky sessions," can be critical in scenarios where stateful applications or workloads are deployed, and you want all requests from a particular client to always go to the same pod. In Kubernetes, you can achieve this using service session affinity.
In traditional monolithic architectures, applications typically run on a single server where session data is stored locally. This model ensures that all subsequent requests from a particular user always have access to that user's session data. But, in a container orchestration environment like Kubernetes, your application could be running across multiple pods spread across different nodes. Here, there's no inherent guarantee that a user's subsequent requests will hit the same pod every time.
This is where sticky sessions come into play. For specific applications, a user's requests must always land on the same pod to maintain application state, provide a consistent user experience, or leverage local caching effectively.
Kubernetes provides the concept of session affinity, enabling you to specify that all requests from a particular client should be routed to the same pod. This is achieved through the use of cookies or by IP.
When you configure session affinity based on the client's IP address, Kubernetes checks the source IP of the incoming request and directs it to the same pod as previous requests from that IP. If session affinity is based on cookies, Kubernetes will ensure that all requests with a specific cookie are directed to the same pod.
In your service's YAML definition, you must specify the session affinity type. For instance:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 9376
sessionAffinity: ClientIP
In the above configuration, the sessionAffinity
field is set to ClientIP, which means the Kubernetes service will
use the client's IP address to ensure that all requests from that
IP will be directed to the same pod.
If you want more control over the session affinity, you can use
sessionAffinityConfig
. For example, to set a timeout
for the session affinity:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 9376
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 3600
While sticky sessions can solve some problems, they are only sometimes the right fit. If the pod handling the sticky session overwhelms or goes down, the user might experience performance issues or disruptions.
Relying solely on sticky sessions can also lead to uneven traffic distribution across pods, especially if certain clients make more frequent or resource-intensive requests. For many use cases, a centralized session store like Redis might be more scalable and fault-tolerant than sticky sessions. So, let’s look at that option.
A distributed session store like Redis in Laravel allows you to share session data across multiple application instances. This is particularly useful in scalable environments like Kubernetes, where your application might run in multiple pods, and any of these pods could serve user requests.
Redis is an ideal choice because of:
Redis also has some advantages over sticky sessions. Since any instance can handle requests, traffic is more evenly distributed across all pods. If a pod fails, user sessions aren't lost. Another pod can pick up the request and fetch session data from Redis. As your traffic grows, you can scale your application and Redis instances independently based on the need.
Let's walk through the steps for setting Redis as a session driver in Laravel. First, you need to install the required package:
composer require predis/predis
Then you can update the Laravel .env file to point to Redis for session management:
SESSION_DRIVER=redis
REDIS_HOST=your_redis_server
REDIS_PASSWORD=your_redis_password
REDIS_PORT=6379
Within Laravel, you need to update your config/session.php to use the session driver from the .env file:
'driver' => env('SESSION_DRIVER', 'file'),
Then ensure the Redis configuration in config/database.php looks like this:
'redis' => [
'client' => 'predis',
'default' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_DB', 0),
],
],
Next, you'll need a table to store the sessions. Laravel provides a command to generate this table:
php artisan session:table
This will create a migration file. Run the migration to make the sessions table:
php artisan migrate
After the above configurations, Laravel will automatically handle sessions using Redis without requiring any specific code in your application. For example, when you set a session variable:
session(['key' => 'value']);
This value will be stored in Redis. To retrieve it:
$value = session('key');
When you call functions like these, Laravel automatically uses Redis as the backend to manage the session data.
To deploy Redis in Kubernetes, you need to use Helm to deploy a Redis instance in your Kubernetes cluster:
# Add the Bitnami repository which has the Redis chart
helm repo add bitnami <https://charts.bitnami.com/bitnami>
# Install Redis using Helm
helm install my-redis bitnami/redis
Ensure to note down the password for the Redis instance provided by Helm during installation. Then, create a Kubernetes service manifest. Let's call it redis-service.yaml:
apiVersion: v1
kind: Service
metadata:
name: redis-service
spec:
selector:
app: redis
ports:
- protocol: TCP
port: 6379
targetPort: 6379
You can apply the Kubernetes service manifest to create the service:
kubectl apply -f redis-service.yaml
Then verify that the service is running:
kubectl get svc redis-service
Finally, point Laravel to the Kubernetes Redis Service by updating your Laravel .env file or configuration to use the Redis service created in Kubernetes:
REDIS_HOST=redis-service
REDIS_PORT=6379
redis-service is the host because it's the name of the Kubernetes service, and the Kubernetes internal DNS will resolve this name to the appropriate IP address for the service.
Congratulations, you've integrated Redis with Laravel and ensured that the Laravel application communicates with the Redis instance deployed in Kubernetes. This ensures session data is stored and managed efficiently in a distributed environment.
Using session affinities and a distributed session store, your Laravel application can store and persist session data that all instances of your app can access. You can then scale your application, ensuring all users maintain their session data regardless of which instance of your app handles their request. In a Kubernetes environment, where pods can be ephemeral, and user requests can be routed to any pod, these options are essential for maintaining user session consistency.
As technology evolves, ensuring seamless user experiences becomes paramount, especially in distributed and scalable environments like Kubernetes. By leveraging Laravel's inherent adaptability with the robustness of Kubernetes, developers can address the challenges of session management. Not only does this combination enhance application resilience, but it also paves the way for future scalability without compromising on the user's experience.
Try Scout APM today!
The post Stateful Scaling: Laravel Session Management in Kubernetes Clusters appeared first on Laravel News.
Join the Laravel Newsletter to get all the latest Laravel articles like this directly in your inbox.
Read more https://laravel-news.com/laravel-session-management-in-kubernetes-clusters
XML Wrangler has been built with developer experience in mind - you can read any type of XML file, even with complex namespaces and even large XML files. It will also throw exceptions if the XML is invalid!
XML Wrangler is a simplistic PHP library designed to make
reading and writing XML easy. Using familiar Laravel-like methods,
this package is framework-agnostic and can be used in any PHP
project (>=v8.1
). XML Wrangler is jam-packed with
features that make working with XML much more enjoyable than the
out-of-the-box PHP experience:
sole
, first
, firstOrFail
,
collect
, etc.Element
DTO element
to define attributes and namespacesYou will want to check out the readme to learn about everything you can do with this package, but here's an example of reading XML:
<?php
use Saloon\XmlWrangler\XmlReader;
$reader = XmlReader::fromString($xml);
// Retrieve all values as one simple array
$reader->values();
// ['breakfast_menu' => [['name' => '...'], ['name' => '...'], ...]
// Use dot-notation to find a specific element
$reader->value('food.0')->sole();
// ['name' => 'Belgian Waffles', 'price' => '$5.95', ...]
// Use the element method to get a simple Element DTO containing attributes and content
$reader->element('food.0')->sole(); // Element::class
// Use XPath to query the XML
$reader->xpathValue('//food[@bestSeller="true"]/name')->get();
// ['Belgian Waffles', 'Berry-Berry Belgian Waffles']
To get started with this package, you can get full installation and usage instructions on GitHub at saloonphp/xml-wrangler on GitHub.
The post Easily Read and Write XML in PHP appeared first on Laravel News.
Join the Laravel Newsletter to get all the latest Laravel articles like this directly in your inbox.
Read more https://laravel-news.com/xml-wrangler
Site Profiler is a fast, accurate, and ad-free tool designed to provide WHOIS and hosting information about any domain. Whether you’re a domain owner or just curious about where a site is hosted, Site Profiler is a fast way to pull up the details you need.
Just drop in any URL and you’ll have the hosting and domain registration details right at your fingertips. It’s free, simple, and user-friendly.
With Site Profiler, you can drop in a URL, check the details, and make the switch all from one place—whether you’ve moving a domain over or an entire website. Google Domains customers can transfer their domain(s) to WordPress.com for free, and if you decide to add a paid website plan, too, your first year of domain fees is on us. And if you’re considering moving your entire site, please take advantage of our 7-day free trial for a risk-free, seamless site transfer. Learn more at wordpress.com/move.
We’re not done with the Site Profiler just yet. Stay tuned for additional features like performance and security scans to make this tool even more powerful.
What other site analyses would you like to see in the Site Profiler? Let us know in the comments.
Check a site, transfer your domain, and find all the details for any domain under the sun, with Site Profiler. Explore the tool here.
Read more https://wordpress.com/blog/2023/11/02/meet-site-profiler/
Tinkerwell, the code runner for PHP, just released version 4 with a host of new goodies, including AI support, a new detail dive, custom themes, a log viewer, and so much more.
If you are unfamiliar with Tinkerwell, it's an app I use daily. Everything from quickly debugging some code to tinkering on the server to using it to explain code in videos. It's an app I love using, and v4 took everything I like about it and made it better. This is a massive release, and let's take a quick look at some of the new features.
You can now add your Open AI API key in the settings to enable AI features. You can select between GPT 3.5 or GPT-4.
With AI support you can have Tinkerwell write code for you, explain code, and more. All within the editor.
Instead of showing the CLI output that Tinkerwell previously used, Tinkerwell 4 has a more structured output called Detail Dive.
Depending on the result, Detail Dive allows you to expand the view, like in the screenshot above, or display collections and arrays in a table view.
If the result is a Mailable, Tinkerwell previews the email. This makes testing emails even easier, as with HELO or Invoker, because you can pass the data to the view you need for your test case.
This allows you to display all relations in a graph for debugging.
Which expands into:
If you enable the SQL query output at the top right when running Detail Dive, Tinkerwell shows you all queries during the code execution.
Tinkerwell 4 has a log viewer with log tailing. Connect to a Laravel app and check the logs via the icon in the sidebar.
You can find out all the features of this release on the Tinkerwell v4 page and buy yourself a copy today while they are running a special.
The post Tinkerwell v4 is now released appeared first on Laravel News.
Join the Laravel Newsletter to get all the latest Laravel articles like this directly in your inbox.
Read more https://laravel-news.com/tinkerwell-v4
This week, the Laravel team released v10.30, which includes the ability to dispatch events based on a database transaction result. This week's release saw a lot of minor fixes, added tests, and miscellaneous changes. See the changelog for a complete list of updates.
Mateus Guimarães and Taylor Otwell collaborated on dispatching an event based on the result of an in-progress database transaction:
What this PR aims to do is to make the event itself aware of transactions. So, if a transaction fails, the event doesn't even get published. That way, it doesn't matter if the listeners are queued or not or if they have afterCommit enabled, and you can ensure, in the tests, that the event did not get published.
Thanks to this contribution, you can now add the
ShouldDispatchAfterCommit
interface to an event, which
instructs the event dispatcher to hold off on dispatching the event
until the transaction is committed; if the transaction is rolled
back, the event does not fire.
Here's a contrived example of how it might work—given the following transaction and dispatch amid the transaction:
DB::beginTransaction();
Log::info("Transaction started");
$order = Order::create(['amount' => 5000]);
// More stuff...
Log::info("Dispatching OrderCreated event");
OrderCreated::dispatch($order);
Log::info("Closing transaction");
DB::commit();
Here's what the logs might look like:
local.INFO: Transaction started
local.INFO: Dispatching OrderCreated event
local.INFO: Closing transaction
local.INFO: Order created event handled...
And finally, the event might look like the following:
use Illuminate\Contracts\Events\ShouldDispatchAfterCommit;
class OrderCreated implements ShouldDispatchAfterCommit
{
// ...
}
Along with ShouldDispatchAfterCommit
, the pull request expanded to include other
interfaces like ShouldHandleEventsAfterCommit
for
listeners and ShouldQueueAfterCommit
, which may be
implemented on jobs, listeners, mail, and notifications.
Mior Muhammad Zaki contributed test improvements, getting Laravel compatible with the future release of PHPUnit 11—see Pull Request #48815 for details.
You can see the complete list of new features and updates below and the diff between 10.29.0 and 10.30.1 on GitHub. The following release notes are directly from the changelog:
artisan migrate --pretend
command 🚀 by @NickSdot in https://github.com/laravel/framework/pull/48768QueriesRelationships[@getRelationHashedColumn](https://github.com/getRelationHashedColumn)()
typehint by @cosmastech in https://github.com/laravel/framework/pull/48847The post Dispatch Events after a DB Transaction in Laravel 10.30 appeared first on Laravel News.
Join the Laravel Newsletter to get all the latest Laravel articles like this directly in your inbox.
Read more https://laravel-news.com/laravel-10-30-0