jueves, 12 de enero de 2017

Serverless cloud computing: Introduction

Lately, there's been a buzz in the IT world about "Serverless" technologies. The term can be a bit misleading, because there is still a server machine doing server-side processing; the key difference is that when we talk about a "serverless" environment, the whole server infrastructure is managed by a third party. In a serverless environment, a developer only needs to provide his custom server-side code, and the platform will take care of running it when suitable. This takes the concept of cloud computing taking things off developer's hands a bit further. Let's recall those different kinds of cloud offerings and try to fit serverless there:

  • IaaS: Infastructure as a Service. The cloud vendor offers an interface for the users to manage their infrastructure: servers, databases, and networks, using a special interface. That way, the user can allocate and consume computational resources using a pay-as-you-go model. This is the model where the user has the most power: he can configure applications, their data, runtime, middleware and OSes; some cloud providers also offer databases, messaging queues and other services. Those which do are sometimes called IaaS+-kind of cloud services. The common use case for this type of solution is to offload datacenter infrastructure management to a third party in order to focus on the application itself. Examples: AWS (Amazon Web Services), Microsoft Azure, Google Compute Engine, Joyent.
  • PaaS: Platform as a Service. The cloud vendor offers a programming framework for developers. The vendor takes care of maintaining the framework and its infrastructure, and the developers take care of their applications built using the framework. The common use case for this type of solution is leveraging the existing framework to reduce development time and time-to-market. Example: Apprenda
  • Baas/FaaS/Serverless: Backend as a Service. Here, the only aspect that the user controls is which code gets run on the server/backend. Everything else is handled by the cloud provider. That's why I put this between PaaS and SaaS. However, a distinction must be made between BaaS and FaaS (see next paragraph).
  • SaaS: Software as a Service. The cloud vendor offers a set of pre-made applications hosted in their own cloud which can be used directly. The client only has access to those apps' interface, and the vendor is fully in charge of mantaining those apps and their infrastructure. The common use case for this type of solution is replacing traditional on-device software, which relieves the user from the hassle of installing and updating. Examples: Google Apps, Salesforce, Citrix GTM, Cisco WebEx.

Mike Roberts, from martinfowler.com, makes a distinction between two types of Serverless cloud computing architectures:

  • BaaS: Backend as a Service. An application built on top of a BaaS cloud service delegates most of the server-side logic and state to the cloud provider.
  • FaaS: In a FaaS environment, the user still writes most of the server side code, but unlike the traditional environments, that code is ran by the cloud provider in ephemeral containers, breaking the mold of the "always on" server. Basically, FaaS is about running server-side code without managing your own servers or server applications. This gives the cloud provider higher flexibility in assigning its computing resources.

The most popular FaaS offerings Amazon Lambda (from AWS) and Microsoft Azure functions (from Azure).

Further reading including architecture examples:

miércoles, 11 de enero de 2017

Serverless en la nube: Introducción

Últimamente, ha habido un revuelo en el mundo IT sobre tecnologías "Serverless". El término puede ser un poco confuso, porque sigue habiendo una computadora haciendo procesamiento del lado del servidor; la diferencia clave es que cuando hablamos de un entorno "serverless", toda la infraestructura del lado del servidor es manejada por terceros. En un entorno así, un desarrollador sólo necesita proveer su código a ejecutar del lado del servidor, y la plataforma de la nube se encargará de desplegarlo y ejecutarlo de manera conveniente y escalable. Esto lleva el concepto de cloud computing de delegar cosas a la nube un poco más allá. Recordemos los distintos tipos de servicios de cloud e intentemos meter a Serverless en esa lista:

  • IaaS: Infastructure as a Service. El proveedor de cloud ofrece una interfaz para que sus usuarios manejen la infraestructura: servidores, bases de datos, redes y otros recursos. De esta manera, el usuario puede definir y asignar recursos computacionales usando un modelo de facturación donde paga proporcionalmente a lo que usa (pay-as-you-go). Este es el modelo donde el usuario tiene más control: puede configurar aplicaciones, sus datos, runtime, middleware y sistemas operativos; algunos proveedores cloud también ofrecen bases de datos, colas de mensajes y otros servicios. Aquellos que agregan esto a veces son denominados IaaS+. El caso usual de uso de este tipo de soluciones es delegar el manejo de la infraestructura del datacenter a terceros a fin de concentrarse en el desarrollo de la aplicación. Ejemplos: AWS (Amazon Web Services), Microsoft Azure, Google Compute Engine, Joyent.
  • PaaS: Platform as a Service. El proveedor cloud ofrece un framework de desarrollo para los programadores. El proveedor se encarga de mantener el framework y su infraestructura, y los desarrolladores se encargan de desarrollar sus aplicaciones usando el framework. El escenario usual de uso de este tipo de solución involucra usar el framework existente para reducir tiempos de desarrollo y salida al mercado. Ejemplo: Apprenda.
  • Baas/FaaS/Serverless: Backend as a Service/Function as a Service. En este caso, lo único que el usuario controla es el código que se ejecuta en el servidor. Todo lo demás es manejado por el proveedor cloud. Por eso se coloca esta modalidad entre PaaS y SaaS. Sin embargo, debe marcarse una distinción entre BaaS y FaaS (ver próximo párrafo).
  • SaaS: Software as a Service. El proveedor cloud ofrece un conjunto de aplicaciones pre-fabricadas que pueden ser usadas directamente. El cliente sólo tiene acceso a la interfaz de usuario de dichas aplicaciones, no tiene injerencia en su desarrollo o mantenimiento; eso es responsabilidad del proveedor. El caso de uso usual de este tipo de soluciones es reemplazar software de escritorio tradicional, lo cual evita al usuario final las molestias de instalar y actualizar. Ejemplo: Google Apps, Salesforce, Citrix GTM, Cisco WebEx.

