30. Blocking code
• Easy to compose using the ‘;’ operator ;-)
• Easy to reason about
• Pleasant to debug
• Maps nicely to low level instructions
• It’s efficient*
• It’s extremely mature
• It’s familiar
35. Microservices
• Remote calls to other parts of the application are everywhere
• A remote call might be calling another remote call
• One operation might be blocking more than one thread
36. Blocking code: Stability
• Slow network connections are very expensive
• Performance problems cause an explosion of threads….
• … which cause performance problems
• Blocking systems don’t degrade gracefully
54. RxJava at High speed
Observable.<String>just("Ouagadougou","Dakar","Accra","Rabat")
.subscribe(System.err::println);
Ouagadougou
Dakar
Accra
Rabat
55. RxJava at High speed
Observable.range(0, 1000)
.subscribe(System.err::println);
0
1
2
3
4
5
6
…
998
999
56. RxJava at High speed
Observable.range(0, 1000)
.skip(10)
.take(10)
.subscribe(System.err::println);
10
11
12
13
14
15
16
17
18
19
57. RxJava at High speed
Observable.interval(1, TimeUnit.SECONDS)
.take(5)
.subscribe(System.err::println);
0 (with one second delay each)
1
2
3
4
58. RxJava at High speed
Bytes.fromClassPath("citiesafrica.xml")
.lift(XML.parse())
.subscribe(System.err::println);
<cities>
<africa>
<city name="Lusaka"/>
<city name="Harare"/>
<city name="Kigali"/>
</africa>
</cities>
START_DOCUMENT
START_ELEMENT cities {}
START_ELEMENT africa {}
START_ELEMENT city {name=Lusaka}
END_ELEMENT city
START_ELEMENT city {name=Harare}
END_ELEMENT city
START_ELEMENT city {name=Kigali}
END_ELEMENT city
END_ELEMENT africa
END_ELEMENT cities
END_DOCUMENT
XML parsing example: https://github.com/flyaruu/xml-rx
60. RxJava at High speed
Database.from(“jdbc:…”)
.select("select name from cities where continent = ? order by name")
.parameter("africa")
.getAs(String.class)
.subscribe(System.err::println);
Harare
Lusaka
Kigali
68. Well…
Double temp = temperatureInCity(“Cairo").toBlocking().first();
updateTemperatureUI(temp);
This code is still just as blocking
But now the consumer and producer are independent of threading
70. Use a non blocking HTTP client
public static Observable<Double> temperatureInCity(String city) {
return HTTP.get("http://api.weather.org/weather?q="+city)
.subscribeOn(Schedulers.io())
.lift(XML.parse())
.filter(e->e.getType()==XmlEventTypes.START_ELEMENT)
.filter(e->e.getText().equals("temperature"))
.first()
.map(xml->Double.parseDouble(xml.getAttributes().get("value")));
}
And the consumer notices nothing…
71. Non blocking consumer
Blocking:
Double temp = temperatureInCity(“Cairo").toBlocking().first();
updateTemperatureUI(temp);
Non blocking:
temperatureInCity(“Nairobi”)
.observeOn(UISchedulers.uiThread())
.subscribe(d->updateTemperatureUI(d));
72. Add a cache
public Observable<Double> temperatureInCity(String city) {
Double temperature = temperatureCache.get(city);
if(temperature!=null) {
return Observable.just(temperature);
}
return HTTP.get("http://api.weather.org/weather?q="+city)
.subscribeOn(Schedulers.io())
.lift(XML.parse())
.filter(e->e.getType()==XmlEventTypes.START_ELEMENT)
.filter(e->e.getText().equals("temperature"))
.first()
.map(xml->Double.parseDouble(xml.getAttributes().get("value")));
}
73. It’s just a library
• Not a new language
• Not a new framework
• Can be implemented incrementally
• Only needs a recent Java version and a recent Servlet Engine (if you
use servlets)
There are obvious examples of ‘Legacy’ in Art and Music
If we get a little bit closer to more technical subjects
Nobody would say: “We have better cars now”
Nobody complains that it does not have air conditioning.
Nobody will say: “I have a 2016 Ford Fiesta and that one is better in (nearly) every way”
It does not get the same kind of respect
Why is ‘legacy’ the most dreaded word for developers?
Why don’t we have similar feelings about ‘classic’ pieces of software?
This one just hurts
This is just sentimental
Retrogaming
- Why are the Sputnik and the Apollo admired in museums, but the software that ran on the 32k computer that got it to their destinations is nowhere to be found
Classics don’t need to change, I would not expect Mozart to develop a beat, or my car to turn hybrid at some point.
We do expect this from software:
Disrepair
Soggy
People who could leave, left
Late sixties, early seventies, the local government decided that this neighbourhood could not be saved.
Plan to tear it down completely and to rebuild it.
Huge amount of protest, people refused to leave.
Now it is a very pleasant place to be. Varied, 400 years of different building. Buildings got renovated.
Fast forward a few decades: One of the most desired area’s in the country.
It is nice. It has soul.
And I think we dodged a bullet there, because the buildings of the 70ties were horrible
Really boring at best
And a ghetto at worst (the hole in the building is unrelated)
Starting clean!
You throw away all your old todo’s / tests / documentation
All the technical debt
All the not-so-great design decisions
You can fantasise about how all problems are gone once you use all the shiny new technologies
New technologies prey on this: Rails, Ratpack: Look how easy it is to make something new
7:30
Large (old) systems are very difficult to replace / and in the not satisfying
If not careful, we’ll get very similar problems again
We massively underestimate the effort of rebuilding. Rebuilding large projects are the most doomed projects ever. Usually 90% is easy.
We need to get over it. We will live in a world of old software
We better start getting good at this. And keep this in mind when we write new software
With all its imperfections
Fix what is broken
Replace what is no longer relevant
… but don’t fall into the ‘better rebuild’ trap
We’re adults now. We should take long term responsibility for what we make.
Banks still run Cobol. Code has a way of sticking around
I have worked on one application for 13 years
Oracle database
Java Servlet backend
Swing Client
12:00
I’ve worked 13 years on this, and it has not been boring
Freek the app builder
More interesting and creative than building new green field applications all the time.
I’ve learned to face my demons of the past
So common it is invisible
One way or another, after the method is terminated, it is done.
Also performance tuning
Since my trusty C64 thirty years ago
In many cases, the right answer might be: Don’t mess with it
Threads eat quite a bit of memory and cpu, even when blocked
Could be a RMI / god forbid SOAP thing or a REST/HTTP call
HTTP maps nicely to the ‘method’ or ‘procedure’ model
Creates connection
Pushes the request data through the socket
Waits for socket data to come in
Reassembles the response
Even a tiny 1ms delay is an eternity for a modern cpu
Having 95% waiting threads is not uncommon
There is a penalty to async / non blocking code, but it is dwarfed by the I/O times
A multi-machine stack trace, and it consumes a thread on every machine
Logging war story?
Slow network connections => MOBILE
Bulkheading for performance problems does not work
Distributed = all systems (Or microservices)
So if we want microservices at scale, at some point we’ll need to face non-blocking communication
22min
Example write to a socket
In blocking code, doing a write will mean it completed successfully
This is how callbacks compose
Pyramid of doom
Life has gotten a whole lot harder
Composition with ‘;’ no longer works
This is going to be painful
Ask about Servlets
Since 2012
For non-blocking code (and smart people have spent a lot of time on this.
Once you actually start to do something, it gets much worse
>100 lines and very complicated
I know I shouldn’t mention Node here, but this is MUCH BETTER
This is how you talk about data
But how can we get closer to this?
A hose
You won’t describe a pipe like ‘Take one drop, transport, etc.
How fast should I move the water?
- What if there is no more water? What if the flow increases? Decreases?
It does not need to contain all the water
This is what node does A pipe is declarative
Not very scientific
Declarative, about dealing with stuff that happens
32 min
Poll. Use it? Went to talks?
Observable will emit 0 or more data items, and then call complete. Or an error and be silent forever
Very quick examples
Like a pushing list
Similar to Java 8 streams, but supports push
You can chain operators
Even though it says 1000, it will never do more than 20 in this case
You can chain operators
Can not be done by Java Streams
Explain byte source
Github
You can chain operators
JDBC is a blocking API
We’ve got our Node.js ‘pipe’
I’m not going to show you the gnarly glue code
Especially with mobile clients, even if I do any actual logic in a blocking style, this can save a ton.
This is an immediate improvement
*slightly simplified
Ideally, you write all your code non blocking
Chances are, that you have blocking code lying around.
40m
This will do its thing, but for one of the reasons we’ve talked about before, we’d like to make this non-blocking.
Where to begin?
41m
Behaves pretty much the same. A little bit of overhead.
You can’t bolt on non-blocking behaviour
It behaves exactly the same: Single threaded.
And that is HUGE
So now the API provider is no longer blocking a thread during the HTTP call (but the consumer still might)
The ‘first’ will unsubscribe and cancel the connection
The big payoff: If both ends of the API are non blocking, it frees up a thread for its duration.
45m
The threading model changes with the data
The API’s might be clunky but they are well defined and performant
Observable API’s can future proof your application
Suitable for guerilla / grassroots adoption -> req. your CTO
Many technologies focus on green field applications
It’s not all rainbows and unicorns
Performance will only improve when threads are expensive
Incremental updates are the way to go, even for profound changes like non blocking code
Your software will be around longer than you think
Big rebuilds are expensive and fail often
RxJava can improve performance, and open up a whole new type of programming, without much risk