Author: Richard Edwards

  • Using Rust to Build Distributed Applications

    Using Rust to Build Distributed Applications

    Rust is an open source programming language that was initially developed at Mozilla Research and became increasingly popular for building distributed applications. It has been referred to in the Stack Overflow Survey as “the most-loved programming language” by software developers for five consecutive years. Moreover, companies like Amazon and Microsoft have recently revealed that they are using Rust to develop the software components that are responsible for ensuring application safety.

    Rust allows the implementation of safe and predictable code by leveraging memory safety and speed. It is the ideal choice to create code without incurring undefined or unpredictable behavior thanks to its features such as consistent runtime behavior and a static type system.

    Although Rust can be used for any system programming application, it is mainly implemented to build applications like simulation and game engines, browser components and file and operating systems. Rust syntax is similar to C++, but it addresses issues that C and C++ normally struggle with such as developing code without security vulnerabilities, general memory errors and problems in writing concurrent programs.

    The Advantages of Rust in Distributed Programming

    Rust tackles the performance and reliability problems of other low-level programming languages by using a careful compiler which examines all the variables used and referenced. As the code is compiled, Rust uses monomorphization by creating exclusive and high-performance code for each type of channel. It prevents programmers from paying performance penalties due to its flexibility. Based on the principle that you don’t pay for what you don’t use, the code written in Rust is enhanced and abstractions are solved at compile time making the program safe and without runtime overhead.

    Rust doesn’t have a garbage collector, which allows programmers to build abstractions with predictable performance. In Rust, there is no garbage to collect because the moment something would have become garbage, it gets freed immediately at compile time, making the program much faster. Moreover, Rust uses a borrow checker to check where data is used across the program, and by following a set of rules it establishes where data needs to be dropped or initialized. It provides the same advantages of a garbage collector with the efficiency and predictability of manual management.

    Another crucial characteristic of Rust is its asynchronous I/O. In Rust, asynchronous programming is widely implemented and well-integrated. It enables developers to effectively scale on a certain number of cores and exploit the operating system resources. By running several units of code on each application, this feature enhances performance and responsiveness of the operating system.

    Rust prevents some of the software engineering problems that could critically damage the application development process. These issues concern concurrency and memory safety which can cause very often denial of service, code vulnerabilities or compromised secrets. Examples of these frictions that are common in other languages such as C or C++ include uninitialized variables, undefined behavior, invalid iterators and unexpected variable modification.

    Another great advantage of using Rust is the Rust developer community, an extremely friendly and welcoming community. There are multiple events, chat rooms and forums to participate in that makes it even more pleasant to build distributed applications with Rust.

    Thanks to its ability to fix concurrency and memory issues, to compile and run safe and predictable code and provide a fast implementation, Rust is quickly increasing its popularity and establishing itself as the ideal choice for building distributed applications.

  • Evolving from FaaS to a Truly Serverless Paradigm

    Evolving from FaaS to a Truly Serverless Paradigm

    True serverless helps alleviate some of the administration and management issues related to FaaS

    Creating distributed applications demands a thorough understanding of cloud infrastructures and architectures. Engineers must address complex operational issues, including provisioning, configuration and how their code will behave over a distributed architecture.

    The current standard is to architect programs into microservices, before deploying to cloud hardware. Docker and similar technologies ensure that the microservices are strongly isolated in-terms of access, dependencies, and the potential overcommit of resources.

    However, containerization is an imperfect solution that masks rather than addresses the core problems of running cloud applications. As an application scales, scripting architectures and defining how different containers communicate with one another becomes exponentially complex. The solution—orchestration technologies such as Kuberenetes—adds yet another layer to an already bloated stack ill-designed for the needs of distributed computing.

    These problems were, in theory, to be alleviated by the concept of serverless—not the removal of servers, but rather the removal of their administration. However, since its emergence in the early part of the last decade, the term has become conflated with function as a service (FaaS).

    FaaS tools such as AWS Lambda break code into computational event-driven units, which only run when called. The event-driven logic scales quickly, efficiently and dynamically, driving down costs as the provider takes care of all server updates and administration, while developers only pay for what is used.

    However, functions run on their own custom framework and are limited in memory and execution time, rendering FaaS an inappropriate approach for scaling an entire application. Regularly scheduled database tasks, CPU-bound processes and long-running persistent connections to a server are examples of common patterns that map poorly onto FaaS.

    Serverless Is More Than Just FaaS

    A platform that looks after the infrastructure of an entire application (as opposed to specific functions) is the logical evolution of FaaS, and represents a truly serverless paradigm. Serverless, in this sense, takes the dynamic scaling properties of FaaS, but without fragmenting the application.

    Rather than simply linking together different components of a larger system, a serverless platform ensures long-running processes and fast discovery, enabling services to communicate and cooperate with one another quickly and reliably. Arbitrarily large memory capacity and unbounded execution time are underpinned by predictable execution and robustness guarantees well beyond the layered stack approach of FaaS. Developers can altogether ignore the management and configuration of servers, treating computation in purely algorithmic or data terms.

    Whereas containerization and FaaS solve pieces of the distributed computing puzzle, they also introduce new issues as the user must engineer their own infrastructure stack to carry out even basic tasks. By contrast, serverless could reduce an application engineered with Chef, Docker, Kubernetes, the JVM and Akka to a single abstraction. It allows for programs to be easily scaled up and down, harnessing almost limitless computing power, without compromising runtime.