Desarrollo de sistemas tolerantes a fallas

45
Sistemas Tolerantes a Fallas Agustín Ramos @MachinesAreUs

description

¿Cuánto cuesta a una organización cuando un sistema falla? ¿Cuál es el impacto de que todo un sistema esté fuera de operación por una falla inesperada? ¿Hay manera de crear sistemas que continúen funcionando aún cuando, por ejemplo, un proceso o sub-sistema muere o no está disponible? ¿Crees que todo esto se puede arreglar con un bloque “try-catch” bien colocado? En esta sesión platicaré sobre la importancia de crear sistemas robustos y tolerantes a fallas, explicando las propiedades básicas que un sistema debe cumplir para continuar funcionando aún en la presencia de errores inesperados. Presentaré también varios patrones de diseño con el código correspondiente para que comiences a introducir robustez y tolerancia a fallas a los sistemas con que trabajas. Semblanza del conferencista: Agustín Ramos es un profesional de desarrollo de software con más de 12 años de experiencia en la industria. Impulsor de la metáfora del artesano como un modelo de cómo debe ser nuestra profesión. Gusta de refactorizar diseños, código, ideas y equipos de desarrollo por igual. Actualmente su principal interés se enfoca en resolver los retos que presenta el desarrollo de sistemas altamente distribuidos y escalables.

Transcript of Desarrollo de sistemas tolerantes a fallas

Page 1: Desarrollo de sistemas tolerantes a fallas

Sistemas Tolerantes a Fallas

Agustín Ramos @MachinesAreUs

Page 2: Desarrollo de sistemas tolerantes a fallas

¿Cuál es el costo de una falla?

Page 3: Desarrollo de sistemas tolerantes a fallas

¿Cuál es el costo de una falla?

• Una pequeña molestia para algún usuario. !

• Una transacción (de negocio) no completada. • Datos inconsistentes.

!• No disponibilidad del sistema. O_o !

• Pérdida de un cliente. • O de muchos de ellos.

!• Muerte de una organización.

Page 4: Desarrollo de sistemas tolerantes a fallas

(Casi) Todos los sistemas son distribuidos

Page 5: Desarrollo de sistemas tolerantes a fallas

Las falacias de los sistemas distribuidos

1. La red es confiable. 2. La latencia es cero. 3. El ancho de banda es infinito. 4. La red es segura. 5. La topología no cambia. 6. Existe solo un administrador. 7. El costo del transporte es cero. 8. La red es homogénea.

Page 6: Desarrollo de sistemas tolerantes a fallas

Todos los sistemas fallan

Page 7: Desarrollo de sistemas tolerantes a fallas

http://www.ctlab.org/documents/How%20Complex%20Systems%20Fail.pdf

Page 8: Desarrollo de sistemas tolerantes a fallas

¿Cómo desarrollar sistemas tolerantes a fallas?

Page 9: Desarrollo de sistemas tolerantes a fallas

1. Aceptar: No puedes prevenir todas las fallas. 2. Evita los “puntos únicos de falla”. 3. Implementa mecanismos de detección de

errores. 4. Implementa corrección de errores.

• Si es posible y hace sentido. • e.g. patrón: Compensating Transactions ?

5. Contención de errores 1. Evita que se propaguen.

Page 10: Desarrollo de sistemas tolerantes a fallas

Consecuencias

Sistemas… • Creados de componentes pequeños,

independientes en tiempo de ejecución. • Distribuidos. • Con reintentos finitos. • Con respuestas apropiadas para casos de

falla.

Page 11: Desarrollo de sistemas tolerantes a fallas

Usa…

µ-Services

Page 12: Desarrollo de sistemas tolerantes a fallas

Patrones de Estabilidad

Page 13: Desarrollo de sistemas tolerantes a fallas
Page 14: Desarrollo de sistemas tolerantes a fallas

Patrón #1 Timeouts

Page 15: Desarrollo de sistemas tolerantes a fallas

Timeouts (1)

// Básico 1 myObject.wait(); // No uses esto por default myObject.wait(TIMEOUT); // Mejor usa esto !// Básico 2 myThread.join(); // No uses esto por default myThread.join(TIMEOUT); // Mejor usa esto

Page 16: Desarrollo de sistemas tolerantes a fallas

Timeouts (2)

// Utilizando el API de concurrencia de Java

<MyActionResult> myAction = <My Blocking Action>