Mike Roberts, de martinfowler.com, marca una diferencia entre dos tipos de arquitecturas Serverless:

  • BaaS: Backend as a Service. Una aplicación construida sobre BaaS delega casi toda la lógica y estado del lado del servidor al proveedor cloud, usualmente vía aplicaciones de tipo "rich client".
  • FaaS: En un entorno FaaS, el usuario aún escribe la mayoría del código a ejecutar del lado del servidor, pero a diferencia de los entornos tradicionales, ese código es ejecutado por el proveedor cloud en "contenedores efímeros", rompiendo el paradigma "always on" de los servidores tradicionales. Básicamente, FaaS se trata de correr código del lado del servidor sin administrar servidores ni aplicaciones en servidores. Esto da al proveedor cloud mayor flexibilidad a la hora de asignar sus recursos computacionales.

Las tecnologías FaaS más populares son Amazon Lambda (de AWS) y las Microsoft Azure functions (de Azure).

Para profundizar en el tema (incluyendo ejemplos de arquitectura):

miércoles, 27 de enero de 2016

Web API (.NET): POSTing an object in XML format to an ApiController

Problem: In a .NET Web API app, inside a class which extends ApiController, it is desirable to receive an object in both XML and JSON format, in the most transparent form possible. Receiving the whole XML as a string, or using attributes (.NET's annotations) in the class to serialize are not acceptable solutions.

What tends to happen is that the object is always set to null when calling the method. There are various possible solutions, among them adding an "=" at the beginning of the POST message body. But doing so is not optimal, because it's a .NET specific convention and would limit us (if a partner used an HTTP client made with C++ running on Linux, we'd be in trouble). We cannot receive a string directly because that would prevent us from receiving the object in JSON format.

Solution: Receive the object with the attribute (.NET annotation) [FromBody], and enable the xml serialization inside our controller. An ideal place to do so would be the class' static constructor. For instance:

public class SomeController : ApiController{

    //Static constructor
    static SomeController(){
        //Needed for xml deserialization to work
        var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
        xml.UseXmlSerializer = true;
    }

    public async Task SomeMethodWhichReceivesBothXmlAndJson( [FromBody] SomeSerializableClass someInstance ){
        //...
    }

}

Web API (.NET): POSTeando un objeto en formato XML a un ApiController

Problema: En un aplicación .NET de tipo Web Api, dentro de una clase que hereda de ApiController, se desea poder recibir un objeto tanto en formato XML como JSON de la forma más transparente posible. Recibir el XML como string, o poner atributos (las annotations de .NET) en la clase a serializar no son soluciones aceptables.

Lo que suele ocurrir es que el objeto siempre llega como null. Hay varias soluciones posibles, entre ellas anteponer un "=" al principio del cuerpo del pedido POST. Pero eso no es aceptable, porque es algo específico de MVC y nos estaría limitando (si nuestro partner hace un cliente HTTP en C++ y Linux vamos a tener problemas). Tampoco podemos recibir un string porque eso nos impediría recibir JSON.

Solución: Recibir el objeto con el atributo (en el sentido de annotation de .NET) [FromBody], y habilitar el serializador xml en nuestro controller. Un lugar ideal para hacerlo es en el constructor estático de la clase. Por ejemplo:

public class SomeController : ApiController{

    //Static constructor
    static SomeController(){
        //Needed for xml deserialization to work
        var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
        xml.UseXmlSerializer = true;
    }

    public async Task SomeMethodWhichReceivesBothXmlAndJson( [FromBody] SomeSerializableClass someInstance ){
        //...
    }

}

sábado, 3 de octubre de 2015

Symfony 2 ignoring changes in parameters.yml

