Python 3 Bi-directional RPC Framework using ZeroMQ and Asyncio
Poseur is an RPC framework built upon ZeroMQ sockets, leveraging Python’s asyncio package for high-performance even on the most demanding of services.
Poseur provides an extensible serialization layer, referred to as codecs, used between the RPC endpoints. Two codecs are included: Python’s pickle Module and MessagePack.
As a design decision, Poseur only supports CPython 3.5+. While it may work with older Python versions inadvertently, we do not explicitly support such versions. Use at your own risk!
Other Features Include:
- Bi-directional RPC. (Servers can call RPC Function on Clients).
- First Class Exceptions.
Upcoming Features Include:
- Heartbeats between RPC endpoints.
- Endpoint Authentication
- Endpoint Encryption
Any features or APIs are subject to mass changes before version 1.0 is published. We will attempt to make a few changes as possible, but we can not make any guarantees.
Use with cautiion!
Poseur is not yet on PyPI. In the meantime, you can install this package by cloning this repository. Note that we only support Python 3.5+:
$ python3 setup.py install $ pip install msgpack-python
or to install the extra dependency for the MessagePack serializer and install the package in develop mode:
$ pip install -e .[msgpack]
Python 3.5 or greater
- msgpack-python (For MessagePack Codec Support)
The working message specification can be found in the repository under spec.rst. Until version 1.0 is released, this is subject to change at any time.
Client to Server RPC
Set up an RPC server and enroll any functions that are to be made available for clients.
import uuid from poseur import Server, rpc @rpc.enroll_function def get_random_uuid_str(): return str(uuid.uuid4()) server = Server() server.bind("tcp://127.0.0.1:1234") server.start()
Set up an RPC client, connect to the server, and call the enrolled function.
import asyncio from poseur import Client client = Client("username1") client.connect("tcp://127.0.0.1:1234") async def get_and_print(): value = await client.get_random_uuid_str() print(value) loop = asyncio.get_event_loop() loop.run_until_complete(get_and_print())
Due to using ZeroMQ for the transport mechanism, the order for which a server binds and clients connect is irrelevant. However, there is one caveat when using bi-directional RPC. The client must be connected before the server attempts to make an remote-call to a client, otherwise an exception will be raised.