reactive-ipc / reactive-ipc-jvm

Reactive IPC for the JVM
Apache License 2.0
55 stars 13 forks source link

Goals & Motivations for Reactive IPC #1

Open benjchristensen opened 9 years ago

benjchristensen commented 9 years ago

The intent is to bring together Reactive Streams, RxJava, Reactor and similar efforts on networking libraries to create a “networking kernel” that can be the foundation of reactive, stream oriented IO for clients and servers supporting UDP, TCP, HTTP/1, HTTP/2 and WebSockets and a mechanism for pluggable codecs on top of all transports.

The desired timeline is BETA (1.0.rc1) by September 2015 and GA (1.0 Final) by end of 2015.

This would result in 3 layers of modules: API, Transport and Core.

screen shot 2015-03-06 at 4 06 51 pm

daviddawson commented 9 years ago

Hello! Interesting to see this initiative.

We've been working in this area for a little while so I thought I'd introduce myself and our ideas.

I run Simplicity Itself, a consultancy in the UK (http://www.simplicityitself.com)

We've been working in the microservices space for a good while, and one of the things that we noticed was that every microservices project we came across adopted semantics other than REST/HTTP. They may not realise it, but they all seem to, given sufficient time. So, message queues (say, SQS or AMQP), sometimes event broadcast. A newer one is data streaming, often in the form of Spark or Spring XD, whatever.

We've done this too in our projects, but it was painful becoming locked into particular transports, and adopting alternate runtimes is sometimes no possible because of it. and so we started a research project 6 months ago to see if we could bring all these things together into something coherent.

Broadly inspired by the success of the HTTP/ other specifications and the approach taken by reactivestreams.org, we started from a network transport specification, with it being executable. The various runtimes we want to support are then tested against it to see if they conform or not. That lets us build in the semantics we want, and also allow the various runtimes to implement their own programming models. Polyglot support is important to us, we use java, groovy, node.js and go in all our projects.

This is progressing (as something of a research project) at https://github.com/muoncore It's rough and ready, frankly I didn't want to publicise for another few months while we implement broader (and much better) support for service discovery, some more intelligent net transports and clean it up from the initial "wouldn't it be cool if" dev phase rush.

We very much enjoy the reactive streaming approach, and so we wanted to see if we could take those semantics and spread them across a network, and across language runtimes, too.

So, we did that, combined with the service discovery and resource concepts to allow the discovery of a remote service, inspect it's available streams and subscribe.

Again, very rough and ready, and with similarities in concept to the reactor lupin subsystem as far as I can tell. We've taken the position to implement the reactivestreams.org semantics exclusively, and then to represent those on the wire via another executable specification (eg, https://github.com/muoncore/muon-protocol-specifications/blob/master/test/amqp/amqp-stream.js). This enables us to deliver cross platform communication, with a node.js/ rxjs implementation now in progress to give bi-directional reactive streaming across a network and platform with swappable transports.

So there we are, that's what we're up to. As far as how it relates to this new initiative, I have no idea, but it's in the same space, so there must be some way for us to play :-)

dstengle commented 9 years ago

I've been thinking about this for a few days and I think I'll just put some questions here for clarification. They might be obvious, but given that this will be the basis for other layers I figure I'll ask here for myself and other people to find.

First, is the goal of this system to have symmetric relationships between the clients and servers with respect to being reactive? This might seem obvious for vector servers (terminology from elsewhere), but it seems like a reactive client could interact with a scalar server without needing as much cooperation.

Given the desire to work across transports, will there be a lowest common denominator representation for IPC between clients and servers? Or will there be framing/protocol across transports to attempt to achieve a middle ground? When I think about this, it seems that initiating connections is much more transport dependent than in terms of end-user code than subscribing to the resulting stream.

If the goals are more oriented around ipc between reactive systems rather than a more generic reactive io (maybe that would just be something like rxnetty?) will there not be access to lower level transport details like headers?

benjchristensen commented 9 years ago

@daviddawson thanks for your response and desire to collaborate!

We very much enjoy the reactive streaming approach, and so we wanted to see if we could take those semantics and spread them across a network, and across language runtimes, too.

Going ever network boundaries sounds like what is being pursued in the Reactive Streams IO initiative: https://github.com/reactive-streams/reactive-streams-io/issues/1 Perhaps Muon can influence that spec? It would be great to work together on getting the RS.io protocol well defined and your experience seems well suited to making it happen.

implement the reactivestreams.org semantics exclusively,

Are you referring to the network specification, APIs exposing IO or stream combinators?

Your work in muon-java looks like related to reactive-ipc-jvm. If you are interested in helping us build a solid core that all our higher-level abstractions/opinions can use that would be great.

benjchristensen commented 9 years ago

First, is the goal of this system to have symmetric relationships between the clients and servers with respect to being reactive?

A reactive client does not need the server to be reactive. For example, I can have a non-blocking, reactive client doing network calls against a blocking, thread-per-connection server. Similarly, a reactive server does not need consuming clients to be reactive.

Thus, we want both reactive and client servers as building blocks for our apps, but one does not require the other.

will there be a lowest common denominator representation for IPC between clients and servers?

This would depend on the protocol being implemented. As long as a transport implementation can fulfill the protocol (such as TCP, UDP, HTTP/1) then it can be used.

Or will there be framing/protocol across transports to attempt to achieve a middle ground?

This reactive-ipc project is not trying to define new network or application protocols, just provide reactive Java APIs on top of existing protocols such as TCP, HTTP/1, HTTP/2, and WebSockets.

A new protocol being pursued is Reactive Streams IO which you can see at https://github.com/reactive-streams/reactive-streams-io/issues/1. Once that is defined we intended to provide a concrete implementation with Java APIs in this Reactive-IPC project.

more generic reactive io

It is intended to be focused on generic interprocess communication or IO. So if TCP is being used, Reactive-IPC would provide reactive APIs for reading/writing over a TCP connection and then higher-level libraries can decide what application semantics to layer on top.

RxNetty is a good example of what Reactive-IPC should offer. Think of Reactive-IPC as the evolution of RxNetty.

NiteshKant commented 9 years ago

This came up in a few discussions in the issue #5 and I thought it would be better to discuss it in the goals and motivation issue.

What should reactive-ipc-core contain?

In order to answer this question, I would first want to go over the overall intention of this effort spanning across various repos in reactive-ipc and reactive-streams-net-jvm, viz.,

  1. Discuss and determine a SPI for client/server for various transports TCP, UDP, HTTP, HTTP/2, WebSockets, etc: The SPI though seemingly simple for TCP is pretty involved when it comes to HTTP, HTTP/2. I think this is a very important and big part of this initiative.
  2. Decouple stream abstraction from the actual implementation of these SPIs. This is achieved by adhering to RS specs as opposed to a higher level stream abstraction like RxJava.
  3. Provide atleast one implementation of this SPI using a mature networking library like netty. Referred to as "Transport" in the block diagram in this issue.
  4. Provide different adapters to the SPI implementations to be used with different stream implementations. Referred to as "API" in the block diagram in this issue.

Currently, the proposed repo for 1 above is reactive-streams-net-jvm. If we happen to conclude that the abstractions are complex enough to get a broader agreement or impede optimized implementations across different networking libraries, we may move them to reactive-ipc-core under this org.

I can see a simplistic implementation of RS spec residing in reactive-ipc-core without overlapping concerns with the facilities provided by a networking or a streams library like dispatching, sequential execution guarantees, codecs, etc. I can surely see all Transport implementation using these common implementations of RS spec. I would actually be much more comfortable if we have a different module like reactive-ipc-reactive-streams (horrible name, may be someone can propose a better name :) ) specifically for this.