Say we want to change the database host because we changed our hosting service provider. We happily edit parameters.yml and upload it back up to the server, but we still get the "Connection timed out" error.

The solution is clearing the cache, but without direct access to the server, doing that via FTP might take ages. In my case, a simpler solution was to delete only the app/cache/prod/appProdProjectContainer.php file, which seems to be where Symfony 2 caches its parameters.

I'd like to personally thank the debug_print_backtrace() function. If you use it, make sure to do so with the DEBUG_BACKTRACE_IGNORE_ARGS flag, or you will get an illegible chunk of text.

Symfony 2 no toma cambios en parameters.yml

Supongamos que queremos cambiar el host de la base de datos porque migramos de hosting. Lo cambiamos alegremente en parameters.yml, pero sigue dando el error "Connection timed out".

La solución es borrar la cache, pero si no se tiene acceso directo al servidor, hacerlo por FTP puede demorar una eternidad. La solución en mi caso fue borrar sólo el archivo app/cache/prod/appProdProjectContainer.php, donde aparentemente Symfony 2 cachea los parámetros.

Quiero agradecer cordialmente a la función debug_print_backtrace() de PHP. Si la usan, asegúrense de invocarla con el flag DEBUG_BACKTRACE_IGNORE_ARGS, o les va a salir un choclo ilegible.

lunes, 14 de septiembre de 2015

How to handle a Win32 Unhandled Exception error in a Release build

You might have run into this scenario: a Windows application, which uses native/unmanaged C++, works perfectly fine in your development box. But in the productions environment, it crashes and a message like this one appears:

Sometimes, that exception can be caught with a try-catch block. But in other cases such as an Access violation, division by zero and similar ones, it can't be caught. Windows offers a specific solution for this: the __try - _except block, but it has some limitations. Specifically, it can only capture SEH exceptions. And those must be enabled on a project basis for this to work.

A better alternative, which is the one we'll analyze next, consists in using the SetUnhandledExceptionFilter function from the Kernel32.lib library. This allows us to catch the exception, but how can we get more information? Well, it is possible to obtain a stack trace by using additional functions from the psapi.lib and dbghlp.lib libraries. This way:

Usage example (StackTracing is a namespace, not a class):

void Init(){
   //...
   //Register handler
   ::SetUnhandledExceptionFilter(OnUnhandledException);
   //...
}


//Define handler (sorry for the Singleton, it's legacy code)
LONG WINAPI OnUnhandledException(  _In_  struct _EXCEPTION_POINTERS *pExceptionInfo ){
   string stackTrace;
   LONG result = StackTracing::DumpStackTrace( pExceptionInfo, stackTrace );
   ::GetErrorLoggerInstance()->Log( LOG_TYPE_ERROR, "StackTracing", "OnUnhandledException", stackTrace );
   ::MessageBoxA( NULL, "Fatal error encountered, application will shut down. Please check log for more information.", "DRA", MB_OK );
   return result;
}
This is the implementation of the helper functions used above:

//Get stack trace
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#pragma comment(lib, "psapi.lib")
#pragma comment(lib, "dbghelp.lib")

// Some versions of imagehlp.dll lack the proper packing directives themselves
// so we need to do it.
#pragma pack( push, before_imagehlp, 8 )
#include 
#pragma pack( pop, before_imagehlp )

struct module_data {
    std::string image_name;
    std::string module_name;
    void *base_address;
    DWORD load_size;
};

DWORD DumpStackTrace( EXCEPTION_POINTERS *ep );
extern void YourMessage(const char* title, const char *fmt, ...);// Replace this with your own function

class symbol { 
    typedef IMAGEHLP_SYMBOL64 sym_type;
    sym_type *sym;
    static const int max_name_len = 1024;

public:
    symbol(HANDLE process, DWORD64 address) : sym((sym_type *)::operator new(sizeof(*sym) + max_name_len)) {
        memset(sym, '\0', sizeof(*sym) + max_name_len);
        sym->SizeOfStruct = sizeof(*sym);
        sym->MaxNameLength = max_name_len;
        DWORD64 displacement;

        if (!SymGetSymFromAddr64(process, address, &displacement, sym))
            throw(std::logic_error("Bad symbol"));
    }

    std::string name() { return std::string(sym->Name); }
    std::string undecorated_name() { 
        std::vector und_name(max_name_len);
        UnDecorateSymbolName(sym->Name, &und_name[0], max_name_len, UNDNAME_COMPLETE);
        return std::string(&und_name[0], strlen(&und_name[0]));
    }
};


class get_mod_info {
    HANDLE process;
    static const int buffer_length = 4096;
public:
    get_mod_info(HANDLE h) : process(h) {}

