Contacts

Salutations à toi, cher ami! Programme d'affiliation médiocre Succès PHP

Mécanisme de stockage standard des sessions utilisateur dans PHP - Stockage dans des fichiers. Toutefois, lorsque l'application est en cours d'exécution sur plusieurs serveurs pour équilibrer la charge, il est nécessaire de stocker ces sessions dans le référentiel accessible à chaque serveur d'applications. Dans ce cas, il est bon de stocker des sessions Redis.

La solution la plus populaire est l'expansion de PPPREDIS. Il suffit d'installer l'extension et configurer PHP.ini et les sessions seront automatiquement enregistrées dans REDIS sans modifier le code de l'application.

Cependant, une telle solution a un inconvénient - le manque de blocage de la session.

Lors de l'utilisation d'un mécanisme de stockage standard de session dans des fichiers, une session ouverte bloque le fichier jusqu'à la fermeture du fichier. Avec plusieurs appels simultanés, accès à la session, de nouvelles demandes seront attendues jusqu'à ce que la précédente complète de travailler avec la session. Cependant, lors de l'utilisation d'une pépedis, il n'y a pas de mécanisme de blocage. Avec plusieurs demandes asynchrones, une course est en même temps et certaines données enregistrées dans la session peuvent être perdues.

Il est facile de vérifier. Nous envoyons 100 demandes au serveur de manière asynchrone, chacune écrivant son paramètre à la session, puis examinez le nombre de paramètres de la session.

Script de test

"; Se rompre;)


En conséquence, nous obtenons que la session n'est pas de 100 paramètres et 60-80. Les données restantes que nous avons perdues.
Dans des applications réelles, bien sûr, 100 demandes simultanées ne seront toutefois pas la pratique que la pratique montre que même avec deux demandes simultanées asynchrones, les données enregistrées par l'une des demandes sont souvent maintenues par une autre. Ainsi, l'utilisation d'une extension PPPredis pour stocker des sessions est dangereuse et peut entraîner une perte de données.

Comme l'une des solutions du problème - votre SessionHandlerSoutenir les serrures.

Ventes

Pour définir le verrou de la session, définissez la valeur de la clé de verrouillage sur la valeur générée aléatoire (basée sur UNIQID). La valeur doit être unique pour que toute demande parallèle puisse accéder.

Serrures de fonction protégée ($ sessionID) ($ tentatives \u003d (1000000 * $ ceci-\u003e LockMaxwait) / $ this-\u003e Spinlockwait; $ this-\u003e jeton \u003d uniqid (); $ ceci-\u003e< $attempts; ++$i) { $success = $this->redis-\u003e Ensemble ($ this-\u003e getrediskey ($ this-\u003e lockkey), $ this-\u003e jeton, ["nx",]); if ($ succession) ($ ceci-\u003e verrouillé \u003d vrai; renvoyer vrai;) USLEEP ($ this-\u003e Spinlockwait); ) Renvoyer false; )
La valeur est installée avec le drapeau Nx., C'est-à-dire que l'installation ne se produit que s'il n'y a pas de telle clé. Si une telle clé existe, nous faisons une ré-tentative après un certain temps.

Vous pouvez également utiliser une durée de vie limitée dans le radish, cependant, le temps de fonctionnement du script peut être modifié après la définition de la clé et le processus parallèle peut accéder à la session jusqu'à ce qu'il soit terminé avec celui-ci dans le script actuel. Lorsque le script est terminé, la clé est en tout cas supprimé.

Lors du déverrouillage de la session lorsque le script est terminé pour supprimer la clé, utilisez Lua.-scénario:

Déverrouillage de la fonction privée () ($ script \u003d<<redis-\u003e Eval ($ Script, Array ($ ceci-\u003e getredriskey ($ this-\u003e lockkey), $ this-\u003e jeton), 1); $ ceci-\u003e verrouillé \u003d faux; $ ceci-\u003e jeton \u003d null; )
Utiliser la commande Del. Il est impossible, car utilisez-le, vous pouvez supprimer la clé installée par un autre script. Un tel scénario garantit la suppression que si la clé de blocage correspond à une valeur unique définie par le script actuel.

Code de classe complète

classe RedissessionHandler implémente \\ SessionHandlerInterface (protégé $ REDIS; protected $ TTL; préfixe protégé $; protégé $ Verrouillé; privé $ blockey; privé $ spinlockwait; privé $ Spinlockwait; Fonction privée __construction (\\ Redis $ Redis, $ PREFIX \u003d "PHPREDIS_SESSION:", $ Spinlockwait \u003d 200000) ($ ceci-\u003e Redis \u003d $ redis; $ this-\u003e ttl \u003d ini_get ("gc_maxlifetime"); $ INI_GET ("max_execution_time"); $ this-\u003e lockmaxwait \u003d $ Inimaxexectiontime? $ INIMAXExecutiontime * 0,7: 20; $ ceci-\u003e préfixe \u003d $ préfixe \u003d $ préfixe; $ ceci-\u003e verrouillé \u003d blocked \u003d € Spinlockwait;) Fonction publique ouverte ($ savePath , $ De sessionName) (retourne vrai;) Serrures de fonction protégée ($ sessionID) ($ tentatives \u003d (1000000 * $ ceci-\u003e LockMaxwait) / $ this-\u003e Spinlockwait; $ this-\u003e jeton \u003d € (); $ ceci-\u003e blockkey \u003d $ sessionID. ".lock"; pour ($ i \u003d 0; $ i< $attempts; ++$i) { $success = $this->redis-\u003e Ensemble ($ this-\u003e getrediskey ($ this-\u003e lockkey), $ this-\u003e jeton, ["nx",]); if ($ succession) ($ ceci-\u003e verrouillé \u003d vrai; renvoyer vrai;) USLEEP ($ this-\u003e Spinlockwait); ) Renvoyer false; ) Fonction privée Déverrouillage de la fonction () ($ script \u003d<<redis-\u003e Eval ($ Script, Array ($ ceci-\u003e getredriskey ($ this-\u003e lockkey), $ this-\u003e jeton), 1); $ ceci-\u003e verrouillé \u003d faux; $ ceci-\u003e jeton \u003d null; ) Fonction publique Fermer () (si ($ this-\u003e verrouillée) ($ ceci-\u003e Déverrouillage de la ();) Retournez vrai;) Fonction publique Lecture ($ sessionID) (si (! $ Ceci-\u003e Verrouillé) (si (! $ this-\u003e Locksession ($ sessionId)) (Retour Faux;)) Rendez-vous $ ceci-\u003e Redis-\u003e escrediskey ($ sessionID))?: "";) Fonction publique Écrire ($ sessionID, $ données) (si ($ this-\u003e ttl\u003e 0) ($ ceci-\u003e redis-\u003e setex ($ this-\u003e getredisey ($ sessionID), $ this-\u003e ttl, $ données);) ailleurs ($ this-\u003e redis-\u003e ensemble ($ this-\u003e getrediskey ($ sessionId), $ données);) retourne vrai;) Fonction publique Détruire ($ SéanceID) ($ this-\u003e Redis-\u003e del ($ this-\u003e getredisey ($ sessionID)); $ this-\u003e Fermer (); retour vrai;) Fonction publique GC ($ Lifetime) (retour vrai) Fonction publique Setttl ($ TTL) ($ ceci-\u003e ttl \u003d $ TTL;) Fonction publique getlockMaxwait () (Retour $ ceci-\u003e LockMaxwait; ) Fonction publique SetockMaxwait ($ LockMaxwait) ($ ceci-\u003e LockMaxwait \u003d $ LockMaxwait;) Fonction protégée ACTREDISKEY ($ TIGNE) (Vide ($ ceci-\u003e PREFIX)) Retourner. $ ceci-\u003e préfixe. $ Clé; ) Fonction publique __Destruire () ($ ceci-\u003e Fermer ();))

Lien

