3
votes

Requêtes PHP une par une ou simultanément

J'ai des questions sur PHP et comment les requêtes fonctionnent sous le capot.

1) Disons que j'ai écrit mon application PHP et l'ai téléchargée sur le serveur. Maintenant, il y a une fonction que j'ai écrite et si l'utilisateur va sur cette route qui exécute cette fonction, quelque chose se passe.

La question est: si un utilisateur fait la demande et qu'un autre utilisateur fait également la demande, le deuxième utilisateur doit-il attendre que la demande du premier utilisateur soit terminée? (en disant que la demande est terminée, je veux dire jusqu'à ce que la fonction que j'ai écrite soit exécutée jusqu'à la fin). Est-ce la bonne estimation ou peu importe la fonction exécutée. Tant que la demande n'est pas terminée, la deuxième demande ne démarre jamais?

2) J'ai mon application PHP. Imaginez que deux personnes effectuent la demande en même temps qui écrit des données dans la base de données (pas d'écriture, mais de mise à jour). Disons que j'ai utilisé des équilibreurs de charge. si un utilisateur fait une demande à balancer1 et qu'un autre utilisateur fait une demande à balancer2, ce que je veux faire, c'est que si l'appel du premier utilisateur met à jour la base de données, la demande du deuxième utilisateur doit s'arrêter immédiatement (elle ne doit pas être mise à jour).

Le scénario est que j'ai un jeton jwt dans ma base de données qui est utilisé pour faire des requêtes sur un outil tiers. il a expiration 1 heure. Disons qu'une heure s'est écoulée. Si un utilisateur fait l'appel pour mettre à jour le jeton et de la manière dont le deuxième utilisateur effectue également l'appel pour mettre à jour le jeton, ce qui se passera est que le second utilisateur mettra à jour le jeton et le jeton du premier utilisateur sera invalide, ce qui est mauvais.


0 commentaires

3 Réponses :


3
votes

PHP traitera les requêtes en même temps. Travailler sur une seule demande ne verrouille pas une autre pour différents utilisateurs. Mais PHP pourrait exécuter les requêtes du même utilisateur une par une, si une session PHP est verrouillée par la première requête. La deuxième demande sera traitée lorsque la session sera fermée.

Essayez d'exécuter un script PHP avec sleep (30) dans le premier onglet du navigateur:

<?
session_start();

echo 'hello';

Et un autre script dans un autre onglet du navigateur: p>

<?
session_start();

sleep(30);

Le script n ° 2 ne sera pas exécuté tant que la première n'est pas terminée.

C'est important, car vous utilisez des sessions dans chaque application.

p>


2 commentaires

pour la deuxième question, je ne suis pas sûr.


@NikaKhurashvili J'ai ajouté un test que vous pourriez utiliser pour le vérifier.



0
votes
  1. Si vous avez une route qui est desservie par une fonction de contrôleur, pour chaque requête, il y a une instanciation distincte du contrôleur. Par exemple: l'utilisateur A et l'utilisateur B demandent le même itinéraire laravel.com/stackoverflow , le contrôleur est prêt à répondre à chaque demande, quel que soit le nombre d'utilisateurs qui la demandent en même temps. Vous pouvez considérer comme un principe de processus similaire pour n'importe quel service. Par exemple, Laravel fonctionne sur PHP. Ainsi, PHP crée des threads de processus chaque fois que nous avons besoin de PHP pour traiter un script. De même, Laravel instancie le contrôleur pour chaque requête.
  2. Pour le même utilisateur envoyant plusieurs demandes, il sera toujours traité comme le point 1.
  3. Si vous souhaitez traiter des demandes particulières une par une, vous pouvez mettre en file d'attente les travaux. Par exemple, disons que vous souhaitez traiter un paiement. Vous avez 5 demandes en cours. Ainsi, le contrôleur prendra toutes les demandes simultanément, mais la fonction de contrôleur peut envoyer un travail en file d'attente et ceux-ci sont traités un par un.
  4. Considérant que deux personnes essaient de demander le même itinéraire qui a une fonction de mise à jour de la base de données, vous pouvez lire un bel article ici sur le verrouillage optimiste et pessimiste.

3 commentaires

Merci. @nikolai ci-dessous y a également répondu et il dit ce qui suit - "Mais PHP exécutera les requêtes du même utilisateur une par une. Cela arrive, car PHP verrouille le fichier de session d'un utilisateur jusqu'à ce que la requête soit terminée. Et une autre requête ne sera pas exécutée. sauf si la session est déverrouillée. " . que dites-vous à ce sujet? vous avez dit en face.


Je ne crois pas que laravel ou même le noyau php aient un mécanisme pour verrouiller les requêtes simultanées d'un utilisateur. Un moyen simple de tester est de prendre une URL laravel ou un simple script php ouvrable sur le Web et de l'ouvrir dans plusieurs onglets en même temps.


En général, @MihirBhende a raison et PHP exécutera simultanément les requêtes du même utilisateur. Mais PHP a un mécanisme pour verrouiller les requêtes, si la session est ouverte, cela se produira. Consultez la documentation us.php.net/manual/en/function .session-write-close.php . Je mettrai à jour ma réponse.



0
votes

Je devrais voter pour fermer ceci - c'est beaucoup trop large ... mais je vais essayer.

Si les requêtes dépendent d'une ressource qui ne peut effectuer qu'une seule tâche à la fois, alors elles ne peut pas «fonctionner» simultanément. Il est fort possible que vous ayez un seul cœur de processeur, ou un seul disque - cependant au niveau de la requête HTTP (en l'absence de code pour appliquer le verrouillage mutex), ils sembleront fonctionner en même temps - c'est ce que multi -tâcher, c'est tout. Le thread d'exécution sera souvent retardé en attendant que quelque chose d'autre se produise et à ce moment-là, le planificateur de tâches du système d'exploitation vérifiera s'il y a d'autres tâches en attente d'être exécutées. Vous pouvez facilement le tester vous-même:

 <?php

 $started=time();
 $fh=fopen("/tmp/concurency_test", "w");
 flock($fh, LOCK_EX);
 sleep(20);
 flock($fh, LOCK_UN);
 print "Ran for " . (time() - $started) " seconds";

(essayez d'y accéder dans différentes fenêtres de navigateur à peu près au même moment - ou dans 2 iframes sur la même fenêtre)

Comparez cela avec:

 <?php

 $started=time();
 sleep(20);
 print "Ran for " . (time() - $started) " seconds";

Cela montre également une des raisons pour lesquelles vous ne devriez pas utiliser de fichiers plats pour stocker des données sur votre serveur. Notez que le gestionnaire de session par défaut en PHP utilise le verrouillage basé sur les fichiers pendant toute la durée pendant laquelle les données de session sont ouvertes par le script.

Les bases de données emploient une variété de stratégies pour éviter de revenir à la mise en file d'attente d'une seule opération - le plus souvent le contrôle de version. Cela ne résout pas le problème que vous décrivez: 2 clients ne devraient jamais utiliser le même jeton de session - c'est pourquoi le jeton de session est séparé des informations d'identification dans un système bien conçu.


0 commentaires