sábado, 22 de febrero de 2014

Alta disponibilidad de servidores y balanceo de carga.


Por estos tiempos las entidades dependen cada vez más de sus sistemas de información/informatización y como es obvio se desea que estos estén disponibles la mayor parte del tiempo posible, la interrupción de los mismos presupone serios problemas:
  • Costes directos asociados a la reparación del sistema de información (piezas a reparar o sustituir, portes, servicios técnicos, etc.).
  • Horas de trabajo adicionales para el departamento de sistemas que tiene que reparar la avería.
  • pérdidas de productividad o incluso horas de trabajo perdidas por los empleados que dependen del sistema.
  • Pérdida de ingresos, por las ventas o servicios que se han dejado de realizar.
  • Costes indirectos: satisfacción de los clientes, pérdida de reputación, mala publicidad, desconfianza de los empleados, etc.
La disponibilidad implica varias categorias:Fiabilidad, Recuperación, Detección de errores, Continuas operaciones.

Cluseter de alta disponibilidad:
Un cluster de alta disponibilidad es un conjunto máquinas(no se debe confundir con cluster de alto rendimiento), en su funcionamiento se manifiesta de manera general el monitoreo constante por parte del cluster(también denominado monitor del cluster), en caso de detectar el fallo del algún nodo procede a reemplazarlo de manera automática, este se puede dividir a su vez en dos clasificaciones:
Alta disponibilidad de infraestructura:
Esta clasificación se da cuando al producirse algún fallo de hardware en una de las máquinas activas del cluster el software es capaz de arrancar el servicio en una de las máquinas inactivas(respaldo), a ese proceso se le llama failover y a su contraparte failback que es la operación de devolver el servicio a los responsables originales después de corregirse la falla.
Alta disponibilidad de aplicación:
Esta clasificación se da cuando al producirse algún fallo de hardware o de las aplicaciones en una de las máquinas activas del cluster el software es capaz de de delegar el servicio que ha fallado a un de las máquinas de respaldo, una vez que la maquina del fallo se restablece la responsabilidad de los servicios le es devuelta.

 
Para esto te puedes encontrar con soluciones como:
Balanceo de carga.

El balance o balanceo de carga es una técnica utilizada para repartir el trabajo a realizar entre varios procesos, discos duros, máqinas, etc. El balance de carga se mantiene gracias a un algoritmo que divide de la manera más equitativa posible el trabajo, para evitar los así denominados cuellos de botella.

El problema de cómo gestionar la carga por los grandes de internet(goole, facebook, amazon, twitter, wikipedia, etc) es enfrentado de esta manera, y además resuelve de forma implícita la escalabilidad para el creciente número de usuario con que trabajan cada día.

Para esto te puedes encontrar con soluciones como:






Alta disponibilidad + Balanceo de carga:
La solución más completa consiste en una vinculación de estas dos tecnologías llegando a tener desempeños inigualables.




Por útimo a modo de ejemplificar los post sobre c++11 y Qt5 dejo un pequño demo sobre balanceo de carga, no funciona con un monitor(es un ejemplo de solo unas pocas lineas de código) sino que los clientes se mantienen chequeando constantemente la disponibilidad del servidor y en caso de no estar accesible uno de ellos toma su lugar.



Ver además: 

Algunas ventajas del uso de c++11.

C++ es un lengueaje de propósito general, el nuevo estándar centra sus esfuersos en dos aspectos fundamentales:
  1. Hacer a c++ un mejor lenguaje para la programación de sistemas y creación de biliotecas.
  2. Hacer a c++ más fácil de enseñar y aprender.
Hay muchas aplicaciones en las que podemos encontrar a c++ unas veces como lenguaje principal y otras veces usado en partes críticas de las mismas ej:
  • Google, el motor de búsqueda.
  • Amadeus, para venta de voletos de vuelo.
  • Facebook, la red social.
  • JVM (Oracle).
  • Interpretes javascrip (google V8).
  • Qt, framework para el desarrollo multiplataforma.
  • POCO, para el desarrollo orientado a la web.
  • OpenCV, para el tratamiento en tiempo real de imágenes.
  • Navegadores Web (Internet Explorer, Mozilla, Google-Chrome, Safari).
  • En general se pueden encontrar muchas aplicaciones en finansa, telecomunicaciones, drivers, el ejército, aplicaciones embebidas, videojuegos, matemática computacional(para lo que no fue originalmente creado, sin embargo está siendo ampliamente utilizado), robótica, entre muchas otras.