$ REDIS \u003d Nouveau Redis (); Si ($ REDIS-\u003e Connect ("11.111.111.11", 6379) && $ REDIS-\u003e SELECT (0)) ($ gestionnaire \u003d nouveau \\ Suffi \\ RedisessionHandler ($ Redis); session_set_save_handler ($ gestionnaire);) session_start ();

Résultat

Après avoir connecté la nôtre SessionHandler Notre script de test montre avec confiance 100 paramètres dans la session. Dans le même temps, malgré le blocage, le temps de traitement total de 100 demandes a légèrement augmenté. Dans la pratique réelle, il n'y aura pas de ce nombre de demandes simultanées. Cependant, l'opération de script est généralement plus substantielle et avec des requêtes simultanées, une attente perceptible peut être remarquable. Par conséquent, vous devez penser à réduire le temps de travailler avec la session de script (appel session_start () seulement si nécessaire travailler avec la session et session_write_close () À la fin du travail avec elle)

Demande le serveur sans redémarrer la page. Ceci est une méthode de bas niveau qui a un grand nombre de réglages. Il sous-tend le travail de toutes les autres méthodes Ajax. Il a deux utilisations:

uRL - Ajouter une demande.
les paramètres - Dans ce paramètre, vous pouvez définir les paramètres de cette demande. Définit l'objet dans le format (nom: valeur, nom: valeur ...). Aucun des paramètres n'est obligatoire. Vous pouvez définir les paramètres par défaut à l'aide de la méthode $ .AjaxSetUp ().

Liste des paramètres

↓ Titre: Type (valeur par défaut)

Lors de l'exécution d'une requête, les en-têtes (en-tête) indiquent les types de contenu admissibles attendus du serveur. Les valeurs de ces types seront extraites du paramètre Accept.

Par défaut, toutes les demandes sans redémarrer la page se produisent de manière asynchrone (c'est-à-dire après l'envoi d'une demande au serveur, la page n'arrête pas son travail en attendant une réponse). Si vous avez besoin d'une exécution synchrone de la requête, définissez le paramètre sur FALSE. Les demandes de crossomain et les demandes comme "JSONP" ne peuvent pas être effectuées en mode synchrones.

N'oubliez pas que l'exécution de requêtes en mode synchrones peut entraîner le blocage de la page jusqu'à ce que la demande soit entièrement remplie.

Ce champ contient une fonction qui sera appelée directement avant d'envoyer une demande AJAX au serveur. Cette fonction peut être utile pour modifier l'objet JQXHR (dans versions précoces Bibliothèques (jusqu'à 1.5), au lieu de JQXHR utilise XMLHTTTPQUEST). Par exemple, vous pouvez changer / spécifier les en-têtes nécessaires (en-têtes) I.D. L'objet JQXHR sera transmis à la première fonction d'argument. Le deuxième argument passe les paramètres de requête.

Dans ce domaine, vous pouvez spécifier des en-têtes de requête supplémentaires (en-tête). Ces changements seront entrés avant l'appel de la Beforesend, dans lequel les éditeurs finaux peuvent être effectués.

Lorsque vous transférez ce paramètre sur true, la requête sera exécutée avec le statut "réussi", uniquement si la réponse du serveur diffère de la réponse précédente. JQuery vérifie ce fait référence à l'en-tête de dernière modification. En commençant par JQuery-1.4, en plus de la dernière modification et "Etag" est également vérifiée (les deux sont fournies par le serveur et sont nécessaires pour notifier au navigateur que les données demandées du serveur ne sont pas modifiées de la demande précédente).

Vous permet de définir l'état de la source de page d'emplacement (comme si cela se produisait via Protocole de fichier), même si JQuery le reconnaissait autrement. La bibliothèque décide que la page fonctionne localement dans le cas des protocoles suivants: fichier, * -extension et widget.

Il est recommandé de définir la valeur du paramètre islocal Au niveau mondial - en utilisant la fonction $ .AJAXsetup () et non dans les paramètres des demandes d'ajax individuelles.

Spécifie le nom du paramètre ajouté à l'URL avec une requête JSONP (par défaut, "Callback" est utilisée - "http: //sitename.ru? Rappel \u003d ...").

Commençant par JQuery-1.5, spécifiant dans ce faux paramètre, vous éviterez l'addition à l'URL. paramètre supplémentaire. Dans ce cas, il est nécessaire de définir explicitement la valeur de la propriété JSONPCallback. Par exemple, c'est le cas: (JSONP: FALSE, JSONPCALLBACK: "CALLBACKNAME").

Définit le nom de la fonction qui sera appelée lorsque vous répondez au serveur de la demande JSPA. Par défaut, JQuery génère un nom arbitraire de cette fonctionnalité, une option plus préférée qui simplifie le fonctionnement de la bibliothèque. L'une des raisons pour lesquelles il est de spécifier votre propre fonction de traitement de la requête JSONP consiste à améliorer la mise en cache des demandes d'obtenir.

En commençant par JQuery-1.5, vous pouvez spécifier une fonction dans ce paramètre afin de traiter vous-même la réponse du serveur. Dans ce cas, la fonction spécifiée doit renvoyer les données reçues du serveur (dans la fonction spécifiée, elles seront disponibles dans le premier paramètre).

Par défaut, toutes les données transmises au serveur sont pré-converties en chaîne (format URL: fname1 \u003d value1 & fname2 \u003d value2 & ...) L'application correspondante "application / x-www-form-urlencoded". Si vous devez envoyer des données qui ne peuvent pas être soumises à un traitement similaire (par exemple, DOM Document), vous devez désactiver l'option ProcessData.

Ce paramètre est utilisé pour les types de types de type AJAX de Domaine AJAX, DataType peut être ou "JSONP" ou "Script". Spécifie le codage dans lequel une requête croisée sera effectuée. Ceci est nécessaire, si le serveur sur le domaine de quelqu'un d'autre utilise un codage autre que le codage sur un serveur de domaine natif.

(Ce paramètre est apparu dans JQuery-1.5) Un ensemble de vapeur, dans lequel les codes d'exécution de la requête sont comparés aux fonctions qui seront causées. Par exemple, pour le code 404 (n'existent pas), vous pouvez dessiner un message à l'écran:

$ .ajax (StatusCode: (404: fonction () (alerte ( "Page non trouvée") ; } } } ) ;

Les fonctions qui répondent à des codes de requête réussie recevront les mêmes arguments que les fonctions d'une exécution réussie de la requête (spécifiée dans le paramètre de réussite) et les fonctions qui fonctionnent sur les codes d'erreur seront identiques aux fonctions d'erreur.

La fonction qui sera appelée dans le cas d'une réalisation réussie de la demande de serveur. Il sera transmis trois paramètres: les données envoyées par le serveur et ont déjà passé le traitement préliminaire (qui est excellent pour différents types de données). Le deuxième paramètre est une chaîne avec statut d'exécution. Le troisième paramètre contient l'objet JQXHR (dans les versions antérieures de la bibliothèque (jusqu'à 1,5), au lieu de JQXHR utilise XMLHTTPQUEST). En commençant par JQuery-1.5, au lieu d'une seule fonction, ce paramètre peut prendre une gamme de fonctions.

Temps d'avoir une réponse du serveur. Fixé en millisecondes. Si ce délai est dépassé, la requête sera complétée par une erreur et l'événement d'erreur se produira (voir la description ci-dessus), qui aura le statut "Timeout".

Le temps comporte à partir du moment d'appeler la fonction $ .ajax. Il peut arriver que, à ce moment-là, plusieurs autres demandes seront lancées et que le navigateur reportera l'exécution de la demande actuelle. Dans ce cas temps libre. Cela peut se terminer, bien que, en fait, la demande n'a pas encore été lancée.

