tutorial servicio redes protocolos protocol los example crear comunicacion caracteristicas delphi protocols notifications soap-client

delphi - servicio - ¿Qué protocolo de red usar para notificaciones livianas de aplicaciones remotas?



wsdl file (10)

Las notificaciones push para iPhone solo funcionan si sus dispositivos remotos son iPhones. Las únicas otras opciones son mantener una conexión abierta (aunque mayormente inactiva) o sondeo del cliente.

Es posible que pueda reducir la sobrecarga de la votación simplificando la llamada. Utilice una simple acción web para devolver el número de mensaje más alto al cliente y haga que el cliente realice un simple HTTP GET para recibir este número. Esto reduce la cantidad de ancho de banda y lo mantiene simple. Si luego el cliente necesita obtener datos actualizados, se puede hacer una llamada completa.

Tengo esta situación ... Comunicación SOAP 1.1 iniciada por el cliente entre un servidor y, digamos, decenas de miles de clientes. Los clientes son externos, ingresan a través de nuestro firewall, autenticados por certificado, https, etc. Pueden estar en cualquier lugar, y generalmente tienen sus propios firewalls, enrutadores NAT, etc. Son verdaderamente externos, no solo oficinas corporativas remotas. Podrían estar en una red corporativa / campus, DSL / Cable, incluso acceso telefónico.

El cliente usa Delphi (2005 + correcciones SOAP de 2007), y el servidor es C #, pero desde un punto de vista de arquitectura / diseño, eso no debería importar.

Actualmente, los clientes envían nuevos datos al servidor y extraen datos nuevos del servidor en un ciclo de sondeo de 15 minutos. Actualmente, el servidor no envía datos: el cliente acierta con el método de "recuento de mensajes" para ver si hay datos nuevos que extraer. Si es 0, duerme durante otros 15 minutos y vuelve a verificar.

Estamos tratando de bajar eso a 7 segundos.

Si se tratara de una aplicación interna, con una o unas pocas docenas de clientes, escribiríamos un servicio de escucha cilent "oyente" y le enviaríamos datos. Pero dado que son externos, se sientan detrás de sus propios servidores de seguridad y, a veces, de redes privadas detrás de los enrutadores NAT, esto no es práctico.

Así que nos quedamos con las encuestas en un ciclo mucho más rápido. Los clientes de 10K, cada uno de los cuales verificará su número de mensajes cada 10 segundos, serán mensajes de 1000 / seg que en su mayoría solo desperdiciarán ancho de banda, servidor, cortafuegos y recursos de autentificación.

Así que estoy tratando de diseñar algo mejor que lo que equivaldría a un ataque de DoS autoinfligido.

No creo que sea práctico que el servidor envíe mensajes "soap" al cliente (push) ya que esto requeriría demasiada configuración en el extremo del cliente. Pero creo que hay alternativas que no conozco. Como:

1) ¿Hay alguna manera para que el cliente solicite GetMessageCount () a través de Soap 1.1 y obtenga la respuesta, y luego, quizás, "mantenerse en línea" durante quizás 5-10 minutos para obtener respuestas adicionales en caso de que haya nuevos datos llega? es decir, el servidor dice "0", luego un minuto después en respuesta a algún disparador SQL (el servidor es C # en el servidor Sql, por cierto), sabe que este cliente todavía está "en línea" y envía el conteo de mensajes actualizado de "5 "¿?"

2) ¿Hay algún otro protocolo que podamos usar para "hacer ping" al cliente, utilizando la información recopilada de su última solicitud GetMessageCount ()?

3) Ni siquiera sé. Supongo que estoy buscando algún protocolo mágico en el que el cliente pueda enviar una solicitud GetMessageCount (), que incluiría información para "oh por cierto, en caso de que la respuesta cambie en la próxima hora, haga ping en esta dirección ... ".

Además, supongo que cualquiera de estos esquemas de "mantener la línea abierta" tendría un gran impacto en el tamaño del servidor, ya que necesitaría mantener miles de conexiones abiertas simultáneamente. Eso también podría afectar los firewalls, creo.

¿Hay algo por el estilo así? ¿O estoy bastante atrapado en las encuestas?

TIA,
Chris

