43. What's the latency for establishing a channel?
For how long do the channels stay alive?
Flux<Payload> recordSignal(Supplier<Flux<Payload>> signalProvider) {
var time = Timer.start("RSOCKET_STREAM_TIMER");
return signalProvider.get().doFinally(signal -> {
time.stop();
});
}
Intercepting Acceptor
44. Logging
@Override
public Flux<Payload> requestChannel(Publisher<Payload> payloads) {
var incoming = Flux.from(payloads)
.doOnSubscribe(s -> logger.info("subscribed to incoming"))
.doOnCancel(() -> logger.info("unsubscribed from incoming"))
.doOnComplete(() -> logger.info("complete incoming"))
.doOnError(e -> logger.info("error incoming"));
var outgoing = delegate().requestChannel(incoming);
return outgoing //
.doOnSubscribe(s -> logger.info("subscribed to outgoing"))
.doOnCancel(() -> logger.info("unsubscribed from outgoing"))
.doOnComplete(() -> logger.info("complete outgoing"))
.doOnError(e -> logger.info("error outgoing"));
}
}
52. Reconnection
/**
* Returns a Flowable that immediately publishes the current connection
* status and thereafter updates as it changes. Once a connection is in
* the CLOSED or ERROR state, it may not be connected again.
* Implementations must publish values per the comments on ConnectionStatus.
*/
connectionStatus(): Flowable<ConnectionStatus>;
53. Exponential backoff
function backoff(): () => number {
let i = 0;
return () => Math.pow(2, i++);
}
...
const next = backoff();
...
await Math.round(next() * 1000);
54. Jitter
function backoff(): () => number {
let i = 0;
return () =>
Math.pow(1.5, Math.random() + i++);
}
...
const next = backoff();
...
await Math.round(next() * 1000);
77. Availability
/**
* @return a positive number representing the availability of the entity.
* Higher is better, 0.0 means not available
*/
double availability();
0 1
warm up
78. Healthy
Healthy
Healthy
50000
50000
1
var socket = healthy.stream()
.filter(s -> s.availability() > 0)
.min(s -> {
var active = s.activeChannels();
var availability = s.availability();
return active / availability;
});