Vuelva a usar la conexión HTTP autenticada o el identificador cUrl

4

Tenemos un complemento de Wordpress a medida, que agrega un cuadro de meta a la página de publicación de edición. El complemento accede a los datos desde una API REST HTTP semiprivada.

La conexión se autentica (DIGEST) y se accede a ella regularmente: todas las personas que escriben una publicación interactuarán con ella varias veces (generalmente en ráfagas ajustadas) y hay > 100 personas así. Por lo tanto, nos gustaría asegurarnos de que las llamadas HTTP estén funcionando de manera eficiente. Vemos dos problemas:

  • No hay evidencia de que se esté utilizando Keep-Alive para detener la apertura del socket TCP y cerrando constantemente.
  • Cada solicitud se realiza dos veces para la autenticación DIGEST. Dado que es el complemento que se autentica (no el usuario), este es > 99% de residuos. Apache ha llamado a su solución para esto autenticación preventiva .

Podemos ver la latencia en el cuadro meta cuando los usuarios interactúan con él, por lo que este es un problema real.

Escuché que algunos de estos problemas se pueden resolver reutilizando el controlador cURL, pero no puedo encontrar ningún consejo de mejores prácticas para implementar eso en un complemento de WordPress específicamente. Un problema que tenemos con eso es que WordPRess reinicializa efectivamente el complemento por solicitud, por lo que podemos decir.

    
pregunta Simon Gibbs 16.01.2013 - 11:16

2 respuestas

2

No es posible, al menos no dentro de lo razonable, resolver ninguno de estos problemas debido a limitaciones fundamentales de PHP en un entorno web (mod_php).

Las variables de clase no persisten entre las solicitudes web, por lo que la parte Keep-Alive del problema no puede solucionarse porque todos los recursos (es decir, el identificador de curl, el socket tcp) se destruirán al final de la solicitud. Reutilizar el controlador cUrl parece ser mayormente relevante para los scripts de proceso por lotes o el raro script web que necesita acceder a varias URL de una sola vez. El tipo de optimizaciones de rendimiento consideradas estándar para los desarrolladores de Java por lo tanto no están disponibles para los desarrolladores de PHP.

Uno podría tratar de implementar la autenticación de resumen al pegar los valores del encabezado de Autorización en la sesión, pero no es barato de implementar (tiempo de desarrollo alto) y no es algo a lo que muchas empresas quieran dedicar tiempo. Este podría ser un buen proyecto universitario de tercer año, por ejemplo.

Con suerte, en algún momento, alguien lanzará un producto complementario para PHP en Apache que de alguna manera canaliza las solicitudes HTTP a través de un grupo de conexión TCP externo al proceso. Eso probablemente ganaría dinero, ya que eliminará una gran cantidad de latencia de las solicitudes HTTP ascendentes de PHP.

    
respondido por el Simon Gibbs 23.01.2013 - 12:47
2

Inspeccionando la solicitud cURL

Incluso si inspeccionar y depurar una solicitud de cURL no es algo exclusivo de WordPress, necesita conocer una buena parte de los elementos internos de la API HTTP de WP para evitarlo. Me he escrito un complemento para hacer eso por mí, que he modificado / simplificado y adjuntado para que lo use. Se mostrarán los detalles del objeto cURL en el gancho de apagado, tanto en la IU de administración como en el Front-End / Theme.

Lo que puedes hacer es usar exactamente el mismo gancho http_api_curl y capturar el objeto cURL. Luego guárdelo en una variable de clase, adjunte sus próximas llamadas y continúe. No he hecho nada como esto antes, pero debería ser factible.

Editar

  

Como el número de ediciones aquí es limitado, trasladé el desarrollo adicional de este complemento a mi cuenta de GitHub . Si tiene notas, comentarios o sugerencias, deje un comentario allí.

El complemento a continuación es completamente funcional. Todavía hay una versión mucho más avanzada en GitHub.

<?php
/** 
 * Plugin Name: (#81791) Dump cURL Request & Response 
 * Author:      Franz Josef Kaiser
 */
add_action( 'plugins_loaded', array( 'WPSE81791_cURL', 'init' ) );
class WPSE81791_cURL
{
    protected static $instance;

    public static $dump;

    public static function init()
    {
        null === self :: $instance AND self :: $instance = new self;
        return self :: $instance;
    }

    public function __construct()
    {
        add_action( 'http_api_curl', array( $this, 'dump_curl' ) );
        add_action( 'shutdown', array( $this, 'do_dump' ) );
    }

    /**
     * Debug the response in the middle.
     * Catches the cURL object during the request.
     * @param  cURL $handle
     * @return void
     */
    public function dump_curl( &$handle )
    {
        curl_setopt( $handle, CURLINFO_HEADER_OUT, 1 );
        curl_setopt( $handle, CURLOPT_HEADER, 0 );
        curl_setopt( $handle, CURLOPT_HEADERFUNCTION, array( $this, 'dump_curl_buffer_cb' ) );
        curl_setopt( $handle, CURLOPT_WRITEFUNCTION, array( $this, 'dump_curl_buffer_cb' ) );
        curl_exec( $handle );
        $this->add_dump(
             curl_getinfo( $handle, CURLINFO_HEADER_OUT )
            .$this->dump_curl_buffer_cb( null )
            .'<br />Nr. of Errors: '.curl_errno( $handle )
            .'<br />Errors: '.curl_error( $handle )
        );
    }

    /**
     * Callback for cURL dump method
     * @param  object $curl
     * @param  null   $data
     * @return int
     */
    public function dump_curl_buffer_cb( $curl, $data = null )
    {
        static $buffer = '';
        if ( is_null( $curl ) )
        {
            $r = $buffer;
            $buffer = '';
            return $r;
        }
        $buffer .= $data;
        return strlen( $data );
    }

    /**
     * Adds data to the static data stack
     * @param  
     * @return void
     */
    public function add_dump( $data )
    {
        self :: $dump[] = $data;
    }

    /**
     * Dumps the data stack for debug
     * @param  
     * @return void
     */
    public function do_dump()
    {
        printf(
             '<pre>%s</pre>'
            ,var_export( implode( "<br />", self :: $dump ), true ) 
        );
    }
}
    
respondido por el kaiser 22.01.2013 - 21:43

Lea otras preguntas en las etiquetas