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
Au fil de notre collaboration avec Deezer, nous avons Ă©tĂ© impliquĂ©s dans plusieurs initiatives visant Ă optimiser les performances de leur plateforme. Notre engagement initial sâest concentrĂ© sur le soutien et le conseil Ă lâĂ©quipe âProduct Featuresâ lors de leur projet de migration en cours. Nous avons apportĂ© notre expertise pour rĂ©soudreâŠ
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âŠ
Groupama Ăpargne Salariale digitalise son expĂ©rience client en leur permettant dâeffectuer leurs versements dâĂ©pargne salariale en ligne. Lâapplication offre aux entreprises une interface web claire et dynamique, composĂ© dâun tunnel de versement complet : import des salariĂ©s via fichier Excel, rappel des contrats souscrits et des plans disponibles, âŠ

