versiones utiliza usos usar ultima realizadas que puedo programar programa por donde con aplicaciones c# architecture p2p

utiliza - usos de c#



Aplicaciones autoorganizativas (3)

Tengo los siguientes requisitos para una aplicación que muchas personas usarán en la oficina: ningún componente del servidor. Todas las instancias de aplicaciones cliente deberían negociar de alguna manera entre ellas mismas para decidir qué cliente asumirá el rol de servidor. Y los clientes deben comunicarse entre sí a través de IP.

Si y cuando la aplicación del cliente se cae, otro cliente debe asumir el control de manera transparente. Entiendo que tener un servidor sería mucho, mucho más simple. Pero debido a que la aplicación debe ser muy resistente, los poderes no deben arriesgarse a que el servidor se apague (o incluso su copia de seguridad) y confíen en esta conectividad de malla híbrida, donde la función del servidor salta de cliente a cliente.

Creo que tengo la conectividad de la aplicación hacia abajo. Básicamente, cuando se inicia la aplicación, se anuncia a sí mismo a través de UDP (ya sea a una dirección IP predefinida que todo escucha o a través de la transmisión UDP). De ahí en adelante, la comunicación procede de manera similar.

La parte con la que tengo problemas es cómo negociar / autoorganizarse entre los clientes para elegir uno con un rol de servidor. Y cómo detectar de forma fiable que un cliente se ha caído y luego debe realizarse una nueva negociación. La dificultad final es replicar los datos acumulados por el cliente con un rol de servidor.

Creé un prototipo en c # que se comunica e intenta replicar los datos, pero la parte de negociación (en particular, junto con una falla del cliente).

Inicialmente pensé que eso era lo que hacía ZeroConf (también conocido como Bonjour). Pero eso solo anuncia los servicios de red disponibles.

De todos modos, no quiero reinventar y no puedo ser la primera persona que quiera hacer esto. Así que mis preguntas:

  • ¿Hay algún patrón que ya implemente lo que describí anteriormente?
  • Si es así, ¿hay una biblioteca .NET disponible (o incluso nativa) para esto?
  • ¿Cuáles son las buenas maneras de negociar el rol del servidor entre los clientes?

