Microservices

Microservices

Microservice software architecture is something opposite of monolithic architecture. For small projects, monolithic architecture is the most straightforward way to think about its design in general. But any mature project cannot be developed and supported easily if it is a monolith.

The microservice pattern forces developers to divide the project not just into separate modules and classes but into individual tiny apps called microservices. They can be deployed in different data centers, supported by other teams, etc.

guide_3_microservices_pic1.png

Now we will build a simple microservice for our trading software. It will receive our order data via API and save it to the local database. Of course, it is possible to save that data to a local disk. Still, suppose we want to build high-frequency trading software. In that case, we don't want to waste any local resources on logging or statistics, or maybe we want to outsource the development of a feature to a different developers team.

First of all, we will build a basic database connector. We will use the SQLite database for educational purposes. We will create a table of Orders containing six fields: timestamp, username, market, side, size, and price.

Example code:

class Database:
    #this is a DB connector
    #we will use SQLite in this example for simplicity
    def init(self):
        #filename and path to the database are hardcoded for simplicity
        self.connect_to = 'test.db'
    def create_table_orders(self):
        #a func to create our database
        conn = sqlite3.connect(self.connect_to)
        conn.execute('''CREATE TABLE if not exists Orders
        (timestamp TEXT NOT NULL,
        username TEXT NOT NULL,
        market TEXT NOT NULL,
        side TEXT NOT NULL,
        size FLOAT NOT NULL,
        price FLOAT NOT NULL
        );''')
        conn.close()

Database connector will have only one method implemented to save order data to the database.

Example code:

def add_data_orders(self, timestamp, username, market, side, size, price):
    #a func to save orders data
    conn = sqlite3.connect(self.connect_to)
    conn.execute("INSERT INTO Orders (timestamp, username, market, side, size, price) VALUES (?, ?, ?, ?, ?, ?)", (timestamp,
    username, market, side, size, price));
    conn.commit()
    conn.close()

Second, we need an API server. Creating a simple API server with the Flask module in less than 30 lines of code is possible. It will be able to receive HTTP POST requests with order data and save it to the database.

Example code:

@app.post("/API/orders")
def save_orders():
    if request.is_json:
        response = request.get_json()
        DB.add_data_orders(response['timestamp'], response['username'], response['market'], response['side'],  
        response['size'], response['price'])
        return response, 201
        return {"error": "Request must be JSON"}, 415

You can find complete database connector code and API SERVER code on GitHub.

And finally, we need an API connector for our service. Our API connector will use the requests library to make POST HTTP requests to our API server.

Example code:

def generate_request(self, order):
    try:
        response = requests.post(self.api_url, json=order)
        print(response)
    except Exception as e:
        print('generate_request - Exception', e)

You can find the complete API CLIENT code on GitHub.

guide_3_microservices_pic2.png

In ~100 lines of code, we created a database connector, API server, and API client to save order data to the database on the remote server.

The code is available in this Github repo.