¿Debo analizar XML en el servidor o proporcionar un proxy y dejar que el navegador lo analice?

11

Necesito interactuar con una API de terceros. Con esta API hago una solicitud GET desde el navegador del usuario final y recibo una respuesta XML. Estos datos se utilizarán en una aplicación basada en navegador donde el usuario puede buscarlos, usarlos para tomar decisiones, etc. El problema principal es que la mayoría de los navegadores han bloqueado el uso de XML entre dominios, por lo que no puedo simplemente obtener El XML de la API.

Sin embargo, los datos generales se dividen básicamente en dos conjuntos.

  1. El primer conjunto de datos es público y solo necesita actualizarse de vez en cuando, por lo que puede almacenarse en caché para todos los usuarios en el lado del servidor, aligerando considerablemente el tráfico.
  2. El segundo conjunto de datos es privado e individual para cada usuario. Estos datos también se actualizan en la API con mayor frecuencia. Esto hace que el almacenamiento en caché sea mucho menos efectivo.

Por razones de escalabilidad, me gustaría mantener la carga del servidor lo más pequeña posible.

Veo dos opciones ante mí:

  1. Proporcione un proxy que se pueda usar para enrutar solicitudes XML al servidor de terceros y directamente de ida y vuelta entre el cliente y la API de terceros.
  2. Haga que el servidor realice la conversión de XML a JSON y elimine la información innecesaria. Esto esencialmente significa hacer una nueva API para nuestro servidor, que se traduce en solicitudes de la API de terceros

¿Cuál sería la mejor manera de proporcionar los datos al usuario? (No tiene que ser una de las dos opciones)

amatista
fuente
¿Cuál es la relación de la fuente XML con el código que la interpreta en el navegador? Porque si ha escrito su propio código de cliente (no compatible) para alimentarse de algunos datos de terceros, lo primero que pienso es que algún día ese tercero hará algún cambio menor en el XML y romperá su aplicación para siempre.
SJuan76
El tercero actualizó su versión de API una vez ya. Mantuvieron la versión anterior por un tiempo permitiendo a las personas actualizar su código para usar la nueva API. Sin embargo, la estructura de los datos en el XML no ha cambiado una vez definida, excepto entre las versiones de API.
amethystdragon
1
Si la API cambia con frecuencia, probablemente valga la pena declarar su propio esquema y tener un servicio que actúe como middleware, manipulando los datos en algo que su cliente espera. Creo que la pregunta se reduce a '¿Qué es más fácil, actualizar el cliente o actualizar el servidor?'
Hipérbole
No es frecuente Ha cambiado una vez durante 10 años.
amethystdragon

Respuestas:

12

La opción proxy es la más fácil de implementar. No tiene que hacer ningún desarrollo personalizado, lo único que debe hacer es configurar un proxy. También es sencillo: no hay código adicional que mantener, y si la API cambia, no tiene que hacer cambios de su lado.

Un proxy sería una opción preferida:

  • Si necesita enviar software de trabajo rápido. Esto lo convierte en una buena opción, por ejemplo, si estaba a punto de enviar una función, pero durante la fase de implementación del proyecto no puede hacer solicitudes AJAX entre dominios.

  • O si la API actual está bien diseñada : la arquitectura es buena, las llamadas son muy claras, la documentación es completa y fácil de entender.

  • O si la API actual está sujeta a cambios. Si cambia, solo necesita cambiar la implementación de JavaScript. Si en lugar de un proxy, está analizando los resultados y generando su propio JSON, existe el riesgo de que los cambios en la API requieran los cambios en el código del lado del servidor.