¿Por qué necesitas negociar el rol del servidor? Piensa en esto por un segundo. Si cada "cliente" puede manejar los deberes del "servidor" para el trabajo iniciado en el cliente, entonces todos manejan el cliente y el servidor, hasta cierto punto. Entonces, el único problema es la negociación de la replicación del estado persistente entre clientes y el manejo de la concurrencia cuando dos clientes manejan el mismo bit de estado (la parte más difícil, desde mi perspectiva, sería alertar al estado de otros clientes que ha cambiado cuando un cliente "salva" Los datos y el hecho de que otros clientes trabajen en el estado abren un método para resolver los choques: puede que no sea un problema si el último en ganar siempre, pero eso es raro.

Si realmente va a hacer una malla, entonces cada cliente debería poder manejar su trabajo independientemente de los demás y solo comunicar los cambios al estado persistente para que las copias coincidan.

lo anterior asume que el número de veces que más de una persona usa el mismo estado al mismo tiempo es limitado. Si ese es el escenario normal, entonces tendrá que averiguar algo de la lógica de su "servidor".


La selección de un servidor entre un grupo de máquinas, ya sea que esas máquinas también sean clientes o no, es un problema extremadamente no trivial. Se llama elección líder. El trabajo seminal que debes leer es El Parlamento a tiempo parcial de Leslie Lamport, que describe el protocolo de Paxos. Google ha aprovechado Paxos para desarrollar un sistema llamado Chubby , que cumple el propósito que usted describe.

Dicho esto, probablemente debería considerar un sistema como Apache ZooKeeper , que es una implementación de código abierto (aunque Java) de una elección de líder distribuido, y más ampliamente, la administración distribuida de bloqueos que se ha probado exhaustivamente bajo una carga masiva. Hadoop distribuyó el almacenamiento de datos y la plataforma informática, y específicamente HBase , una base de datos distribuida que se ejecuta en Hadoop, hace un uso intensivo de ZooKeeper para decidir "quién está a cargo" entre un grupo de servidores. De esta manera, cualquiera de ellos puede caer, y los demás deciden entre ellos quién se hará cargo del trabajo.

Como mencioné anteriormente, la elección del líder está llena de errores. Es muy difícil hacerlo bien. He implementado paxos "por diversión" media docena de veces en C # y todas mis implementaciones tienen errores.


Por lo tanto, actualmente tiene un sistema en el que cada cliente en una LAN se anunciará a través del UDP al resto de la LAN. Una de las aplicaciones cliente es un "servidor" y tiene algunos poderes adicionales de comando y control además de ser un cliente en sí mismo.

Esto no es una idea nueva, para estar seguro. Lo que desea es agregar algunas conversaciones adicionales durante la comunicación de conexión inicial "aquí estoy". Cuando un nuevo cliente grita "aquí estoy" al resto de la LAN, si hay un servidor, el servidor debe decir "Bienvenido, yo soy el servidor", y la nueva aplicación de cliente ahora sabe qué cliente está actuando como el servidor. Todos los demás clientes probablemente deberían decir "hola" también. Si no hay un servidor, el nuevo cliente primero debe repetir el "hola" (después de todo, se trata de UDP; debe esperar que no se reciban algunos mensajes) y, si nadie responde, este nuevo cliente es el único en La red y es el "servidor" por defecto. Si hay otros pero ninguno afirma ser el servidor, los clientes pueden "discutir entre ellos" para determinar un nuevo servidor.

Además de esto, la copia del servidor debe gritar periódicamente (quizás cada 3-5 segundos) gritando "Todavía estoy aquí" para todos; Esto se conoce como un mensaje de "latido" y es una alternativa muy común al método de verificación "ping" de dos vías.

Si la aplicación del servidor (o cualquier copia, en realidad) se cierra normalmente, debería gritar "adiós a todos, averiguar quién es el siguiente servidor". Los clientes restantes pueden discutir entre ellos. Si el cliente que actúa como servidor falla, perderá el mensaje de "latido" del servidor, pregunte "quién es el servidor" y, si nadie responde, los clientes discutirán entre ellos.

Ahora, los clientes "discutiendo entre ellos" pueden ser tan simples o complejos como desee. Lo más simple sería que el cliente diga "OK, ahora soy servidor" para que se convierta en servidor. Es probable que tenga que incluir algún tipo de tiempo en el mensaje para que si otra computadora lo dice al mismo tiempo, los clientes puedan decir "el cliente 15 lo dijo primero, así que vamos con él". Los clientes pueden "votar"; haga que cada cliente hable con todos los demás para determinar la latencia nominal entre ese cliente y todos los demás, y ese cliente "votará" por la conexión de menor latencia (ningún cliente puede votar por sí mismo a menos que descubra que es la única). La mayoría de los votos gana.

O bien, un servidor puede, como parte de su mensaje de "latido", decir "si caigo, mi sucesor es el cliente X"; y si se pierde un latido del corazón y no se responde a los mensajes subsiguientes de "sigue en pie, servidor" de los clientes, los clientes pueden decir "¡el rey está muerto! ¡Viva King Client X!".

Comprenda que, por necesidad, esta capa de gobierno dentro de un sistema de todos los clientes al elegir un cliente "autorizado" para convertirse en el servidor aumentará dramáticamente la complejidad de las comunicaciones del cliente. Además, mientras que su uso del protocolo UDP se presta a una comunicación rápida, los mensajes UDP chocan TODO EL TIEMPO; Si estás hablando mientras otra persona está hablando, tus mensajes chocan. Por lo tanto, recomendaría el uso de TCP en lugar de UDP para la mayoría de las comunicaciones en este software en las que es necesario que se escuche a un cliente en particular. Eso es cualquier interrogatorio directo de un cliente ("¿sigue ahí, servidor?"), Sea cual sea el proceso que utilice para que los clientes decidan quién es un nuevo servidor, etc.