Rust multi module microservices Part 1 - Introduction

Hey folks, welcome to a mini-series of articles in which I continue my Rust learning journey, aiming to share knowledge and enjoyment throughout the process. In this series, I will focus on visualizing a multi-crate workspace project that allows for extensive code reuse across applications while maintaining the highest level of type safety. I plan to implement a variety of real-world use cases, such as shareable library crates, database migration, asynchronous communication using Kafka, distributed tracing with Zipkin, Avro, and much more 🀩

Workspace Setup

  1. Create a directory for initializing the cargo root project. I'll skip the part about how to install and update Rust and its tooling, as there are numerous articles and videos available on the subject. I have faith in your Googling skills! πŸ˜†

     mkdir rust-superapp && cd rust-superapp
    
  2. Let’s create a Cargo.toml file with the below contents

     [workspace]
     members = []
    
     [workspace. Dependencies]
     # We will add all our common dependent crates for our sub crates to share
     # the same version. How cool is that :D
    
  3. For this series, I have chosen a simple example of a Books HTTP REST API application crate, where you can create a book using a POST API. Additionally, there is a Books Analytics Kafka consumer application crate that prints the newly created book, which comes to this service through the power of Kafka πŸš€. Let's create our sub-packages.

    Execute the following commands to generate the sub-crates, all within the root directory. (Run them one at a time, of course, 😌)

     # Library crates
     cargo new --vcs=none --lib common
     cargo new --vcs=none --lib database
     cargo new --vcs=none --lib kafka
    
     # Application 
     cargo new --vcs=none books_api
     cargo new --vcs=none books_analytics
    
    1. A binary crate is a Rust program that compiles into one or more executables, each having its own main() function. In contrast, a library crate does not compile into an executable and does not have a main() function. Library crates typically define shared functionality that can be used across multiple projects. Additionally, we will initialize a Git repository in the root directory and prevent Cargo from initializing a Git repository each time a crate is created by using the

      --vcs=none flag.

  4. This creates folders, but they remain fairly disconnected and independent. Recall the Cargo.toml file mentioned earlier, which included a workspace section with a members array? πŸ€“ Let's add our crates there! After doing so, our Cargo.toml in the root directory will appear as follows.

     [workspace]
     members = ["common", "database", "kafka", "books_api", "books_analytics"]
    
     [workspace. Dependencies]
    

Expectation

Now, we have a foundation to begin building our services. Your setup should resemble the following! (Please disregard the Easter eggs )

0
Subscribe to my newsletter

Read articles from Omprakash Sridharan directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Omprakash Sridharan
Omprakash Sridharan