Por otro lado, analizar el resultado tiene un beneficio para permitir abstraer completamente la API en el lado del cliente. Esta es una alternativa más lenta, ya que requiere diseñar la nueva interfaz (si la API original no está bien diseñada) e implementar las características de extracción, transformación y carga, pero puede ser una buena opción a largo plazo para un proyecto grande. Esta es una opción preferida:

  • Si necesita funciones adicionales. Puede explotar las diferentes funciones que no estaban disponibles en la API original, como el almacenamiento en caché en un nivel que no es compatible con un servidor proxy ordinario, o el cifrado , o un modelo de autenticación diferente .

    Por ejemplo, si el número de solicitudes AJAX se convierte en un problema o si el modelo de comunicación bidireccional tiene sentido, puede implementar Web Sockets.

  • O si la API actual no está bien diseñada. Como un patrón de fachada, este enfoque le permite rediseñar la API. Si el original es pobre, tener una fachada permite resolver las malas elecciones de diseño hechas por los autores originales de una API heredada. Puede actuar también en partes grandes, como la arquitectura general de la API, pero también en detalles, como los nombres de los argumentos o los mensajes de error.

    Si bien la modificación de una API existente a veces es imposible, tener una fachada puede permitir trabajar con un código limpio que abstraiga los inconvenientes y errores en el diseño original.

  • O si la API actual está sujeta a cambios. De hecho, es posible que prefiera cambiar el código del lado del servidor en lugar de JavaScript si la API cambia con el tiempo, sin afectar la interfaz pública de su fachada. Puede ser más fácil porque tiene más experiencia con la programación del lado del servidor o porque conoce más herramientas para la refactorización del lado del servidor o porque es más fácil en su proyecto lidiar con el control de versiones del código del lado del servidor.

Puede notar que omití hablar de JSON, rendimiento, almacenamiento en caché, etc. Hay una razón para eso:

  • JSON vs. XML: depende de usted elegir la tecnología adecuada . Lo hace midiendo objetivamente el sobrecalentamiento de XML sobre JSON, el tiempo que lleva serializar datos y la facilidad de análisis.

  • Rendimiento: compara diferentes implementaciones, elige la más rápida, luego perfílala y optimízala según los resultados del generador de perfiles. Deténgase cuando logre el rendimiento especificado en los requisitos no funcionales.

    Además, entienda lo que está tratando de lograr. Hay varias partes que interactúan entre sí: la API original, el ancho de banda entre su servidor y el de la API, el rendimiento de su servidor, el ancho de banda entre su servidor y los usuarios finales y el rendimiento de sus máquinas. Si se le pide que obtenga una respuesta a una solicitud dentro de los 30 ms, pero la API original gasta 40 ms. procesando la solicitud, no importa lo que haga, no podrá obtener el rendimiento requerido.

  • Almacenamiento en caché : el almacenamiento en caché es una de las técnicas para hacer que su aplicación web se sienta más rápido, reduciendo el ancho de banda, etc.

    1. Asegúrese de utilizar también el almacenamiento en caché del cliente (el almacenamiento en caché del lado del servidor no reducirá el uso de ancho de banda entre usted y los clientes), dado que la configuración adecuada de los encabezados HTTP a menudo es difícil.

    2. Asegúrese de determinar correctamente qué almacenar en caché, durante cuánto tiempo y cuándo invalidarlo: si la descripción del producto cambió hace 10 segundos, pero los clientes de un sitio web de comercio electrónico aún ven la versión anterior, está bien. Si el propietario cambió la descripción, la envió y aún ve la variante anterior debido al almacenamiento en caché, esto es problemático.

    3. No se concentre solo en el almacenamiento en caché. La minificación, por ejemplo, también es importante. Reducir el número de solicitudes también puede ser beneficioso.

Arseni Mourzenko
fuente
1
+1 Dudé un poco sobre si debía o no mencionar el almacenamiento en caché y finalmente decidí no hacerlo. Todavía vale la pena mencionarlo, buen punto.
JensG
7

Hay una tercera opción que quizás no haya visto: Cross Origin Resource Sharing (CORS) .

El estándar CORS funciona al agregar nuevos encabezados HTTP que permiten a los servidores servir recursos a dominios de origen permitidos. Los navegadores admiten estos encabezados y respetan las restricciones que establecen.

Ejemplo : supongamos que su sitio es http://my-cool-site.com y tiene una API de terceros en el dominio http://third-party-site.com , a la que puede acceder a través de AJAX.