Como lo dice el título del post, acá les comparto algo de lo nuevo de c++11 antiguamente conocido como c++0x (si quieres una referencia más completa deberás leer un libro, yo recomiendo “The C++ Programming Language . Fourth Edition. Bjarne Stroustrup (el creador original de C++... que más se puede decir...)”, autores como estos además te recomiendan para ver material técnico específico la especificación de la iso(ISO C++ standard (ISO/IEC 14882-2011) [C++,2011] )).
Bueno las novedades de c++ abarcan la forma de escribir(sintácsis), el rendiemiento, facilidades de la biblioteca estandar, entre otras, de manera general son bastantes los cambios(a mi concideración para bien). C++11 salió ya hace algún tiempo: en 2009 se realiza una primera revisión del estándar a modo de borrador, en agosto de 2011 fue aprobado por la iso, en 2012 sale la primera implementación completa y hoy estamos aquí, algunos sin usarlo todavía a pesar de que actualmente es soportado por gcc(g++), clang, visualc++, por solo mencionar los compiladores más populares. Resulta que la “inercia” por lo que conocemos en ocaciones es muy fuerte y hace que nos estanquemos mientras la tecnología avanza. Yo concidero que un ingeniero no se debe medir tanto por lo que sabe como por lo que está dispuesto a aprender, una empresa que contrate un desarrollador o ingeniero en general que no esté dispusto a seguir los avances estaría adquiriendo un recurso humano que rapidamente quedaría sin soporte, es mejor tener un desarrollador LTS(Longer Time Support, :-P que se adapta a los cambios tecnológicos al pasar el tiempo).

Para ver un ejemplo de comparación del rendimiento(performace) del nuevo c++(c++11) en comparación con el antiguo(2003 que fue una revisión/corrección del c++ iso 1998) consideremos el siguiente ejemplo.
std::vector<int> getInts()
{
std::vector<int> ints;
for(int i =0; I <=10000000; i++) ints.push_back(i);
return ints;
}
Como podemos ver aquí se está creando un vector de enteros en un ámbito más reducido al que probablemente usará el valor de retorno, en este caso una vez que se tenga en memoria este vector al retornarlo se llama al constructor de copia para copiar uno por uno los elementos del vector para retornar esta copia y eliminar(de forma automática) de la memoria el creado originalmente, como te podrás dar cuenta tiene poco sentido esto de que teniendo los datos en meoria se cree una copia, se elimine el original y el copiado sea el que se use por el simple hecho de salirse del ámbito(el ámbito es la definición del espacio de vida de un objeto que puede ser global, de espacio de nombre, de clase, de función, de bloque, etc). Pués bien c++11 provee algunas soluciones a esto, una de ellas es la utilización de el contructor move que en vez de hacer una copia lo que hace es mover la dirección de memoria del dato en cuestión y entregarsela al ámbito que hizo el pedido.
Otra forma de resolver este problema hubiese sido usando un puntero reservando memoria para él de forma dinámica y retornando su dirección de memoria, esto en realidad es una solución implementable pero a la vez es un antipatrón ya que va en contra del principio de RAII (‘‘Resource Acquisition Is Initialization’’), o sea si la memoria se crea en este ámbito quién debería ser el responsable de eliminarla para mantener este esquema... pués c++11 también provee una solución elegante desde esta perpectiva y es con el uso de shared_ptr lo que crea un objeto de propiedad compartida que devolverá la memoria reclamada en cuanto el último de sus propietarios lo haga sin tener que llamar de forma explícita a delete.

