Tratar con la pérdida de conectividad
Una vez completada una llamada RPC, la conexión no está cerrada; está marcado como libre. Por lo tanto, el servidor puede dejar de funcionar o se puede perder la conectividad de red durante o entre llamadas, mientras que una conexión se encuentra en el grupo. Como cuestión de la directiva, el tiempo de ejecución de RPC vuelve a intentar esas llamadas solo si se cumplen las dos condiciones siguientes:
- El servidor no puede ejecutar la llamada o la llamada es idempotente.
- El cliente puede implementar reintentos de forma eficaz en el rendimiento.
Los párrafos siguientes se expanden y aclaran las dos condiciones.
Una llamada idempotente es una llamada que se puede ejecutar más de una vez en el servidor sin efectos secundarios no deseados. Por ejemplo, tener una llamada RPC que consulta el saldo en el banco para una cuenta determinada es idempotente. Si esta llamada se ejecuta dos veces debido a la pérdida de conectividad, no se produce ningún daño. Otro ejemplo de una llamada idempotente es cambiar la dirección de un cliente en una base de datos. La ejecución dos veces es correcta, ya que la segunda ejecución simplemente reemplaza la dirección ya actual por la misma dirección. Una operación como "restar cincuenta dólares de la cuenta xyz" no es idempotente. La pérdida de conectividad de red no debería dar lugar a varias ejecuciones de dicha llamada.
Para ser seguro, el tiempo de ejecución de RPC trata todas las llamadas como no idempotentes. El atributo [idempotent] no se admite para ncacn_ip_tcp y se omite. Por lo tanto, la primera condición de la lista anterior se reduce al servidor que posiblemente no puede ejecutar la llamada.
En muchos casos, el tiempo de ejecución de RPC no puede determinar de forma concluyente que la llamada no se ejecutó aún en el servidor. En tales casos, el cliente no volverá a intentar ejecutar la llamada.
Los ejemplos siguientes muestran cuándo el tiempo de ejecución de RPC realiza o no vuelve a intentar una llamada:
Se reinicia un servidor.
Se realiza una llamada RPC simple y sin seguridad en una interfaz en la que no se ha realizado ninguna llamada anterior después del reinicio. Puesto que no se realizaron llamadas en esta interfaz, el tiempo de ejecución de RPC intenta negociar el uso de la interfaz. Envía un paquete mediante una conexión en el grupo. Puesto que se ha reiniciado el servidor y la conexión ya no es válida, devuelve un error. Dado que el tiempo de ejecución de RPC del lado cliente aún no ha empezado a enviar los datos para la llamada real, el cliente determina que el servidor no se pudo haber ejecutado en esos datos. Por lo tanto, cierra la conexión y busca otra conexión en el grupo. Si no encuentra una conexión, abre una nueva conexión e intenta negociar de nuevo el uso de la interfaz. Si esto se realiza correctamente, se realiza la llamada (es decir, se realiza un reintento, porque se detectó el error antes de que se iniciara la llamada).
Una llamada RPC con seguridad de nivel de privacidad (cifrado) se realiza en una conexión con un contexto de seguridad ya negociado.
Para garantizar un rendimiento eficaz, el tiempo de ejecución de RPC cifra el paquete serializado insertado (sobre los datos de texto no cifrado). Si se produce un error en el intento de enviar los datos, el tiempo de ejecución de RPC no puede reintentar la llamada, ya que los datos de texto no cifrado se han sobrescrito con los datos cifrados y no pueden volver a cifrar los datos con un nuevo contexto de seguridad. Por lo tanto, no se realiza ningún reintento.
Se produce un error en el envío de un fragmento que no es el primero.
No se realiza el reintento, ya que el tiempo de ejecución de RPC puede optar por descartar el contenido del primer fragmento una vez completado y no tiene forma de reintentar el envío del primer fragmento.
Se envía la solicitud RPC.
El servidor anula la conexión. No se intenta reintentar, ya que RPC no puede distinguir si el servidor recibió la llamada y comenzó a ejecutarla.
Si el servidor usa un punto de conexión dinámico, RPC no volverá a resolver el punto de conexión durante los reintentos. Esto significa que si se desactiva un servidor y vuelve a funcionar, puede residir en un punto de conexión diferente y RPC no volverá a resolver de forma transparente el punto de conexión cuando se vuelva a intentar una llamada. Para forzar la reestablección del punto de conexión, el cliente RPC debe llamar a RpcBindingReset antes de reintentar una llamada.
En muchos de estos casos, si un cliente RPC puede determinar si una llamada es idempotente o si mantiene los datos descartados por RPC, puede optar por crear un mecanismo de reintento sobre RPC.
Nota
Si el servidor es un clúster y los distintos nodos del clúster ejecutan versiones diferentes del software de servidor, un reintento rpc puede llevar a cabo la llamada en un nodo diferente del clúster en el caso de la conmutación por error y potencialmente en una versión diferente del servidor. En estos escenarios de implementación, asegúrese de que el cliente no se basa en una versión determinada del software de servidor para ejecutar una llamada determinada. Si es así, el cliente debe crear un mecanismo sobre RPC que detecte y controle dichas condiciones.