Get ahead
VMware offers training and certification to turbo-charge your progress.
Learn moreThe Reactor team is happy to announce the release of 2.0.0.RC1, which is now available in the spring.io Maven repository as well as Maven central. Version 2.0 is an #uberupdate
from Reactor version 1.1 and contains several new components as well as complete rewrites of important classes like Stream
, which now implements the Reactive Streams standard.
Please note that the Maven coordinates for Reactor 2.0 have changed from those for Reactor 1.x. The new coordinates all fall under the group ID io.projectreactor
rather than the previous org.projectreactor
. A sample dependencies block for a Gradle project might look like this:
ext {
reactorVersion = '2.0.0.RC1'
}
repositories {
maven { url 'http://repo.spring.io/libs-milestone' }
mavenCentral()
}
compile "io.projectreactor:reactor-core:$reactorVersion",
"io.projectreactor:reactor-net:$reactorVersion",
"io.projectreactor.spring:reactor-spring-context:$reactorVersion"
If you're a complete newbie to Reactor, you might want to first jump over to the spiffy new website at http://projectreactor.io and get acquainted with it before some of this will make sense.
Along with the changes announced in the 2.0.0.M1 release, here’s a brief list of important changes over version 1.1:
Stream
has been rewritten to implement the Reactive Streams standard, is 5-10x faster, and has much less overhead than the previous version.Stream
and the renaming of Reactor
to EventBus
. Documentation around this transition is ongoing.Stream
API derives from Reactive Extensions and mirrors many of its naming conventions. By leveraging a common vocabulary and behavior, it’s possible to easily translate Rx.NET and RxJava examples to Reactor.Stream
integration, DSL helper methods.If we had to limit ourselves to talking about just one change, then the native and foundational support for Reactive Streams would be it. It’s hard to overstate just how fundamental Reactive Streams has become to Reactor. Stream processing is the new black and Reactor has embraced that from the beginning of the project. The addition of Reactive Streams and its propagation of backpressure support, however, makes processing large volumes of data in real or near-real time much more accessible to your cloud applications. Now patterns such as stop-read
under load, batch flush
or adaptive batch
are available out of the box.
Each step in a Reactor Stream
is a Reactive Streams component that correctly propagates demand and backpressure based on the rate of processing under the current resource constraints. Using Reactive Streams, Reactor 2.0 makes it possible to create a stream of processing that adjusts its resource usage automatically. You can influence the rate at which new items are pulled into the system because of the way Reactive Streams backpressure is communicated upstream. That means a slow downstream component can push back all the way to the source to slow down the ingest rate if current processing is using all available resources.
Pool<Connection> pool;
Stream<Message> input;
input.capacity(1)
.batchConsume(msg -> {
pool.getConnection().merge(msg);
}, requestMore -> Math.max(pool.getSize() - pool.getActive(), 1));
In the snippet above we’re adapting the number of items to process based on the number of available connections in the pool. The Consumer
passed as the first parameter to the batchConsume
method will be invoked governed by the requestMore
value returned from the Function
passed as the second parameter. In this case we’re going to pre-fetch a number of messages equal to the number of free connections in the pool, or just a single message if all connections are active (in that case we’ll rely on backpressure from the connection pool).
If we wanted to make sure our stream was not a resource hog, we could also change the capacity algorithm to return a number less than the number of available connections, which would leave some connections available to other components in our application.
Starting with Reactor 2.0.0.RC1, it’s possible to include Reactor in your Android application by simply excluding the gs-collections
library which would otherwise force you to jump through some hoops due to it’s size. We’ve implemented a SimpleCachingRegistry
for the EventBus
that doesn’t use gs-collections
. Future improvements could include a dedicated UI event loop Dispatcher
to make sure your event handlers are run on the correct thread.
We’re very interested to see how Reactor can facilitate reactive applications on Android devices and how that ties to Reactor’s extremely high volume, low latency capabilities on the server side. Please let us know if you’re using Reactor on Android and if there are things we can do to make that experience better.
RC1 introduces new support for HTTP based on Reactor’s use of Netty 4. It’s not comprehensive yet, but it provides a few helper methods and some useful abstractions for building (and accessing) non-blocking REST-based micro and nanoservices. I wouldn't be trying to build production services with it yet, as there's still some refining that needs to happen before GA. You can embed a microservice using Reactor without resorting to the Netty API directly.
The following creates a Netty-based embedded HTTP server with path parameters that dispatches tasks onto the shared RingBufferDispatcher
.
HttpServer<String, String> server = NetStreams.httpServer(
spec -> spec.listen(3000)
.codec(StandardCodecs.STRING_CODEC)
.dispatcher(Environment.sharedDispatcher())
);
server.get("/echo/{greeting}", ch -> {
String greeting = ch.param("greeting") + " World!";
ch.transfer(Transfer.NON_CHUNKED)
.responseHeader("Content-Length", "" + greeting.length())
.log("server");
return Streams.just(greeting);
});
server.start();
We’ve also updated the TCP and ZeroMQ support to make better use of the important changes we made to Stream
. Most importantly, TCP servers and clients make use of Reactive Streams backpressure support to implement patterns like 'stop-read' to keep the server from overflowing downstream processing by reading too much data from the client, before there are resources available to process it.
We’ll do at least one more RC before releasing Reactor 2.0 GA. There’s still a few tweaks we need to make around complicated fork/join dispatching before we’re happy with its predictability. There are likely some additions to the HTTP support that we’ll want to make since this first cut is a fairly simple set of features. We might come across a few more bugs in edge cases as well.
We feel pretty good about this release candidate and we encourage you to try it out. If you’re doing new development, then we definitely encourage you to build on the Reactive Streams foundation of Reactor 2.0 versus the less capable, pre-Reactive Streams version in 1.1. If you’re upgrading existing Reactor code, the path is actually quite easy. In almost all cases your code will be greatly simplified.
If you run into problems upgrading your code, or just have general questions about how to use Reactor to solve your fast data problems, don’t hesitate to ask on the Reactor Framework Google Group.
We also welcome community contributions via pull requests on GitHub.
You might also be interested to know that the Reactive Streams project is being considered for inclusion in JDK 9 in the form of a new java.util.concurrent.Flow
class and appropraite inner classes. The discussion on this topic is being held in the JSR-166 concurrency-interest mailling list managed by professor Doug Lea of the State University of New York at Oswego.
Reactor is Apache 2.0 licensed and the project is managed through GitHub: