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 soy parte de un proyecto en el que hasta ahora todavía no he visto nada más que la excepción base que se detecta. Mencioné que se considera una mala práctica hacerlo, pero la respuesta fue "Este servicio debe ejecutarse las 24 horas del día, los 7 días de la semana, 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 lidiar con el manejo de excepciones en programas / servicios "críticos" que deben ejecutarse durante todo el día (y en este caso creo que puede estar bien si el servicio está inactivo por un minuto o dos, así que ni siquiera es crítico). 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, utilizado cuando buscan en línea estaciones de ferrocarril.
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 cayera por un minuto o dos, mientras que el último podría causar bajas humanas. ¿Sugerencias sobre cómo lidiar con cada uno? ¿Apunta a dónde puedo encontrar más información y pensamientos sobre este tema?
fuente
catch Exception
. Eso no significa que su programa funcione , significa que las fallas permiten que el estado de la aplicación se corrompa mientras continúa ejecutándose, un lugar mucho más peligroso. Un estrelló programa podría ser desastroso, pero un programa que está en un estado no válido, pero todavía puede ser acciones que realizan activamente desastrosa.Respuestas:
Ciertas características del lenguaje como
generalmente no son útiles en un sistema en tiempo real. Probablemente deberíamos elegir un idioma sin estas características 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 las fallas cortas y no globales son aceptables, entonces podríamos usar una estrategia similar a Erlang. Erlang es un lenguaje de programación concurrente y funcional. Por lo general, 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 breve 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.
Entonces, básicamente, necesitamos un código equivalente a esto:
más una forma de terminar el ciclo. Tal bucle conduciría cada hilo de trabajo.
Un problema al ignorar los errores a través de un problema general es que los invariantes de su programa podrían haber sido violados por la causa del error, 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, mediante el envío de mensajes. 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 solucionar reiniciando, incluso cuando se toman esas precauciones. De lo contrario, los problemas difíciles como quedarse sin memoria se pueden manejar reiniciando. Pero un reinicio no lo ayudará a recuperar la conectividad a Internet cuando se desconectó un cable físico.
fuente
Para responder a su pregunta, uno tiene que entender qué son las excepciones y cómo funcionan.
Por lo general, se producen excepciones cuando se producen dichos 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 controladores de captura, el programa detiene la ejecución. Dependiendo de su configuración y requisitos, puede ser aceptable.
En tus casos específicos:
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.
fuente
Parece que hay un problema aquí, en la medida en que las excepciones no se tratan adecuadamente. Capturar excepciones en el punto apropiado y tomar las medidas apropiadas (dependiendo del tipo de excepción) mantendrá el servicio funcionando de una manera mucho más confiable.
Si el servicio debe continuar, presumiblemente es importante que funcione según lo previsto. Dado su ejemplo, si un programa que controla los interruptores ferroviarios arroja una excepción, puede indicar que hay un problema para comunicarse con los sensores relacionados con la seguridad. Si detecta la excepción base y continúa, el servicio puede ejecutarse, pero puede no funcionar como se esperaba y provocar un desastre.
Alternativamente, si detecta la excepción lanzada cuando hay una falla de comunicación con el sensor y la trata adecuadamente (es decir, detener los trenes en el área afectada), su servicio se está ejecutando y no ha matado a nadie.
Entonces, como entiendo la pregunta, sugeriría que, en primera instancia, sería mejor agregar un manejo de excepciones más específico en lugar de eliminar los manejadores de tipo base-excepción.
fuente
Con respecto al punto 2: no use C #. No es un lenguaje en tiempo real y que va a hacerse daño si se intenta utilizar como tal.
Para el punto 1: podría seguir el camino erlang: dejar que se bloquee, luego reiniciar
fuente
Declaimer: estos son solo pensamientos, no tengo la experiencia.
Supongo que un programa que satisfaga 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, al fallar una afirmación de estado interno, debería poder destruirse y volver a crearse, notificando en el proceso a todos sus consumidores y proveedores. Más concretamente, si el programa está controlando los interruptores del ferrocarril y falla una afirmación en el bucle de decisión, aún puede ejecutar un módulo de emergencia, que detiene todos los trenes involucrados y espera a que el módulo de decisión principal se reinicialice.
Más realista, uno 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 conmutan.
Un ejemplo son dos procesos en la misma máquina, que se monitorean uno al otro y si uno se mata, el otro lo vuelve a generar y disocia su PID padre de sí mismo.
fuente