ExecutorService executor = Executors.newSingleThreadExecutor(); Future<MyActionResult> future = executor.submit(myAction); MyActionResult result = null; try { result = future.get(); // No uses esto por default result = future.get(TIMEOUT, TIMEUNIT); // Mejor usa esto } catch (TimeoutException e) { // Si ocurre el timeout ... } catch (...) { ... }

Page 17: Desarrollo de sistemas tolerantes a fallas

Timeouts (3)

// Utilizando el SimpleTimeLimiter de Guava

Callable<MyActionResult> myAction = <My Blocking Action>

SimpleTimeLimiter limiter = new SimpleTimeLimiter(); MyActionResult result = null; try { result = limiter.callWithTimeout(myAction,

TIMEOUT, TIMEUNIT, false);

} catch (UncheckedTimeoutException e) { ... } catch (...) { ... }

Page 18: Desarrollo de sistemas tolerantes a fallas

Patrón #2 Circuit Breaker

Page 19: Desarrollo de sistemas tolerantes a fallas

Circuit Breaker (1)

Page 20: Desarrollo de sistemas tolerantes a fallas

Circuit Breaker (2)

Page 21: Desarrollo de sistemas tolerantes a fallas

Circuit Breaker (3)

public class CircuitBreaker implements MyResource { public enum State { CLOSED, OPEN, HALF_OPEN } final MyResource resource; State state; int counter; long tripTime; public CircuitBreaker(MyResource r) { resource = r; state = CLOSED; counter = 0; tripTime = 0L; } ...

Page 22: Desarrollo de sistemas tolerantes a fallas

Circuit Breaker (4)

... public Result access(...) { // resource access Result r = null; if (state == OPEN) {

checkTimeout(); throw new ResourceUnavailableException();

} try { r = resource.access(...); // should use timeout } catch (Exception e) {

fail(); throw e;

}

success(); return r;

}

...

Page 23: Desarrollo de sistemas tolerantes a fallas

Circuit Breaker (5)

...

private void success() {

reset();

}

private void fail() { counter++; if (counter > THRESHOLD) {

tripBreaker();

}

}

private void reset() { state = CLOSED; counter = 0;

}

...

Page 24: Desarrollo de sistemas tolerantes a fallas

Circuit Breaker (6)

...

private void tripBreaker() { state = OPEN; tripTime = System.currentTimeMillis(); } private void checkTimeout() { if ((System.currentTimeMillis - tripTime) > TIMEOUT) { state = HALF_OPEN; counter = THRESHOLD; } }

public State getState() return state; }

}

Page 25: Desarrollo de sistemas tolerantes a fallas

Patrón #3 Fail Fast

Page 26: Desarrollo de sistemas tolerantes a fallas

Fail Fast (1)

Page 27: Desarrollo de sistemas tolerantes a fallas

Fail Fast (2)

Page 28: Desarrollo de sistemas tolerantes a fallas

Fail Fast (3)

public class FailFastGuard { private FailFastGuard() {} public static void checkResources(Set<CircuitBreaker> resources) { for (CircuitBreaker r : resources) { if (r.getState() != CircuitBreaker.CLOSED) { throw new ResourceUnavailableException(r); }

}

}

}

Page 29: Desarrollo de sistemas tolerantes a fallas

Fail Fast (4)

public class MyService { Set<CircuitBreaker> requiredResources; // Initialize resources ... public Result myExpensiveAction(...)

{

FailFastGuard.checkResources(requiredResources);

// Execute core action ...

}

}

Page 30: Desarrollo de sistemas tolerantes a fallas

Patrón #4 Shed Load

Page 31: Desarrollo de sistemas tolerantes a fallas

Shed Load (1)

Page 32: Desarrollo de sistemas tolerantes a fallas

Shed Load (2)

Page 33: Desarrollo de sistemas tolerantes a fallas

Shed Load (3)

public class ShedLoadFilter implements Filter { Random random; public void init(FilterConfig fc) throws ServletException { random = new Random(System.currentTimeMillis()); }

public void destroy() { random = null; } ...

Page 34: Desarrollo de sistemas tolerantes a fallas

Shed Load (4)

...

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, ServletException {

int load = getLoad();

if (shouldShed(load)) { HttpServletResponse res = (HttpServletResponse)response; res.setIntHeader("Retry-After", RECOMMENDATION); res.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE); return;

}

chain.doFilter(request, response); } ...

Page 35: Desarrollo de sistemas tolerantes a fallas

Shed Load (5)

...

private boolean shouldShed(int load) { // Example implement if (load < THRESHOLD) { return false; } double shedBoundary = ((double)(load - THRESHOLD))/ ((double)(MAX_LOAD - THRESHOLD)); return random.nextDouble() < shedBoundary; } }

Page 36: Desarrollo de sistemas tolerantes a fallas

Patrón #5 Deferrable Work

Page 37: Desarrollo de sistemas tolerantes a fallas

Deferrable Work (1)

Page 38: Desarrollo de sistemas tolerantes a fallas

Deferrable Work (2)

Page 39: Desarrollo de sistemas tolerantes a fallas

Deferrable Work (3)

// Adaptive load variant ProcessingState state = initBatch(); while(!state.done()) { waitLoadBased();

state = processNext(state); } void waitLoadBased() { int load = getLoad(); long delay = calcDelay(load); Thread.sleep(delay); // try-catch left out for better readability

}

long calcDelay(int load) { // Simple example implementation if (load < THRESHOLD) { return 0L;

}

return (load – THRESHOLD) * DELAY_FACTOR; }

Page 40: Desarrollo de sistemas tolerantes a fallas

Patrón #6 Monitoreo

Page 41: Desarrollo de sistemas tolerantes a fallas
Page 42: Desarrollo de sistemas tolerantes a fallas
Page 43: Desarrollo de sistemas tolerantes a fallas

Referencias

• How Complex Systems Fail http://j.mp/HowComplexSystemsFail

!• Release It!

http://j.mp/ReleaseIt !

• Fault tolerance made Easy http://j.mp/FaultToleranceMadeEasy

!• Fault tolerance 101

http://j.mp/FaultTolerance101

Page 44: Desarrollo de sistemas tolerantes a fallas

Se MUY amable con tus usuarios Ellos te lo agradecerán :)

Page 45: Desarrollo de sistemas tolerantes a fallas

Preguntas

Agustín Ramos @MachinesAreUs