Dans JQuery-1.4 et plus jeune, à la fin du temps d'attente, l'objet XMLHTTPRequest basculera sur l'état d'erreur et l'accès à ses champs peut provoquer une exception. DANS Firefox 3.0+ Les requêtes du type de script et JSONP ne seront pas interrompues lorsque le temps d'attente est dépassé. Ils seront complétés même après cette période expireront.

Une fonction qui fournira un objet XMLHTTTPRequest. Par défaut, les navigateurs IE Navigateurs Cet objet est ActiveXObject et dans d'autres cas, il est XMLHTTPRequest. Avec ce paramètre, vous pouvez implémenter votre propre version de cet objet.

(Ce paramètre est apparu dans JQuery-1.5.1) Un ensemble de paires (nom: signe) pour modifier / ajouter les valeurs des champs correspondants de l'objet XMLHTTPRequest. Par exemple, vous pouvez définir sa propriété SansReDentials dans True, lors de la recherche d'une requête CrossDomain:

$ .ajax ((URL: A_CROSS_DOMAIN_URL, XHRFields: (Sansrétiens: True)));

DANS jquery-1.5 La propriété Sansfredentials n'est pas prise en charge par l'indigène XMLHTTPRequest et avec une requête de crossomen Ce champ sera ignoré. Dans toutes les versions suivantes de la bibliothèque, elle est corrigée.

Manutentionnaires d'événements

Beforesert, erreur, DataFilter, succès et réglages complets (leur description dans la section précédente) vous permettent d'établir des gestionnaires d'événements qui se produisent à certains points de l'exécution de chaque requête AJAX.

Êtreforesend. Cela se produit immédiatement avant d'envoyer une demande au serveur. erreur arrive en cas d'exécution infructueuse de la requête. datafilter. arrive au moment de l'arrivée des données du serveur. Vous permet de gérer les données "brutes" envoyées par le serveur. succès. Il se produit dans le cas d'une réussite de la demande. compléter. arrive en cas d'achèvement de la demande.

Exemple simple usage. Nous retirerons le message avec une exécution de la requête réussie:

$ .ajax ((URL: "ajax / test.html", succès: fonction () (alerte ("charge a été effectuée."););));

En commençant par JQuery-1.5, la méthode $ .AJAX () renvoie l'objet JQXHR, qui, entre autres choses, implémente l'interface différée, ce qui vous permet de définir des gestionnaires d'exécution supplémentaires. En plus de la norme .Done (), .fail () i.then () méthodes de différé (), avec lesquelles vous pouvez installer des gestionnaires, sont implémentées dans JQXHR.SUCCESS () ,.Error () et.Collete () . Ceci est fait pour répondre aux noms habituels des méthodes avec lesquelles les gestionnaires de l'exécution des requêtes Ajax sont définis. Cependant, en commençant par JQuery-1.8, ces trois méthodes seront non désiré pour une utilisation.

Pour certains types de requêtes, tels que JSONP ou CrossDomains, obtenez des requêtes, il n'est pas prévu d'utiliser des objets XMLHTTTPRequest. Dans ce cas, transmis aux gestionnaires XMLHTTPRequest et TextStatus contiendront une valeur non définie.

Handlers intérieurs, cette variable contiendra la valeur de paramètre le contexte.. Si cela n'a pas été spécifié, cela contiendra un objet de paramètres.

Type de données

La fonction $ .ajax () trouvera sur le type de serveur de données envoyé du serveur lui-même (MIME TOOLS). De plus, il est possible de spécifier personnellement (clarifier) \u200b\u200bcomment interpréter ces données. Ceci est fait en utilisant le paramètre DataType. Valeurs possibles de ce paramètre:

"XML" - Le document XML résultant sera disponible sous forme de texte. Vous pouvez travailler avec lui standard signifie jQuery (ainsi que sur le document HTML). "HTML" - Le HTML reçu sera disponible sous forme de texte. S'il contient des scripts dans les étiquettes



Dans cet exemple en utilisant la méthode jQuery .charge () Nous sommes pressés sur l'élément

Avez-vous aimé l'article? Partagez-le