Magento 2 Slow Admin Login

Published: May 21, 2018

Tags:

Recently at Something Digital we upgraded a client’s site to version 2.1.12. Shortly thereafter, we received a report that logging in to the admin panel was taking significantly longer than usual.

Looking in New Relic we could see that the vast majority of the time was being spent reading the session from Redis.

A screenshot showing a transaction trace of a slow login in New Relic

I did a bit of Googling and landed on the “Magento 2 Slow Admin Login and Saving Products” StackExchange question. There I found a link to the following patch…

From aaa60b1b72bdc189b38492bd50b0ffb23101173e Mon Sep 17 00:00:00 2001
From: Dmytro Horytskyi <[email protected]>
Date: Wed, 22 Nov 2017 17:35:17 +0200
Subject: [PATCH] MAGETWO-84106: [2.2.1] Implementation (fix) of session
 locking mechanism in php-redis-session-abstract leads to 30 sec timeout

---
 lib/internal/Magento/Framework/Session/SessionManager.php | 12 +-----------
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/lib/internal/Magento/Framework/Session/SessionManager.php b/lib/internal/Magento/Framework/Session/SessionManager.php
index 2cea02fa3b36..272d3d923c8a 100644
--- a/lib/internal/Magento/Framework/Session/SessionManager.php
+++ b/lib/internal/Magento/Framework/Session/SessionManager.php
@@ -504,18 +504,8 @@ public function regenerateId()
             return $this;
         }
 
-        //@see http://php.net/manual/en/function.session-regenerate-id.php#53480 workaround
         if ($this->isSessionExists()) {
-            $oldSessionId = session_id();
-            session_regenerate_id();
-            $newSessionId = session_id();
-            session_id($oldSessionId);
-            session_destroy();
-
-            $oldSession = $_SESSION;
-            session_id($newSessionId);
-            session_start();
-            $_SESSION = $oldSession;
+            session_regenerate_id(true);
         } else {
             session_start();
         }

The issue is explained in detail in the GitHub issue “Admin login always takes >30 sec when using Redis on 2.2.1”

The regenerateId method was recently rewritten to generate a new session id when an admin logs into the admin dashboard.

The change in the session id causes the session read method of the redis session handling class to loop 60 times with a 500 ms sleep at the end of each loop before breaking out while it looks for the locking pid. This is because both session_regenerate_id and session_start increment the lock value 0->1->2 but only when the value is 1 will it break out otherwise it continues for $tries (60) with a 500 ms sleep between each one.

Essentially it’s not safe to call both session_regenerate_id and session_start the way Magento had when using the Redis session handler as it will double lock the session, leading to the session never getting unlocked until the session reader ultimately gives up on trying to obtain the lock.

At the time of writing this the fix is applied to the latest 2.2.X version (2.2.4) but is still not applied to the latest 2.1.X version (2.1.13) despite being backported to 2.1 and being present in 2.1-develop on GitHub.

Max Chadwick Hi, I'm Max!

I'm a software developer who mainly works in PHP, but also dabbles in Ruby and Go. Technical topics that interest me are monitoring, security and performance.

During the day I solve challenging technical problems at Something Digital where I mainly work with the Magento platform. I also blog about tech, work on open source and hunt for bugs.

If you'd like to get in touch with me the best way is on Twitter.