Contactos

¡Saludos a ti, querido amigo! Programa de afiliados Pobre éxito PHP

Mecanismo de almacenamiento estándar de sesiones de usuario en PHP - Almacenamiento en archivos. Sin embargo, cuando la aplicación se está ejecutando en varios servidores para equilibrar la carga, es necesario almacenar estas sesiones en el repositorio accesible a cada servidor de aplicaciones. En este caso, es bueno para almacenar sesiones. Redis.

La solución más popular es la expansión de Phredis. Es suficiente para instalar la extensión y configurar php.ini y las sesiones se guardarán automáticamente en Redis sin cambiar el código de la aplicación.

Sin embargo, tal solución tiene un inconveniente: la falta de bloqueo de la sesión.

Cuando se utiliza un mecanismo de almacenamiento de sesión estándar en los archivos, una sesión abierta bloquea el archivo hasta que esté cerrado. Con varias apelaciones simultáneas, acceso a la sesión, se esperarán nuevas solicitudes hasta que la anterior complete el trabajo con la sesión. Sin embargo, al usar un Phpredis no hay un mecanismo de bloqueo. Con varias solicitudes asíncronas, una carrera es al mismo tiempo, y se pueden perder algunos datos registrados en la sesión.

Es fácil de comprobar. Enviamos 100 solicitudes al servidor de forma asíncrona, cada una de las cuales escribe su parámetro a la sesión, luego considere el número de parámetros en la sesión.

Script de prueba

"; Rotura;)


Como resultado, obtenemos que en la sesión no es 100 parámetros, sino 60-80. Los datos restantes que perdimos.
Sin embargo, en aplicaciones reales, por supuesto, 100 solicitudes simultáneas no serán, sin embargo, la práctica muestra que incluso con dos solicitudes simultáneas asíncronas, los datos registrados por una de las solicitudes se mantienen a menudo por otra. Por lo tanto, el uso de la extensión PHPREDIS para almacenar sesiones es inseguro y puede llevar a la pérdida de datos.

Como una de las soluciones del problema, su MaestríaCerraduras de apoyo.

Ventas

Para configurar el bloqueo de la sesión, configure el valor de la tecla BLOQUEO para generarle aleatoriamente (según el Uniqid). El valor debe ser único para que cualquier solicitud paralela pueda acceder.

Locksession de función protegida ($ sesiones) ($ intentos \u003d (1000000 * $ esta-\u003e lockmaxwait) / $ esta-\u003e spinlockwait; $ esto-\u003e token \u003d uniqid (); $ esto-\u003e< $attempts; ++$i) { $success = $this->redis-\u003e Set ($ esta-\u003e getRediskey ($ esta-\u003e LockKey), $ este-\u003e Token, ["NX",]); Si ($ sucesiones) ($ esto-\u003e bloqueado \u003d verdadero; devuelve verdadero;) usleep ($ esta-\u003e spinlockwait); ) Falso retorno; )
El valor se instala con la bandera. NX., Es decir, la instalación ocurre solo si no hay tal clave. Si existe tal clave, hacemos un nuevo intento después de un tiempo.

Sin embargo, también puede usar un tiempo de vida limitado en el rábano, sin embargo, el tiempo de funcionamiento del script se puede cambiar después de configurar la tecla, y el proceso paralelo puede acceder a la sesión hasta que se complete con él en el script actual. Cuando se completa el script, la clave está eliminada en cualquier caso.

Al desbloquear la sesión cuando se completa el script para eliminar la clave, use Lua.-guión:

Función privada UnlockSession () ($ script \u003d<<redis-\u003e eval ($ script, matriz ($ esta-\u003e getrediskey ($ esta-\u003e lockkey), $ esta-\u003e token), 1); $ esto-\u003e bloqueado \u003d falso; $ esto-\u003e token \u003d null; )
Usa el comando Del. Es imposible, ya que usarlo puede eliminar la llave instalada por otro script. Dicho escenario garantiza la eliminación solo si la clave de bloqueo corresponde a un valor único establecido por el script actual.

Código de clase completa

clase RedissionSessionhandler implementa \\ SessionHandlerInterface (protegido $ Redis; Protegido $ TTL; protegido $ prefijo; protegido $ bloqueado; Lockkey Privado $ Bloquee; Token privado $; Privado $ SpinLockwait; Privado $ Lockmaxwait; Función pública __Construct (\\ Redis $ Redis, $ Prefix \u003d "Phpredis_Session:", $ spinlockwait \u003d 200000) ($ esta-\u003e redis \u003d $ redis; $ esto-\u003e ttl \u003d ini_get ("gc_maxlifetime"); $ inimaxecutiontimetime \u003d ini_get ("max_execution_time"); $ esto-\u003e lockmaxwait \u003d $ ¿InimaxexectionTime? $ InimaxExecuctuTime * 0.7: 20; $ este-\u003e Prefijo \u003d $ este-\u003e bloqueado \u003d FALSO; $ ESTA-\u003e LOCKKEY \u003d NULL; $ ESTA-\u003e SPINLOCKWAIT \u003d $ SPIPLOCKWAIT;) FUNCIÓN PÚBLICA ABIERTA ($ SAVEPATH , $ SESIONNAME) (devuelve verdadero;) Locksession de la función protegida ($ sesiones) ($ intentos \u003d (1000000 * $ esta-\u003e lockmaxwait) / $ esta-\u003e spinlockwait; $ esto-\u003e token \u003d uniqid (); $ esto-\u003e Lockkey \u003d $ sessionid. ".lock"; para ($ i \u003d 0; $ i< $attempts; ++$i) { $success = $this->redis-\u003e Set ($ esta-\u003e getRediskey ($ esta-\u003e LockKey), $ este-\u003e Token, ["NX",]); Si ($ sucesiones) ($ esto-\u003e bloqueado \u003d verdadero; devuelve verdadero;) usleep ($ esta-\u003e spinlockwait); ) Falso retorno; ) Función privada Unlocksession () ($ script \u003d<<redis-\u003e eval ($ script, matriz ($ esta-\u003e getrediskey ($ esta-\u003e lockkey), $ esta-\u003e token), 1); $ esto-\u003e bloqueado \u003d falso; $ esto-\u003e token \u003d null; ) Cierre de la función pública () (si ($ esto-\u003e bloqueado) ($ esto-\u003e desbloqueo ();) devuelve verdadero;) FUNCIÓN PÚBLICA LEER ($ SESIONESIO DE SESIONADA) (¡SI (! $ ESTA-\u003e Bloqueado) (¡Si (! $ esto-\u003e Locksession ($ sessionid)) (devolución falsa;)) devuelve $ esto-\u003e redis-\u003e getrediskey ($ sessionid))?: ";) Función pública Escribir ($ Sesión, $ DATA) (SI ($ esto-\u003e ttl\u003e 0) ($ esto-\u003e redis-\u003e SETEX ($ esto-\u003e getRediskey ($ sessioniD), $ esto-\u003e ttl, $ datos);) otra cosa ($ esta-\u003e redis-\u003e establecido ($ esto-\u003e getRediskey ($ sesiones), $ datos);) devuelve verdadero;) función pública destruir ($ sesiones) ($ esta-\u003e redis-\u003e del ($ esto-\u003e getrediskey ($ sessionid)); $ esto-\u003e Cerrar (); devuelve verdadero;) Función pública GC ($ Lifetime) (devuelve verdadero) Función pública SettTL ($ TTL) ($ ttl) ($ esta-\u003e ttl \u003d $ ttl;) Función pública Getlockmaxwait () (Devuelva $ esta-\u003e Lockmaxwait; ) FUNCIÓN PÚBLICA SETLOCKMAXWAIT ($ Lockmaxwait) ($ esto-\u003e lockmaxwait \u003d $ lockmaxwait;) Función protegida GetRedRediskey ($ Tecla) (vacío ($ esta-\u003e Prefijo)) (devolución de $). $ esto-\u003e Prefijo. Clave $; ) Función pública __destruct () ($ esto-\u003e cierre ();))

Conexión

$ redis \u003d nuevo redis (); Si ($ REDIS-\u003e Conecte ("11.111.111.11", 6379) && $ REDIS-\u003e Seleccione (0)) ($ Handler \u003d New Ufi \\ Redisessionhandler \\ RedIsessionhandler ($ Redis); session_set_save_handler ($ manejador);) session_start ();

Resultado

Después de conectar nuestra Maestría Nuestro script de prueba muestra con confianza 100 parámetros en la sesión. Al mismo tiempo, a pesar del bloqueo, el tiempo total de procesamiento de 100 solicitudes ha crecido ligeramente. En la práctica real, no habrá tal número de solicitudes simultáneas. Sin embargo, la operación del script suele ser más sustancial, y con consultas simultáneas puede haber notable esperando. Por lo tanto, debe pensar en reducir el tiempo de trabajar con la sesión del script (llamada session_start () Solo si es necesario trabajar con la sesión y session_write_close () Tras la finalización de trabajar con él)

Solicita al servidor sin reiniciar la página. Este es un método de bajo nivel que tiene una gran cantidad de configuraciones. Subída el trabajo de todos los demás métodos AJAX. Tiene dos usos:

url - Añadir solicitud.
ajustes - En este parámetro, puede configurar la configuración de esta solicitud. Establece el objeto en el formato (nombre: valor, nombre: valor ...). Ninguno de los ajustes es obligatorio. Puede configurar la configuración predeterminada utilizando el método $ .AJAXSETUP ().

Lista de ajustes

↓ Título: Tipo (valor por defecto)

Al ejecutar una consulta, los encabezados (encabezado) indican los tipos de contenido permitidos esperados del servidor. Los valores de estos tipos se tomarán del parámetro Acepta.

De forma predeterminada, todas las solicitudes sin reiniciar la página ocurren asíncrono (es decir, después de enviar una solicitud al servidor, la página no detiene su trabajo mientras espera una respuesta). Si necesita una ejecución síncrona de la consulta, configure el parámetro en FALSO. Las solicitudes y solicitudes de crossDomain como "JSONP" no se pueden realizar en modo síncrono.

Tenga en cuenta que la ejecución de las consultas en modo síncrono puede resultar en bloquear la página hasta que la solicitud se cumpla plenamente.

Este campo contiene una función que se llamará directamente antes de enviar una solicitud AJAX al servidor. Esta función puede ser útil para modificar el objeto JQxhR (en versiones tempranas Bibliotecas (hasta 1.5), en lugar de JQxhr usa XMLHTTTPRequest). Por ejemplo, puede cambiar / especificar los encabezados necesarios (encabezados) I.D. El objeto JQxhr se transmitirá a la primera función de argumento. El segundo argumento pasa la configuración de la consulta.

En este campo, puede especificar encabezados de consulta adicionales (encabezado). Estos cambios se ingresarán antes de la llamada antes de la atención, en la que se pueden realizar los editores finales.

Al transferir esta configuración a VERDADERO, la consulta se ejecutará con el estado "exitoso", solo si la respuesta del servidor difiere de la respuesta anterior. JQERY comprueba este hecho que se refiere al último encabezado modificado. Comenzando con jQuery-1.4, además de la última modificación y "ETAG" también se verifica (ambos son proporcionados por el servidor y son necesarios para notificar al navegador que los datos solicitados del servidor no se cambian de la solicitud anterior).

Le permite establecer el estado del origen de la página de ubicación (como si sucediera a través del protocolo de archivo), incluso si Jquery lo reconoció lo contrario. La biblioteca decide que la página se ejecuta localmente en el caso de los siguientes protocolos: archivo, * -exension y widget.

Se recomienda establecer el valor del parámetro. islocal A nivel mundial, utilizando la función $ .AJAXSETUP (), y no en la configuración de las solicitudes de AJAX individuales.

Especifica el nombre del parámetro que se agrega a la URL con una consulta JSONP (de forma predeterminada, "Callback" se usa - "http: //sitename.ru? Llamada de llamada \u003d ...").

A partir de JQery-1.5, especificando en este parámetro falso, evitará la adición a la URL parámetro adicional. En este caso, es necesario establecer explícitamente el valor de la propiedad JSONPCallback. Por ejemplo, esto es: (JSONP: Falso, JSONPCALLBACK: "CallbackName").

Define el nombre de la función que se llamará al responder al servidor en la solicitud JSONP. De forma predeterminada, JQERY genera un nombre arbitrario de esta función, que es una opción más preferida que simplifica el funcionamiento de la biblioteca. Una de las razones en las que es para especificar su propia función de procesamiento de consultas JSONP es mejorar el almacenamiento en caché de obtener solicitudes.

Comenzando con JQery-1.5, puede especificar una función en este parámetro para procesar la respuesta del servidor usted mismo. En este caso, la función especificada debe devolver los datos recibidos desde el servidor (en la función especificada, estarán disponibles en el primer parámetro).

De forma predeterminada, todos los datos transmitidos al servidor se convierten previamente a la cadena (Formato URL: FNAME1 \u003d VALUE1 y FNAME2 \u003d VALOR2 & ...) La "aplicación / x-www-formulte-urlenced" correspondiente. Si necesita enviar datos que no se pueden someter a un procesamiento similar (por ejemplo, DOM DOCUMENT), debe deshabilitar la opción ProcessData.

Este parámetro se usa para los tipos de tipo AJAX de dominio cruzado, el tipo de datos puede ser o "jsonp" o "script". Especifica la codificación en la que se realizará una consulta cruzada. Esto es necesario, si el servidor en el dominio de otra persona usa una codificación que no sea la codificación en un servidor de dominio nativo.

(Esta configuración apareció en jquery-1.5) Un conjunto de vapor, en el que los códigos de ejecución de la consulta se comparan con las funciones que se causarán. Por ejemplo, para el código 404 (no existe), puede dibujar un mensaje a la pantalla:

$ .AJAX (estadoCode: (404: Función () (alerta ( "Página no encontrada") ; } } } ) ;

Las funciones que responden a un exitoso códigos de consulta recibirán los mismos argumentos que las funciones de una ejecución exitosa de la consulta (especificada en el parámetro de éxito), y las funciones que funcionan en los códigos de error serán las mismas que las funciones de error.

La función que se llamará en el caso de una finalización exitosa de la solicitud del servidor. Se transmitirán tres parámetros: los datos enviados por el servidor y ya han pasado el procesamiento preliminar (que es excelente para diferentes tipos de datos). El segundo parámetro es una cadena con estado de ejecución. El tercer parámetro contiene el objeto JQxhr (en versiones anteriores de la biblioteca (hasta 1.5), en lugar de JQxhr utiliza XMLHTTPRequest). Comenzando con JQery-1.5, en lugar de una sola función, este parámetro puede tomar una serie de funciones.

Tiempo para tener una respuesta del servidor. Ubicado en milisegundos. Si se excede este tiempo, la consulta se completará con un error y se producirá el evento de error (consulte la descripción anterior), que tendrá el estado "Tiempo de espera".

El tiempo está contando desde el momento de llamar a la función $ .AJAX. Puede suceder que en este momento se iniciarán varias otras solicitudes y el navegador pospondrá la ejecución de la solicitud actual. En este caso se acabó el tiempo. Puede terminar, aunque de hecho, la solicitud aún no se ha lanzado.