    module_data operator()(HMODULE module) { 
        module_data ret;
        char temp[buffer_length];
        MODULEINFO mi;

        GetModuleInformation(process, module, &mi, sizeof(mi));
        ret.base_address = mi.lpBaseOfDll;
        ret.load_size = mi.SizeOfImage;

        GetModuleFileNameExA(process, module, temp, sizeof(temp));
        ret.image_name = temp;
        GetModuleBaseNameA(process, module, temp, sizeof(temp));
        ret.module_name = temp;
        std::vector img(ret.image_name.begin(), ret.image_name.end());
        std::vector mod(ret.module_name.begin(), ret.module_name.end());
        SymLoadModule64(process, 0, &img[0], &mod[0], (DWORD64)ret.base_address, ret.load_size);
        return ret;
    }
};


// if you use C++ exception handling: install a translator function
// with set_se_translator(). In the context of that function (but *not*
// afterwards), you can either do your stack dump, or save the CONTEXT
// record as a local copy. Note that you must do the stack dump at the
// earliest opportunity, to avoid the interesting stack-frames being gone
// by the time you do the dump.
DWORD StackTracing::DumpStackTrace( EXCEPTION_POINTERS *ep, std::string& stackTrace ){
    HANDLE process = GetCurrentProcess();
    HANDLE hThread = GetCurrentThread();
    int frame_number=0;
    DWORD offset_from_symbol=0;
    IMAGEHLP_LINE64 line = {0};
    std::vector modules;
    DWORD cbNeeded;
    std::vector module_handles(1);

    // Load the symbols:
    if (!SymInitialize(process, NULL, false)) 
        throw(std::logic_error("Unable to initialize symbol handler"));
    DWORD symOptions = SymGetOptions();
    symOptions |= SYMOPT_LOAD_LINES | SYMOPT_UNDNAME;
    SymSetOptions(symOptions);
    EnumProcessModules(process, &module_handles[0], module_handles.size() * sizeof(HMODULE), &cbNeeded);
    module_handles.resize(cbNeeded/sizeof(HMODULE));
    EnumProcessModules(process, &module_handles[0], module_handles.size() * sizeof(HMODULE), &cbNeeded);
    std::transform(module_handles.begin(), module_handles.end(), std::back_inserter(modules), get_mod_info(process));
    void *base = modules[0].base_address;

    // Setup stuff:
    CONTEXT* context = ep->ContextRecord;
#ifdef _M_X64
    STACKFRAME64 frame;
    frame.AddrPC.Offset = context->Rip;
    frame.AddrPC.Mode = AddrModeFlat;
    frame.AddrStack.Offset = context->Rsp;
    frame.AddrStack.Mode = AddrModeFlat;
    frame.AddrFrame.Offset = context->Rbp;
    frame.AddrFrame.Mode = AddrModeFlat;
#else
    STACKFRAME64 frame;
    frame.AddrPC.Offset = context->Eip;
    frame.AddrPC.Mode = AddrModeFlat;
    frame.AddrStack.Offset = context->Esp;
    frame.AddrStack.Mode = AddrModeFlat;
    frame.AddrFrame.Offset = context->Ebp;
    frame.AddrFrame.Mode = AddrModeFlat;
#endif
    line.SizeOfStruct = sizeof line;
    IMAGE_NT_HEADERS *h = ImageNtHeader(base);
    DWORD image_type = h->FileHeader.Machine;
    int n = 0;

    // Build the string:
    std::ostringstream builder;
    do {
        if ( frame.AddrPC.Offset != 0 ) {
            std::string fnName = symbol(process, frame.AddrPC.Offset).undecorated_name();
            builder << fnName;
            if (SymGetLineFromAddr64( process, frame.AddrPC.Offset, &offset_from_symbol, &line)) 
                builder << "  " /*<< line.FileName*/ << "(" << line.LineNumber << ")\n";
            else builder << "\n";
            if (fnName == "main")
                break;
            if (fnName == "RaiseException") {
                // This is what we get when compiled in Release mode:
                //YourMessage("Crash", "Your program has crashed.\n\n");
                return EXCEPTION_EXECUTE_HANDLER;
            }
        }
        else
            builder << "(No Symbols: PC == 0)";
        if (!StackWalk64(image_type, process, hThread, &frame, context, NULL, 
                            SymFunctionTableAccess64, SymGetModuleBase64, NULL))
            break;
        if (++n > 10)
            break;
    } while (frame.AddrReturn.Offset != 0);
    //return EXCEPTION_EXECUTE_HANDLER;
    SymCleanup(process);

    // Display the string:
    //::MessageBoxA( NULL, builder.str().c_str(), "Stack Trace", MB_OK );
    stackTrace = builder.str();
    return EXCEPTION_EXECUTE_HANDLER;
}