How to See Full Request URI in FPM Status
Or: How FPM status page can help when some URLS are blocked?
I changed some code in my application, and now the tests suite is failing with many timeout errors. Huh?! 😮 What happened?
Section intitulée the-initial-setupThe initial setup
Before my changes, we had the following application flow:
- someone create a “project” (POST /projects);
- the server dispatches a message in rabbitmq;
- the server saves some data in the database;
- and finally returns a 201;
- then a handler processes the message: it fetches the “project” via an API and does its job.
Note: I simplified the algo to make it simpler to understand.
We are using asynit to run our tests. From the README, it’s a:
Asynchronous HTTP Request Testing Library for API and more…
Section intitulée the-next-setupThe next setup
We are using symfony/messenger to handle async tasks. In order to simplify our test suite, I tested to consume messages synchronously instead of relying on a worker. Even if I’m not a big fan of this solution, especially since the test env now differs from the prod env, the code is so much simpler! So what’s going on here?
My first intuition was:
there is a deadlock somewhere!
A deadlock is a situation where a processus A waits for another processus B. And this processus B also waits for A.

Section intitulée finding-the-deadlockFinding the deadlock
Since the platform is build on top of HTTP API, I wanted to use the PHP FPM status page to understand which URLs are blocked.
After quick configuration I’m getting this page:
Oups! As you can see, the “request URI” column does not contain the full request URI. Only the script, and the query string are here. It’s not a bug, it’s a feature, since it’s documented:
request uri The URI of the last served request (after webserver processing, it may always be /index.php if you use a front controller pattern redirect).
Since I’m using Symfony, I’m using the front controller pattern.
Let’s try to fix it!
I’m using nginx, and nginx passes some parameters to FPM. It looks like that:
location ~ ^/index\.php(/|$) {
fastcgi_pass 127.0.0.1:9000;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
include environments;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SERVER_NAME $http_host;
}
Section intitulée how-to-see-real-request-url-in-fpm-status-pageHow to See Real Request URL in FPM Status page?
So after some guess and tries, I found that adding the following code make the full URI available:
location ~ ^/index\.php(/|$) {
fastcgi_pass 127.0.0.1:9000;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
include environments;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SERVER_NAME $http_host;
+ fastcgi_param SCRIPT_NAME $request_uri;
}
Here we go! Now we have the full path in the request URI, and it’s much easier to debug.
Section intitulée so-what-s-going-onSo, what’s going on?
While it’s not the most important part of this article, you might be curious and you want to know the fix.
So I was able to detect that an HTTP call was waiting for the result of another HTTP call.
Section intitulée the-bugThe bug
Let’s sum it up, by reusing the flow in the first chapter, a bit more detailed:
- someone create a “project” (POST /projects);
- the server dispatches a message in rabbitmq;
- the handler processes the message: it fetches the "project” via an API and does its job;
- but the project is not available yet. It retries until it exist;
- 💥 ;
the server saves some data in the database;and finally returns a 201.
Section intitulée the-fixThe fix
The fix is pretty simple, I moved the message dispatch as late as possible:
- someone create a “project” (POST /projects);
- but the project is not available yet. It retries until it exist;
- the server saves some data in the database;
- the server dispatches a message in rabbitmq;
- the handler processes the message: it fetches the "project” via an API and does its job;
- and finally returns a 201.
Section intitulée conclusionConclusion
Monitoring what’s going on during the tests suite from the FPM point of view is really useful! It helps me to find my deadlock very quickly because I could see very clearly what API endpoints were being requested at any time. I also discovered via this status page we were using only 4 FPM workers! It really too low since asynit runs by default 15 requests simultaneously. I increased it to 25, and the tests suite is now almost twice faster. I really like these quick wins!
Finally, you can find the full diff in the pull request and #190
Commentaires et discussions
Ces clients ont profité de notre expertise
JoliCode continue d’accompagner les équipes web d’Afflelou en assurant la maintenance des différentes applications constituant la plateforme Web B2C. Nous mettons en place des bonnes pratiques avec PHPStan et Rector, procédons à la montée de version de PHP et Symfony, optimisons le code grâce au profiling, et collaborons avec l’infogéreur pour les…
L’équipe de Finarta a fait appel à JoliCode pour le développement de leur plateforme Web. Basée sur le framework Symfony 2, l’application est un réseau privé de galerie et se veut être une place de communication et de vente d’oeuvres d’art entre ses membres. Pour cela, de nombreuses règles de droits ont été mises en places et une administration poussée…
En tant que joaillier 100 % numérique, l’équipe de Courbet Paris a souhaité se doter d’une plateforme eCommerce, capable d’offrir une expérience moderne qui revalorise l’acte d’achat de produits de joaillerie sur internet. JoliCode a accompagné leur équipe en développant une plateforme robuste, mais aussi évolutive, afin de répondre aux enjeux business…

