Foros del Web » Programación para mayores de 30 ;) » Java »

Deadlock implementando un protocolo en java

Estas en el tema de Deadlock implementando un protocolo en java en el foro de Java en Foros del Web. Buen día a todos. Desde hace tiempo he estado desarrollando lo que se conoce como un Broker del protocolo Mqtt. No es necesario conocer este ...
  #1 (permalink)  
Antiguo 08/09/2015, 21:11
Avatar de Instru  
Fecha de Ingreso: noviembre-2002
Ubicación: Mexico
Mensajes: 2.751
Antigüedad: 22 años, 1 mes
Puntos: 52
Deadlock implementando un protocolo en java

Buen día a todos.

Desde hace tiempo he estado desarrollando lo que se conoce como un Broker del protocolo Mqtt. No es necesario conocer este protocolo.

Mqtt es un protocolo de comunicación entre 2 dispositivos. Su forma de manejar los mensajes es a través de paquetes.
Mi problema se enfoca en 2 paquetes: publish y pubrec.
Un host manda un publish para enviar a otro host un mensaje. Y este otro host debe responder con un pubrec para acusar de recibido el primer publish. Si después de cierto tiempo no se recibe el pubrec se vuelve a enviar el publish.

En java yo implemento esto usando un par de colas concurrentes (ConcurrentLinkedQueue).

Cada vez que se hace una petición de enviar algún mensaje, se encola en la primer cola el publish o los publish que se quieren enviar.
Ahora, en la segunda cola se toma el publish que esta en la cabeza de la primer cola y se envía, pero no se quita de la cabeza de la segunda cola. De esta manera, si no recibimos respuesta, volvemos a enviar el paquete que esta en la cabeza de la segunda cola el cual será el publish que no obtuvo respuesta.

Una vez que llega pubrec, se quita el publish de la segunda cola(aqui en realidad, hay una serie mas de paquetes, pero por simplicidad los omito). Como la segunda cola terminó de trabajar, entonces se toma el siguiente publish de la primer cola.
En pocas palabras la primer cola es literalmente una fila, y la segunda cola es mas bien un buffer de trabajo.

El problema se da cuando 2 hosts quieren enviar un publish casi al mismo tiempo.
Lo que sucede es lo siguiente.
Host1 envía publish y host2 también. Ambos esperan pubrec para poder quitar el publishd e la cabeza. Host1 espera pubrec1 el cual no puede ser enviado porque host2 esta esperando pubrec2 para poder enviar pubrec1.

Por lo tanto los 2 hosts se bloquean intentando enviar publish de manera indefinida sin recibir nunca una respuesta.

Creo que es algo difícil de explicar, pero espero me haya dado a entender.
No se qué hacer para evitar este bloqueo y conserve el orden y todas las propiedades del protocolo mqtt.

Espero alguien pueda ayudarme.

Saludos
  #2 (permalink)  
Antiguo 09/09/2015, 00:42
Avatar de chuidiang
Colaborador
 
Fecha de Ingreso: octubre-2004
Mensajes: 3.774
Antigüedad: 20 años, 2 meses
Puntos: 454
Respuesta: Deadlock implementando un protocolo en java

Hola:

Habitualmente el envío y la recepción se suelen separar en dos hilos independientes, de esta forma, mientras el que recibe está bloqueado, se puede seguir enviando.

En tu caso, quizás se pueda solucionar si creas un hilo encargado de recibir mensajes de la comunicación que haga lo siguiente:

- si el mensaje es un mensaje pubrec, él mismo envía la respuesta.
- si recibe una respuesta, informa al hilo encargado de enviar de que ha llegado la respuesta.

Por otro lado, el hilo que envía, recoge de la cola, envía y se queda a la espera que de que el hilo receptor le avise, o pase el tiempo para reenviar. Si el hilo receptor le avisa, quita el mensaje de la cola y envía el siguiente.

Un detalle, al haber dos hilos que envían por el mismo sitio, debes sincronizar el envío synchronized(socket) {enviar} o el tipo de canal que tengas (si es udp quizás no haga falta).

Se bueno.
__________________
Apuntes Java
Wiki de Programación
  #3 (permalink)  
Antiguo 11/09/2015, 16:41
Avatar de Instru  
Fecha de Ingreso: noviembre-2002
Ubicación: Mexico
Mensajes: 2.751
Antigüedad: 22 años, 1 mes
Puntos: 52
Respuesta: Deadlock implementando un protocolo en java

Hola. Gracias por tu respuesta.

De hecho mi implementación maneja 2 hilas mas el hilo principal. Tal como dices, hay un hilo para el emisor y otro para el receptor. El hilo principal se encarga de obtener la entrada para enviarla.

Por otro lado, las estructuras concurrentes de java han sido de gran ayuda ya que estas implementan los bloqueos de manera eficiente.

Al final, tuve que cambiar un poco la idea. Lo que hice en esencia fue no bloquear el emisor. De esta manera, siempre se puede enviar lo que hay en la cola. Para revisar las respuestas utilice una estructura de datos que consistia en una combinación de tabla hash y una cola. Cada mensaje enviado que requiera respuesta se encola( para mantener el orden ). Y cuando llega la respuesta, se busca el mensaje encolado usando el hash y se quita de la cola.
Aparte, cada que vence un timer, se vuelve a encolar la cabeza de la cola-hash para intentar enviar de nuevo.

Suena complejo, pero hasta ahorita es lo que ha funcionado de maravilla.

Saludos

Etiquetas: protocolo
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 23:40.