Otro ejemplo es al usar regex(nuevo), si quieres representar una expresión que incluya algún slash invertido o comilla doble este debe ser precedido por un backslash(es a lo que se le llama escapar la cadena). Por ejemplo al representar lo siguiente:
string s = "\\w\\\\w"; // I hope I got that right
podemos darnos cuenta que esto es propenso a errore, para ello el nuevo c++(c++11) provee raw string literals en el cual un backslash es un backslash!!!, ej:
string s = R"(\w\\w)"; // I’m pretty sure I got that right

Otro ejemplo que me gustaría comentar, auto y range-for:
La palabra auto ha cambiado el significado de las antiguas versiones donde la había heredado de C, antes significaba que la variable era autodestruible, o sea escribir auto int era equivalente a int esto indicaba que el objeto llamaba a su destructor de forma automática al salirse del ámbito, ahora indica detecció de tipo desde el inicializador con lo cual podriamos por ejemplo escribir:
template<class T> void f1(vector<T>& arg)
{
for (vector<T>::iterator p = arg.begin(); p!=arg.end(); ++p) *p = 7;
for (auto p = arg.begin(); p!=arg.end(); ++p) ∗p = 7;
}
los cuales serían equivalentes y por su puesto el segundo más elegante que el primero.

El range-for te permite recorrer un contenedor de forma muy sencilla, tal como sigue:
void print_book(const vector<Entry>& book)
{
for (const auto& x : book) cout << x << '\n';
}
esto no se explica, solo se mira y el código habla por si solo, además comentar que para tener un contenedor propio capaz de usar esta cualidad solo hay que implemntar el begin y el end del contenedor.

Como último ejemplo las expresiones lambda o funciones lambda (simplemente lambda como también se les suele llamar). Lambda es una notación simplificada para definir y utilizar objetos o instancias de funciones anónimas. Esto es particularmente útil cuando pasas una operación como argumento a un algorimo, aquí puedes ver un ejemplo:
template<class C>
void print_modulo(const C& v, ostream& os, int m)
// output v[i] to os if v[i]%m==0
{
breadth_first(begin(v),end(v),
[&os,m](int x) { if (x%m==0) os << x << '\n'; }
);
}
Un ejemplo de la utilidad de esto lo puedes ver al usar signal/slog(un concepto de Qt framework).

Como podrás saber es imposible tratar en un simple post sobre todas estas nuevas características por lo que te dejo en manos de Stroustrup:
Here are what I consider the most widely useful new ‘‘building bricks’’ affecting the style of
C++11 code with references to the text and their primary authors:
Control of defaults: =delete and =default: §3.3.4, §17.6.1, §17.6.4; Lawrence Crowl and
Bjarne Stroustrup.
Deducing the type of an object from its initializer, auto: §2.2.2, §6.3.6.1; Bjarne Stroustrup.
I first designed and implemented auto in 1983 but had to remove it because of C compatibil-
ity problems.
Generalized constant expression evaluation (including literal types), constexpr: §2.2.3,
§10.4, §12.1.6; Gabriel Dos Reis and Bjarne Stroustrup [DosReis,2010].
In-class member initializers: §17.4.4; Michael Spertus and Bill Seymour.
Inheriting constructors: §20.3.5.1; Bjarne Stroustrup, Michael Wong, and Michel Michaud.
Lambda expressions, a way of implicitly defining function objects at the point of their use in
an expression: §3.4.3, §11.4; Jaakko Jarvi.
Move semantics, a way of transmitting information without copying: §3.3.2, §17.5.2;
Howard Hinnant.
A way of stating that a function may not throw exceptions noexcept: §13.5.1.1; David Abra-
hams, Rani Sharoni, and Doug Gregor.
A proper name for the null pointer, §7.2.2; Herb Sutter and Bjarne Stroustrup.
The range-for statement: §2.2.5, §9.5.1; Thorsten Ottosen and Bjarne Stroustrup.
Override controls: final and override: §20.3.4. Alisdair Meredith, Chris Uzdavinis, and Ville
Voutilainen.
Type aliases, a mechanism for providing an alias for a type or a template. In particular, a
way of defining a template by binding some arguments of another template: §3.4.5, §23.6;
Bjarne Stroustrup and Gabriel Dos Reis.
Typed and scoped enumerations: enum class: §8.4.1; David E. Miller, Herb Sutter, and
Bjarne Stroustrup.
Universal and uniform initialization (including arbitrary-length initializer lists and protec-
tion against narrowing): §2.2.2, §3.2.1.3, §6.3.5, §17.3.1, §17.3.4; Bjarne Stroustrup and
Gabriel Dos Reis.
Variadic templates, a mechanism for passing an arbitrary number of arguments of arbitrary
types to a template: §3.4.4, §28.6; Doug Gregor and Jaakko Jarvi.