Y supongamos que una página que su servidor de my-cool-site.com realizó una solicitud a third-party-site.com. Normalmente, el navegador de los usuarios rechazará las llamadas AJAX a cualquier otro sitio que no sea su propio dominio / subdominio según la Política de seguridad del mismo origen . Pero si el navegador y el servidor de terceros son compatibles con CORS, suceden las siguientes cosas:

  • El navegador enviará el siguiente encabezado HTTP a third-party-site.com

    Origin: http://my-cool-site.com
  • Si el servidor de terceros acepta solicitudes de su dominio, responderá con el siguiente encabezado HTTP:

    Access-Control-Allow-Origin: http://my-cool-site.com
  • Para permitir todos los dominios, un servidor de terceros puede enviar este encabezado:

    Access-Control-Allow-Origin: *
  • Si su sitio no está permitido, el navegador arrojará un error.

Si el cliente tiene navegadores bastante modernos que admiten CORS , y su servidor de terceros también es compatible con CORS , definitivamente puede hacerlo con pequeños cambios en su código.

Encontré una buena explicación en CORS , en la que también encontrarás otra forma de hacer esto: JSONP . Pero JSONP requeriría una buena cantidad de cambios en su código.

Para realizar una solicitud CORS, simplemente use XMLHttpRequesten Firefox 3.5+, Safari 4+ y Chrome y XDomainRequestobjete en IE8 +. Cuando se utiliza un XMLHttpRequestobjeto, si el navegador ve que está intentando realizar una solicitud entre dominios, activará sin problemas el comportamiento de CORS.

Aquí hay una función de JavaScript que lo ayuda a crear un objeto CORS de navegador cruzado.

function createCORSRequest(method, url){
    var xhr = new XMLHttpRequest();
    if ("withCredentials" in xhr){
        // XHR has 'withCredentials' property only if it supports CORS
        xhr.open(method, url, true);
    } else if (typeof XDomainRequest != "undefined"){ // if IE use XDR
        xhr = new XDomainRequest();
        xhr.open(method, url);
    } else {
        xhr = null;
    }
    return xhr;
}

Como usted dice que "la mayoría de los navegadores han bloqueado el uso de XML entre dominios", supongo que su servidor externo podría no ser compatible con CORS. Entonces tienes que encontrar enfoques alternativos.


sampathsris
fuente
1
¿Podría intentar resumir el contenido en los enlaces? Los enlaces son propensos a la pudrición de enlace y por lo tanto no son la mejor forma de transmitir la información en SE :)
Ampt
Lamentablemente, el servidor de terceros no es compatible con CORS.
amethystdragon
4

Por razones de escalabilidad, me gustaría mantener la carga del servidor lo más pequeña posible

Creo que esto apunta más o menos a la respuesta. El hecho de proporcionar o no datos preprocesados ​​al cliente o no depende principalmente de:

  1. la diferencia con respecto al tráfico
  2. El impacto en el rendimiento del procesamiento
  3. El impacto de un formato de datos diferente en el cliente

Si el XML es comparativamente pequeño o solo hay unas pocas solicitudes, puede tener sentido simplemente reenviarlo al cliente y olvidarlo. Lo mismo es cierto cuando los datos preprocesados ​​siguen siendo una gran parte de los datos originales, o si el cliente no puede beneficiarse mucho de un formato de datos diferente (por ejemplo, JSON).

Sin embargo, si el cliente tiene dificultades para procesar un gran conjunto de datos XML, o si el cliente necesita solo una pequeña fracción de los datos XML originales, entonces puede tener sentido realizar un preprocesamiento en el lado del servidor.

Al final, es más fácil escalar un servidor que escalar un cliente / navegador o el ancho de banda disponible. Para ponerlo en una oración, depende de dónde esté el cuello de botella en el sistema.

JensG
fuente
+1, y suma: prueba el rendimiento en diferentes situaciones.
SeraM
0

Mi elección sería almacenar en caché y comprimir (desechar información innecesaria) y gzip resultados al navegador del cliente, su opción # 2 . Debido a que los navegadores no suelen ser CPU de gama alta y las líneas de red del servidor al navegador tienen una capacidad limitada. Estoy hablando de clientes móviles . Si no planea admitir clientes móviles, elija lo que sea más simple, por ejemplo, algunosGoogle:CORS proxy

xmojmr
fuente