En jquery-1.4 y más joven, al final del tiempo de espera, el objeto XMLHTTPRequest cambiará al estado de error y el acceso a sus campos puede causar una excepción. EN Firefox 3.0+ Las consultas del tipo Script y Jsonp no se interrumpirán cuando se exceda el tiempo de espera. Se completarán incluso después de que expirará este tiempo.

Una función que proporcionará un objeto XMLHTTPRequest. De forma predeterminada, los navegadores de IE, este objeto es ActiveXObject, y en otros casos es XMLHTTPRequest. Con este parámetro, puede implementar su propia versión de este objeto.

(Esta configuración apareció en jquery-1.5.1) Un conjunto de pares (nombre: letrero) para cambiar / agregar los valores de los campos correspondientes del objeto XMLHTTPRequest. Por ejemplo, puede configurar su propiedad WithCredentials en VERDADERO, al realizar una consulta cruzada:

$ .AJAX ((URL: A_CROSS_DOMAIN_URL, XHRIELFIES: (conCredentials: verdadero));

EN jquery-1.5 La propiedad de Withcredentials no es compatible con el XMLHTTPRequest nativo y con una consulta CrossDomen, este campo será ignorado. En todas las siguientes versiones de la biblioteca, se fija.

Manejadores de eventos

BeForesert, error, DataFilter, éxito y configuración completa (su descripción en la sección anterior) le permite establecer controladores de eventos que ocurran en ciertos puntos en la ejecución de cada consulta AJAX.

apariencia. Sucede inmediatamente antes de enviar una solicitud al servidor. error Sucede en caso de ejecución fallida de la consulta. filtro de datos. sucede en el momento de llegar a los datos del servidor. Le permite manejar los datos "RAW" enviados por el servidor. Éxito. Ocurre en el caso de una finalización exitosa de la solicitud. completo. sucede en el caso de cualquier finalización de la solicitud.

Ejemplo uso simple. Vamos a retirar el mensaje con una exitosa ejecución de consultas:

$ .AJAX ((URL: "AJAX / TEST.HTML", éxito: Función () (Alerta ("Se realizó la carga");));

Comenzando con JQuery-1.5, el método de $ .ajAX () devuelve el objeto JQxhr, que, entre otras cosas, implementa la interfaz diferida, que le permite establecer manipuladores de ejecución adicionales. Además de la norma .done (), .fail () i.then () Los métodos para diferidos (), con los que puede instalar los manipuladores, se implementan en JQxhr.Success (), .Error () y.Comet () . Esto se hace para cumplir con los nombres habituales de los métodos con los que se establecen los manejadores de la ejecución de las consultas AJAX. Sin embargo, comenzando con JQery-1.8, estos tres métodos serán no deseado para su uso.

Para algunos tipos de consultas, como JSONP o Cross CrossMains, obtengan consultas, no se proporciona para usar los objetos XMLHTTPRequest. En este caso, se transmitirá a los manipuladores XMLHTTTPRequest y TextStatus contendrán un valor indefinido.

Instalaciones interiores, esta variable contendrá el valor del parámetro contexto.. En caso de que no se haya especificado, esto contendrá un objeto de configuración.

Tipo de datos

La función $ .AJAX () se encontrará con el tipo de servidor de datos enviado desde el propio servidor (MIME Herramientas). Además, es posible especificar (aclarar) personalmente cómo interpretar estos datos. Esto se hace utilizando el parámetro DataType. Posibles valores de este parámetro:

"XML" - El documento XML resultante estará disponible en el formulario de texto. Puedes trabajar con él medios estándar jQuery (así como con el documento HTML). "HTML" - El HTML recibido estará disponible en el formulario de texto. Si contiene scripts en etiquetas



En este ejemplo utilizando el método jQuery. .carga () Nos presionamos en el elemento.

¿Te gustó el artículo? Compártelo