In absence of 1 belonging in reactive-ipc-core, I do not see much staying in reactive-ipc-core.

IMO, an attempt to create an abstraction over various network libraries in the way they encode/decode data, handle network interfacing, represent data (byte buffers) is a huge task with diminishing returns. I would like to stay away with this undifferentiated heavy-lifting unless we have a strong usecase of supporting various networking libraries and there is a value in sharing code across.

jbrisbin commented 9 years ago

I can see a simplistic implementation of RS spec residing in reactive-ipc-core without overlapping concerns with the facilities provided by a networking or a streams library like dispatching, sequential execution guarantees, codecs, etc. I can surely see all Transport implementation using these common implementations of RS spec.

@NiteshKant I agree with this completely...

I would actually be much more comfortable if we have a different module like reactive-ipc-reactive-streams (horrible name, may be someone can propose a better name :) ) specifically for this.

...this not so much.

I think our use of Reactive Streams is so fundamental that it actually makes more sense to keep it in core than anywhere else. We're not going to be creating any abstractions besides utility classes that don't in some way reference or leverage Reactive Streams, so I don't think it's meaningful to split it out into a separate submodule.

I would like to stay away with this undifferentiated heavy-lifting unless we have a strong usecase of supporting various networking libraries and there is a value in sharing code across.

I would prefer to stay away as well. I just don't think we can.

BTW this is a good argument in favor of supporting more than one transport library OOTB. It would be an excellent way to determine what needs to be shared and what has to live in the implementation module.

jbrisbin commented 9 years ago

Maybe using the terms "signal" and "dispatching" are misleading. Essentially what I am saying is that anything we put into core that in any way implements functionality that sends messages to subscribers must provide some facility for asynchronous message passing. It's either that or we put synchronized blocks everywhere.

Simply put: if we only rely on synchronous, direct method invocation for calling onXxx methods then we are not, by popular definition, Reactive. In this case we are actually no different than an invocation of a controller method in Spring MVC.