Manejo de excepciones en un programa que necesita ejecutarse 24/7

13

He leído que solo debemos detectar las excepciones que se pueden manejar, lo que hace que la captura de la clase de excepción base (C # en este caso) sea una mala idea (además de otras razones). Actualmente formo parte de un proyecto en el que aún no he visto nada más que la excepción base que se está capturando. Mencioné que se considera una mala práctica hacerlo, pero la respuesta fue "Este servicio debe ejecutarse 24/7, así es como es.".

Como no tuve una buena respuesta sobre cómo manejar adecuadamente las excepciones en un programa que necesita ejecutarse 24/7, ahora estoy aquí. No he logrado encontrar ninguna información / sugerencia sobre cómo manejar el manejo de excepciones en programas / servicios "críticos" que deben ejecutarse las 24 horas del día (y en este caso creo que puede estar bien si el servicio no funciona durante un minuto). o dos, por lo que ni siquiera son críticos). Entiendo que depende de la naturaleza exacta del programa. Los requisitos para un programa que puede causar problemas que amenazan la vida son bastante diferentes en comparación con un escáner de registro para un juego en línea.

Dos ejemplos:

1: un servicio de escritura anticipada para clientes de los ferrocarriles británicos, que se utiliza cuando buscan estaciones de ferrocarril en línea.

2: un programa que controla automáticamente los interruptores ferroviarios para los ferrocarriles anteriores en función de la información en tiempo real proporcionada por varios sensores en las vías, trenes, etc.

El primer programa probablemente no causaría un problema importante si se fallara por un minuto o dos, mientras que este último podría causar víctimas humanas. ¿Sugerencias sobre cómo tratar con cada uno? ¿Puntero a donde puedo encontrar más información y pensamientos sobre este tema?

    
pregunta user1323245 22.01.2014 - 09:09

5 respuestas

6

Ciertas funciones de lenguaje como

  • Recolección de basura
  • Sistemas de excepción
  • Evaluación perezosa

generalmente no son útiles en un sistema en tiempo real. Probablemente debería elegir un idioma sin estas funciones e intentar probar ciertas propiedades como el uso máximo de memoria o el tiempo de respuesta máximo.

Cuando un programa necesita ejecutarse continuamente, pero se aceptan fallas cortas y no globales, entonces podríamos usar una estrategia similar a Erlang. Erlang es un lenguaje de programación concurrente y funcional. Generalmente, un programa escrito en Erlang consistirá en múltiples procesos de trabajo que pueden comunicarse entre sí (modelo de actor). Si un subproceso de trabajo encuentra una excepción, se reinicia. Si bien esto implica un corto tiempo de inactividad, los otros actores pueden continuar como de costumbre.

Para resumir esto: en un programa robusto, varias partes están aisladas unas de otras y se pueden reiniciar o escalar de forma independiente.

Básicamente, necesitamos un código equivalente a este:

while (true) {
  try {
    DoWork();
  }
  catch (Exception e) {
    log(e);
  }
}

más una forma de terminar el bucle. Un bucle de este tipo impulsaría cada subproceso de trabajador.

Un problema con ignorar los errores a través de un catch-all es que la causa del error podría haber violado las invariantes de su programa y que las operaciones posteriores podrían ser inútiles. Una buena solución para esto es no compartir datos entre trabajadores independientes. Reiniciar un trabajador reconstruirá todos los invariantes necesarios. Esto significa que deben comunicarse de manera diferente, por ejemplo, a través de mensajes enviados. El estado de un actor puede no ser parte de las invariantes de otros actores.

Otro problema con la captura de demasiadas excepciones es que no todas las excepciones se pueden corregir al reiniciar, incluso cuando se toman tales precauciones. De lo contrario, los problemas difíciles como quedarse sin memoria pueden ser manejados al reiniciar. Pero un reinicio no le ayudará a recuperar la conectividad a Internet cuando se extrajo un cable físico.

    
respondido por el amon 22.01.2014 - 09:43
2

Para responder a su pregunta, uno tiene que entender qué son las excepciones y cómo funcionan.

Las excepciones generalmente se lanzan cuando ocurren tales errores, donde se requiere la asistencia del usuario. En tales casos, no importa cuánto tiempo lleve desenrollar la pila y manejar la excepción.

Sin manipuladores de captura, el programa detiene la ejecución. Dependiendo de su configuración y requisitos, puede ser aceptable.

En sus casos específicos:

  1. si la consulta no se puede ejecutar (por ejemplo, un nombre de ciudad incorrecto), informe al usuario del error y pida que lo corrijan.
  2. Si no obtiene información de un sensor crítico, no tiene mucho sentido continuar sin pedirle al operador que solucione el problema.

Eso significa que en ambos casos puede tener sentido usar excepciones, con más cuidado en un programa de RT para indicar solo problemas serios donde no es posible continuar la ejecución.

    
respondido por el BЈовић 22.01.2014 - 11:27
1
  

Hasta ahora no he visto nada, pero se ha detectado la excepción base.

Parece que hay un problema aquí, en la medida en que las excepciones no se tratan adecuadamente. La captura de excepciones en el punto apropiado y la toma de las medidas apropiadas (según el tipo de excepción) mantendrán el servicio en funcionamiento de una manera mucho más confiable.

Si el servicio debe continuar, es de suponer que es importante que funcione según lo previsto. Teniendo en cuenta su ejemplo, si un programa que controla interruptores ferroviarios lanza una excepción, puede indicar que hay un problema de comunicación con sensores relacionados con la seguridad. Si detecta la excepción base y continúa, es posible que el servicio se ejecute, pero puede que no funcione según lo previsto para el desastre.

Alternativamente, si detecta la excepción lanzada cuando hay una falla de comunicación con el sensor y la trata adecuadamente (es decir, detenga los trenes en el área afectada), su servicio está funcionando y usted no ha matado a nadie.

Por lo tanto, según entiendo la pregunta, sugeriría que, en primer lugar, buscaría agregar un manejo de excepciones más específico en lugar de eliminar los controladores de tipo de excepción base.

    
respondido por el Matthew Swain 27.01.2014 - 21:31
0

Con respecto al punto 2: no utilice C #. No es un lenguaje en tiempo real y usted se se lastimará si intenta usarlo como tal.

Para el punto 1: puedes ir por el camino del erlang: dejar que se bloquee, luego reiniciar

    
respondido por el miniBill 22.01.2014 - 09:30
0

Declaimer: estos son solo pensamientos, no tengo la experiencia.

Supongo que un programa que cumpla con los requisitos del segundo ejemplo debería ser extremadamente modular . En consecuencia, los módulos podrán reiniciarse, sin desestabilizar el sistema.

Por ejemplo, un objeto, en su defecto para un estado interno, debe poder ser destruido y recreado, notificando en el proceso a todos sus consumidores y proveedores. Más concretamente, si el programa está controlando los interruptores del ferrocarril y falla un asalto en el bucle de decisión, aún puede ejecutar un módulo de emergencia, que detiene a todos los trenes involucrados, y espera a que se reinicie el módulo de decisión principal. p>

Más realista, se introduciría redundancia : duplicación del hardware y software. Una instancia está conectada al sistema controlado y la otra es de ejecución libre. Si se detecta un error, los sistemas se cambian.

Un ejemplo son dos procesos en la misma máquina, que se controlan entre sí y, si uno muere, el otro lo reaparece y desasocia su PID principal.

    
respondido por el Vorac 22.01.2014 - 09:53

Lea otras preguntas en las etiquetas