Introduction — pylm 0.14.1 documentation

# Introduction

This is a short introduction of some of the key aspects of pylm, a framework to implement high performance micro-services from reusable components.

But let’s begin with something basic, a server and a client able to call one of the server’s methods. Much in the fashion of a RPC server.

With pylm, the first step is to create the server by subclassing one of the available templates in the high-level API:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    from pylm.servers import Server
    import logging

    class MyServer(Server):
        def foo(self, message):
            self.logger.warning('Got a message')
            return b'you sent me ' + message

    if __name__ == '__main__':
        server = MyServer('my_server',
                          db_address='tcp://127.0.0.1:5555',
                          pull_address='tcp://127.0.0.1:5556',
                          pub_address='tcp://127.0.0.1:5557',
                          log_level=logging.DEBUG
                          )
        server.start()

Secondly, we create the client that connects to the server and calls the `foo` function from the server.

    1
    2
    3
    4
    5
    6
    7
    from pylm.clients import Client

    client = Client('my_server', 'tcp://127.0.0.1:5555')

    if __name__ == '__main__':
        result = client.eval('my_server.foo', b'a message')
        print('Client got: ', result)

It does not care in which order you start the client and the server, pylm uses ZeroMQ sockets for all the connections, that deal with all the details. Pylm uses ZeroMQ extensively, and somehow, it also follows its philosophy.

This is what we get when we start the server:

    $> python server.py
    2016-08-09 07:34:53,205 - my_server - WARNING - Got a message

And the client:

    $> python client.py
    Client got: b'you sent me a message'

Which is what we expected. The function `foo` only picks what is sent from the client, and adds it to `you sent me`. As simple as it seems. However, this basic example allows us to discover some important aspects of pylm.

- All messages are binary, represented as a sequence of bytes. This means that you decide how to serialize and deserialize the data you send to the server. If I decided to send a number instead of a sequence of bytes (replacing line 6 for `result = client.job('foo', 1)`), the client would crash with a TypeError.
- The server inherits from `pylm.servers.Server`. This parent class includes some interesting capabilities so you don’t have to deal with health monitoring, logging, performance analysis and so on. Maybe you don’t need all these things with a single server, but they become really handy when you have to monitor hundreds of microservers.
- The philisopy of pylm has two main principles:
  1. Simple things must be simple. If you don’t need something, you just ignore it and the whole system will react accordingly.
  2. Pylm is a framework, and does not come with any imposition that is not strictly necessary. Use the deployment system of your choice, the infrastructure you want... Pylm gives you the pieces to create the cluster, and you are in charge of the rest.

This example does not honor of the capabilities of pylm. Particularly the patterns that support parallel execution of jobs. To learn what are the capabilities of the different servers that are already implemented in pylm, visit the section about the High level API.

If you want to understand the underlying principles and algorithms of the small components that are used to implement a palm micro-service, visit the section about the Low level API.