Para ver un pequeño ejemplo de c++11 en acción revisa:

viernes, 21 de febrero de 2014

¿Por qué deberiamos migrar nuestro código a Qt5?

Con un tiempo ya de liberada la versión 5 del framework Qt existen proyectos y personas que aún no actualizan su código a la nueva versión(para garantisar soporte prolongado de las dependencias). Cuando salió Qt4 trajo con sigo grandes cambios en la API con respecto a Qt3 haciendo que la actualización a Qt4 del software escrito en Qt3 fuese una tarea relmente difícil, era casi como reescribir el programa. Por el contrario de lo que occurrió con Qt5 que ha mantenido armonía con la API de Qt4, la mayor parte de esta permanece idéntica, lo que hace que la transición de las aplicaciones basadas en Qt4 a Qt5 sea con menores dolores de cabeza de lo que fue alguna vez entre otras versiones.
En Qt5, QML se ha puesto en el punto de mira del proyecto, es uno de los módulos más importantes que por supuesto usa al resto, pero esta es casi la presentación, la portada, lo que ve el usuario. A su vez el cambiar a Qt/C++ por Qt/Quick no es del todo positivo, mejor dicho no es que no sea positivo, es que si alquien escoje C++ teniendo como primer medidor el performace realmente no creo que Qt/Quick se le pueda comparar, en este sentido lo que se suele hacer es crear interfaces modernas y vistosas (look-and-feel) usando QML que pueden tener un potente lógica por detrás escrita en C++ y vinculada al código javascrip sin una mayor cantidad de esfuerso.
He estado escribiendo esto porque por un lado ves a algunos proyecto muy bien plantados con Qt4 tratando de migrar a Qt5 mientras que por otro lado vemos a algunos que están naciendo y tienen planificado el uso de Qt4.*, pues esto es algo sobre lo que devemos reflexionar, como mismo hasta aquí escribía refiriendome a que el “nuevo” Qt no trae tantos cambios entonces por qué deberiamos migrar?, aquí dejo algo de lo nuevo:
1. Ahora las Qwidgets  son un módulo aparte, pues existe una clase Qwindows de la cual heredan todas las ventanas, esto se implementó para permitir que QML pudiera tomar el control visual de las ventanas principales sin depender de Qwidget .
2. El procedimiento de creación de plugins se ha cambiado por completo(para bien, aunque debido a este cambio los modulos y plugins diseñados con Qt4 no son compatibles con los de la nueva versión).
3. Ahora connect en vez de  retornar un bool, retorna un QmetaObject::Connection .
4. C++11 viene con soporte de funciones lambda y Qt5 le añade soporte a las conecciones para  estas funciones .
5. Módulo de puerto serie incluido (Qt5.1).
6. QWS no forma parte de Qt5, desde la versión 4.8 se introdujo QPA, con eso puedes ir portando desde Qt4, en Qt5 QPA pasó a ser la parte central de Qt dejando atrás a QWS que tenía algunos problemas arquitectónicos.
7. Para usar c++11 puedes poner CONFIG += c++11  en el *.pro y basta.

Como podrás ver esta lista no es(ni pretende) exaustiva así que si quieres una lista completa de los cambios por release puedes consultar URLs como las que siguen:
5.1
5.2
5.3
Qt 5 Supported Platforms

Para ver un ejemplo de uso de Qt5 y c++11 revisa: