Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A few ideas for the event bus #1

Closed
cburgdorf opened this issue Aug 30, 2018 · 2 comments
Closed

A few ideas for the event bus #1

cburgdorf opened this issue Aug 30, 2018 · 2 comments

Comments

@cburgdorf
Copy link
Contributor

Inter-process communication in Trinity

We are currently experimenting with different architectures to figure out the best way forward to prepare for a multi process architecture in which having multiple processes doesn't feel fragile and cumbersome but rather robust, manageable and lightweight.

It currently seems that we are leaning towards an architecture that uses a single event bus to allow loose, decoupled, async communication between processes as explained in this comment.

That idea is currently in a PoC phase with a pre-mature event bus spike as well as two PoC PRs that demo it's usage (ethereum/py-evm#1202, ethereum/py-evm#1172).

There are a number of issues today that I believe are crucial to move this forward hence I'm collecting and throwing them out here.

Random ideas for the event bus

1. Get objective performance metrics

I believe the number one reason why we want this architecture is simplicity and robustness. However, we also need to take performance into account. There are several things that may make this approach less performant out of the box (though, with much much room for improvements) and it would be nice to measure and compare rather than just guess.

2. Allow routed events

To begin with, all events that are broadcasted are delivered to all endpoints of the event bus (where each endpoint is usually sitting in a different process). Then, inside these endpoints, the events are either processed because someone is listening to them via subscribe / stream APIs, or they are lost if no one is interested in them. Nevertheless, they are delivered to each endpoint no matter if they are actually consumed or not.

We can do better than that and allow events to be routed (related: routed events in Chromium multi process architecture).

Routing can happen implicitly (more on that later) or explicitly.

3. Explicit routing via broadcast API

The broadcast API could accept an optional configuration object that could allow things like:

Excluding specific endpoints for delivery

event_bus.broadcast(SomeEvent(), Config(exclude_endpoints = ["proc1", "proc2"])

Only delivering to explicitly named endpoints

event_bus.broadcast(SomeEvent(), Config(filter_endpoints = ["proc1", "proc3"])

Excluding specific endpoints groups for delivery

event_bus.broadcast(SomeEvent(), Config(exclude_groups = ["plugins"])

Only delivering to explicitly named endpoint groups

event_bus.broadcast(SomeEvent(), Config(filter_groups = ["plugins"])

Groups of endpoints can be a powerful concept for when the exact ids/names of endpoints are unknown at design time but a statement about them belonging to a specific group can well be codified at development time (think: plugins!)

4. implicit routing via request API

While one of the primary use cases for the event bus is loosly coupled, async communication (think: PeerJoined / PeerLeft), there does exist a valid use case for communication pattern that fall more into the traditional request / response category. While one can do this with the existing APIs, the current event bus PoC does not have great support for this to make this more ergonomic and efficient.

It would be great to have an API roughly as follows.

peer_info = await event_bus.request(PeerInfoRequest(), Config(filter_endpoint="networking"))

This API would allow to:

  • request something and directly wait on the response in one API
  • ensure that the response is only delivered to this single callsite that was requesting it (implicit routing)

5. Allow all APIs to have timeouts

E.g.

result = await event_bus.request(PeerInfoRequest(), Config(timeout=1.5))

6. Make domestic events super efficient

Events that are scoped to only be broadcasted inside the endpoint that raises them do not need to go through the central coordinator at all and hence can be much much more efficient.

7. Check if we can move the event bus into it's own process and check if that would actually be beneficial

Currently, the event bus itself is sitting in the main process with endpoints being passed into other processes. That also means that all messaging is always going through this process. In other words an event raised in proc1, to be consumed in plugin-proc-n is always going through another hop proc1 -> main -> plugin-proc-n. That also means that there's a decent amount of processing going on in the process that hosts the event bus. But since the main process is at the very top of the hierarchy, it's kind of the natural / ideal place for this to happen. I believe our main process isn't performing much work anyway today but it would still be interesting to see if this work could move into another process.

8. Check if we can have an event bus without a central coordinator

More radical thought. Maybe we can achieve this kind of API even without going through a central coordinator hop

9. Check and compare to existing well established messaging solutions such as ZeroMQ

Something like zmq + aiozmq may actually provide better performance since the bulk of the work happens in native code. Yet it seems to have strong Python bindings. We might be even able to implement our event bus API on top of it or make the backend swappable.

@cburgdorf
Copy link
Contributor Author

This was copied from ethereum/py-evm#1206 Some of these things have already been implemented.

@pipermerriam
Copy link
Member

Glancing over this I think it's safe to close. Everything on the list either seems to be done or something we've decided to not do.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants