crossbario / autobahn-python

WebSocket and WAMP in Python for Twisted and asyncio
https://crossbar.io/autobahn
MIT License
2.48k stars 768 forks source link

INVOCATION to own endpoints #602

Closed sehoffmann closed 8 years ago

sehoffmann commented 8 years ago

First off: I don't know whether the behaviour I'm going to propose is already implemented. If so, it would be nice, if that would be documented.

In a complex application there might be many components depending on each other. In order to fulfill the request of an user, a component might need to access data provided by other components.

For small applications (in regards to traffic/workload), it might be enough to have a single server providing multiple components. If however workload increases, it might be neccessary to split components across multiple server.

In case two or more components are residing on the same server, a regular python method call can be used to invoke the endpoint provided by another component saving a whole roundtrip to the router. If one now needs to scale though, he has to change all method calls into wamp calls again. It would be nice to have one single codebase which can handle both scenarios.

I propose that wamp calls to endpoints registered by the same session, don't result in an actual INVOCATION message but are simply translated to regular python calls. Because this implicitely means that we circumvent the router, which is also responsible for authorization, this should not be the default behaviour. By actively setting a new register option allow_local_calls, one can tell Autobahn "that I know what I'm doing and I'm aware of the consequences". CallDetails should be identical to those supplied if a session would have called it self (wth the regular roundtrip to the router).

goeddea commented 8 years ago

I see your use case, but I do not think this is something that we want. (Just my 2cents.)

This is something that it's Python-specific, or specific to a particular implementation language. This breaks the principle that implementation language of a component should not have any consequences beyond the component.

sehoffmann commented 8 years ago

What bugs me about this reasoning is, that there is nothing preventing me from manually doing this. The problem with this however as outlined above is, that this breaks compatibility in case I move an endpoint to another peer. Having people to live with this due to some abstract reasoning just sounds unreasonable to me, especially if this is implemented as an optional feature.

Maybe I should provide some hard facts to support my case: A simple wamp call will result in 4 messages being exchanged overall. A wamp call to an endpoint which at the same time relies on 3 other endpoints (which is not an unusual number) results in 16 messages. That's 300% more workload in both regards to CPU and traffic.

Also I personally don't have any issues with having implementation specific features. Crossbar and other routers have implementation specific features as well. More importantly, we are not talking about consequences beyond the component. My POI on this is, that if all my endpoints are in the same session, I already have "priviliged access" to them, so we are more precisely talking about "consequences for the own component". For me, such a feature is more of an internal implementation optimization than changing behaviour.

Not providing such a feature, given how relatively simple it is to implement and by which insane amount it increases performance sounds extremly unreasonable to me. Good luck trying to justify to any business guy, why we have to pay three times more money on hardware if a simple software change could fix that without consequences.

PS: I would willingly agree to do a PR for this

oberstet commented 8 years ago

For one, this is already implemented: an AutobahnPython component that runs side-by-side with a router process does use a function-call based WAMP transport under the hood. Nothing is serialized/deserialized at all. Nevertheless, everything runs through regular router code for authorization etc even in this case. And this is necessary to enable full transparency / deployment independence.

Good luck trying to justify to any business guy, why we have to pay three times more money on hardware if a simple software change could fix that without consequences.

Well, the explanation is simple: there are consequences, and these are breaking WAMP principles. Having a shortcut mode in AutobahnPython in general (that is, when the component is not running embedded in a CB router process): no. This would break transparency / deployment independence.

Note, that running AutobahnPython components inside router processes might be restricted to CB internal stuff in the future. Because of security / coupling concerns ..

sehoffmann commented 8 years ago

I'm not talking about components running side-by-side with a router. I'm talking about arbitrary peers which want to call their own endpoints.

Because this implicitely means that we circumvent the router, which is also responsible for authorization, this should not be the default behaviour. By actively setting a new register option allow_local_calls, one can tell Autobahn "that I know what I'm doing and I'm aware of the consequences".

oberstet commented 8 years ago

I'm talking about arbitrary peers which want to call their own endpoints.

Ok, understood.

No, we don't support skipping the router, and we won't. It breaks fundamental WAMP design philosophy. It would also require to replicate router logic in the client library (eg to support pattern-based registrations etc).

sehoffmann commented 8 years ago

Ok whatever,

I don't want to sound sulky but at this point I'm really fed up with Autobahn, Crossbar and WAMP. If you can handle such an insane performance impact just in order to fulfill some abstract paradigmas, philosphies or moral views, fine. If you believe that this is the right way, do whatever you want, it's your project in the end, isn't it? Just don't expect to get much feedback from people who actually try to utilize the stuff you build for real world applications. Because so far, this project has probably been the most frustrating experience for me in both regards to actually using it pragmatically and to project managment. At this point iI'm just tired of investing hours and hours trying to propose meaningful improvements just to get them rejected in a dictator-like fashion for "reasons". For a long time I've also been hesitating to open PR's just for the very same reason. Trying to contribute to this project or giving feedback resulted from actual development work seems like a total waste of time. Maybe in a year you will realize that 80% of the traffic hopping over your router could be completely ommited and this will eventually get implemented. But my impression so far has been, unless YOU see and encounter a problem, there is no problem. I will just work around this limitation like I already did anyways. Screw those other user who might face the same issue. Not my concern, right? Retrospectively, I definitely regret choosing WAMP and even more do I regret wasting countless of hours into useless discussions.

oberstet commented 8 years ago

Ok. I am sorry to hear that. But I think there have been multiple instances where you raised issues, and these got addressed in the way you proposed! And I highly appreciate your input and the discussions.

And then there are instances where I have a strong opinion, like with this issue. Let me try to expand why. I think one of the core value propositions of WAMP is decoupling and abstraction. If we compromise on that, we might loose the whole point of WAMP. That is my general concern.

Let's take your proposal above: it seems simple to shortcut calls for endpoints which reside in the same client first. But e.g. what about pattern-based registrations, shared registrations, call cancelling, and other advanced features? You would end up with a router embedded in the client ultimately. And implement that functionality in each and every Autobahn client library. Because next would be adding client-internal broker functionality ("Why can't I have client-interal PubSub brokering?"). And then Python isn't enough, but people would ask to replicate this in AutobahnJS as well.

to fulfill some abstract paradigmas, philosphies or moral views, fine

What moral views? "some abstract paradigms": yes, decoupling, language and deployment independence. If you disagree with these, then WAMP isn't for you.

Maybe it's a question of granularity: making each and every tiny little function in an application into a registered WAMP procedure is probably going too far. WAMP tries to adress the "microservice granularity", not language-specific, function level.

But my impression so far has been, unless YOU see and encounter a problem, there is no problem.

I think that's unfair, and not supported by looking at the history of changes to WAMP etc that directly resulted from community feedback and proposals.

Maybe in a year you will realize that 80% of the traffic hopping over your router could be completely ommited and this will eventually get implemented.

Then throw away all of WAMP and implement a monolithic Python application. That will have the least overhead!

At this point iI'm just tired of investing hours and hours trying to propose meaningful improvements just to get them rejected in a dictator-like fashion for "reasons".

Feel free to use something else that better fits your requirements.