ACTUALIZACIÓN 30/4/2010:
Después de haber demostrado que tener una notificación de 7 segundos no es fácil ni económico, especialmente sin salirse del estándar corporativo de HTTPS / SOAP / Firewalls, probablemente vamos a lanzar una solución de dos fases. Phase1 hará que los clientes sondeen "a pedido" con GetMessageCount que se realiza a través de SOAP, nada de lujoso aquí. Habrá un botón de "actualización" para extraer nuevos datos (lo cual es razonable aquí, ya que el usuario generalmente tendrá motivos para sospechar que los nuevos datos están listos, es decir, simplemente cambiaron el color de la tela en el sistema en línea, para que sepan hacer clic ACTUALIZA antes de ver el manifiesto de envío en el escritorio, y ahora ve el color en la descripción.) (Esta NO es realmente una aplicación de ropa / moda, pero entiendes la idea). La idea de tener las dos AP siempre sincronizadas, con actualizaciones en tiempo real desde el host, aún está sobre la mesa, usando las tecnologías que se discuten aquí. Pero espero que sea lanzado para otro lanzamiento, ya que podemos entregar el 85% de la funcionalidad sin tener que hacer esto. Sin embargo, espero que podamos hacer una prueba de concepto y podamos demostrar que funcionará. Volveré y publicaré futuras actualizaciones. Gracias por la ayuda de todos en esto.


Echaré un vistazo a kbmMW

Posiblemente usaría un método similar a MS Exchange: conexión y autenticación a través de tcp / ip, luego notificación de actualizaciones desde el servidor al cliente a través de udp, luego el cliente recibe la solicitud udp y descarga la actualización a través de tcp / ip.

(Al menos así entiendo que funciona MS Exchange)


Las dos grandes partes en el desarrollo multinivel en Delphi son los desarrolladores de componentes4 (con su producto kbmMW descrito en la respuesta de Mark Robinson) y RemObjects con su producto RemObjects SDK (tienen un buen ejemplo que podría ser similar a lo que desea: notificaciones push) para iPhone ).

En su entorno complejo, el UDP multidifusión podría no cortarlo, pero desde una perspectiva general es inmejorable.

Si una conexión está abierta, se puede usar de forma bidireccional (esto también lo utilizan .NET remoting y WCF), pero tiene una sobrecarga adicional.

Necesitará encontrar un equilibrio entre mantener las conexiones activas (bloquear recursos) y crear nuevas conexiones (tiempo de cálculo de costos y latencia).

--jeroen


Cada vez que tenga un servidor y más de 10.000 clientes, y necesita obtener actualizaciones cada pocos segundos, se encontrará con problemas. Me gustaría obtener algunos servidores más y mantener a los clientes conectados en un hilo de fondo en el cliente que inicialmente se conecta y luego espera que lleguen los avisos del servidor con un mecanismo integrado de mantener activo.

Si está tratando de enviar desde el servidor a un cliente que no está actualmente conectado, entonces buena suerte si no tiene control sobre los entornos de los clientes. Me parece que te obligan a tener conexiones iniciadas por el cliente.


Considere la posibilidad de "reproducir" el protocolo HTTP un poco para obtener lo que desea mientras sigue pudiendo examinar todos los proxies y NAT y firewalls que uno podría tener en el lado del cliente.

Haga que cada cliente haga una simple solicitud HTTP para el recuento de mensajes de una manera que impida cualquier tipo de almacenamiento en caché (ejemplo: GET http://yourserver.org/getcount/nodeid/timeofday/sequence ). En la implementación del servidor del servidor HTTP, el retraso proporciona la respuesta si el "recuento" es el mismo que solía ser (es decir, no hay mensajes nuevos).

He hecho esto para una aplicación estilo Ajax que se ejecutaba en un navegador y se comportaba como una aplicación de chat, pero su solución puede ser incluso más rápida. Implementé las cosas del lado del servidor usando el servidor TIdHttp y eso me permitió retrasar la respuesta a las cosas del cliente simplemente con la función Sleep () en su hilo. Desde el lado del cliente parecía un servidor que a veces es muy lento para dar una respuesta.

Pseudocódigo para las cosas del lado del servidor:

function ClientHasMessages(ClientID:Integer; MaxWait:TDateTime):Boolean; var MaxTime:TDateTime; begin if ClientActuallyHasMessage(ClientID) then Result := True else begin MaxTime := Now + MaxWait; while Now < MaxTime do begin if ClientActuallyHasMessage(ClientID) then begin Result := True; Exit; end else Sleep(1000); end; Result := False; // TimeOut end; end;

La idea detrás de este código: se ejecuta en un hilo en su propio servidor, donde puede probar el recuento de mensajes, presumiblemente, a muy bajo costo:

  • No causa tráfico de red mientras espera.
  • No usa CPU mientras duerme.
  • Le permitirá al usuario conocer su mensaje muy rápidamente.
  • Permite al cliente controlar cuánto tiempo puede esperar (el cliente aumentará la cantidad de tiempo que el servidor puede retrasar la respuesta hasta que ya no reciba la respuesta, y luego retroceder un poco, de esa manera el protocolo se adapta a cualquier error de NAT enrutador que usa el cliente).
  • Puede salirse con largos períodos de ausencia de comunicaciones TCP / IP y aún así poder proporcionar la respuesta al instante. 30 segundos se hace fácilmente y para los clientes con buenos enrutadores NAT puede ser mucho más largo.

El tamaño inferior de esto serían los requisitos en el servidor, pero estoy tentado de decir que son factibles:

  • La implementación TCP / IP del servidor necesita rastrear un gran número de conexiones simultáneas (cada cliente tendrá una solicitud HTTP activa en todo momento). Mi máquina NAT de Linux está rastreando conexiones de 15K en este momento y está básicamente inactiva, por lo que podría funcionar.
  • El servidor tendría un hilo abierto para cada solicitud HTTP de cliente único, en todo momento: una vez más, el Servidor 2008 "Estación de trabajo" que estoy usando para escribir esto (gracias MSDN por permitirme hacer tales cosas escandalosas) tiene aproximadamente 1500 hilos activo y también está básicamente inactivo ...
  • Dependiendo de la tecnología que use para el código del lado del servidor, MEMORY podría ser el factor limitante.

Podría intentar hacer una llamada al servidor y esperar en el servidor durante un tiempo (¿1 minuto?) Hasta que tenga algunas actualizaciones. De esta forma, no necesita una conexión de servidor a cliente y obtiene resultados casi instantáneos para el cliente (si tiene actualizaciones en 1 minuto, finaliza la llamada de espera). Es relativamente fácil y ampliamente utilizado (?) Por las aplicaciones web (como Gmail: tiene una conexión en segundo plano como esta: si llega un nuevo correo electrónico, ¡lo verá instantáneamente en su bandeja de entrada!). Uso algo como esto (RemObjects):

function TLoggingViewService.GetMessageOrWait: TLogMessageArray; begin if (Session.Outputbuffer.Count > 0) or //or wait till new message (max 3s) Session.Outputbuffer.WaitForNewObject(3 * 1000) then //get all messages from list (without wait) Result := PeekMessage; end;

El punto negativo es: mantienes la conexión abierta por un tiempo relativamente largo (¿qué pasa si la conexión se pierde debido a wifi, etc.?) Y una "carga" de servidor alta (cada conexión tiene un hilo, se mantiene abierta: si tienes muchos clientes puedes obtener sin recursos).

Usamos RemObjects aquí, y usamos TCP + Binmessage que tiene una sobrecarga MUCHO menor que SOAP + HTTP y es realmente rápido. Entonces, si puedes usar eso, ¡realmente puedo recomendar eso! (en su caso, necesita Remobjects para Delphi y RemObjects para .Net). Solo use SOAP si necesita conectarse con terceros y solo use HTTP si lo necesita debido a internet / firewall. SOAP es bueno, pero tiene altos problemas de sobrecarga y rendimiento.

También puede usar una combinación de estos: una conexión TCP simple (RemObjects) (con poca sobrecarga) en un hilo de fondo, sondeando cada 10 segundos y esperando 5 segundos para nuevos datos.


Realicé pruebas de rendimiento en sistemas incluso más grandes que sus clientes de 10K, y cuando alcanza las cantidades mencionadas de solicitudes por segundo, es muy probable que enfrente problemas con Conexiones / seg., Conexiones abiertas simultáneas, cortafuegos cada vez más lentos, etc. (Casi igual problemas que podría enfrentar un rastreador de Torrent).

Si los clientes solo necesitan "preguntar si hay algo nuevo", el protocolo más ligero que es fácil de implementar es UDP, el siguiente más ligero sería TCP puro, ambos usando clientes Indy.

El protocolo en sí podría ser tan simple como enviar "Algo nuevo desde [aaaa-mm-dd hh: mm: ss]" al servidor, y responder con un número de 1 byte (256 respuestas posibles).

Con TCP, tendría el beneficio adicional de mantener abierta la "tubería" durante unos minutos, y puede enviar el mensaje "cualquier cosa nueva" cada x segundos. También con TCP, el servidor podría "enviar" información a la tubería (cliente (s)) cuando ocurra algo, dado que el cliente está verificando los datos en la tubería periódicamente.


Intentaría distribuir la carga tanto como fuera posible entre varios servidores. Para eso, haría lo siguiente:

  1. Los clientes se registran en su servicio para recibir notificaciones. Obtienen una identificación de sesión que es válida por una cantidad de tiempo determinada (15 minutos).
  2. Los servidores ejecutarán un control periódico sobre qué cliente registrado tiene un mensaje entrante y generarán una lista de dichos clientes (técnicamente, insertaría eso en una base de datos diferente en su DMZ).
  3. Ejecuta varios servidores de "notificaciones push" que siguen un protocolo muy, muy simple: obtienen una consulta URL que contiene la ID de la sesión y responde con una breve respuesta HTTP: ya sea una 404 o una 200 con una URL (firmada) del SOAP server to address para captar los mensajes. Para actuaciones adicionales, puede usar HTTP 1.1 y conexiones persistentes.
  4. El cliente agrupará estos servidores de notificación de inserción tantas veces como lo desee. Debido a que son muy simples y estrictamente de solo lectura, pueden responder consultas muy rápidamente y serán fáciles de escalar.
  5. Si el cliente recibe una respuesta 302, puede conectarse al servidor SOAP correcto (también puede usarlo para la distribución de carga si lo desea) y extraer los mensajes.

Tendrás que tener cuidado con la seguridad aquí. Primero, sugiero que NO use HTTPS para sus servidores de notificaciones automáticas. En su lugar, puede firmar el contenido de la respuesta con una clave de sesión intercambiada cuando el cliente solicitó notificaciones. El cliente es responsable de validar la respuesta. No olvide que debe firmar no solo el estado sino también la URL del servicio SOAP.

Es un poco complejo, pero al desvincular el estado y el tráfico real de mensajes, puede escalar su solución mucho más fácilmente. Además, no tendrá que pasar por la costosa negociación de SSL hasta que realmente desee intercambiar datos.


Utilizamos los "eventos" de RemObjects SDK para esto, pero esto puede no ser adecuado para usted porque

a: Solo funciona con el propio protocolo binario de RemObjects, no con SOAP (es decir, los clientes deben incorporar el código RO)

B: Básicamente es un enfoque de "mantener la línea abierta". así que la escalabilidad de los clientes de 10K es un problema potencial.

Probé algunas pruebas solo para ver qué tiene realmente el mantenimiento de enchufes 10K abiertos. Si todo lo que necesitas es un par de gigs de memoria adicional del servidor, va a ser una solución económica. Y debido a que el socket se abre desde el extremo del cliente, no debería causar problemas de firewall. Lo peor que puede hacer el firewall es cerrar el socket, por lo que su cliente debería volver a abrirlo cuando eso ocurra.


Algo un poco afuera en el jardín izquierdo.

¿Por qué se requiere la autenticación solo para obtener un indicador que indique que las actualizaciones están listas? ¿Por qué no tener una máquina fuera del firewall de autenticación ... o incluso en la nube ... que no hace más que manejar esas solicitudes ''es cualquier cosa disponible''? Luego, si hay algo disponible, haga que el cliente revise los aros para obtener los datos reales. Este servidor de solicitud podría hacer el recuento de 7 segundos del servidor real.

Ahora estamos hablando de muy pocos datos y muy poco tiempo de configuración para una simple ''bandera'' ni siquiera un conteo.

Todavía hay miles de solicitudes, pero miles de solicitudes con una sobrecarga mínima en comparación con la solicitud autenticada completa.