More info on how Replication setContinuous CONTINUOUS vs ONESHOT

Hi Folks,

Pls provide more info how Replication setContinuous CONTINUOUS vs ONESHOT works in CBL java.
1)When does keep-alive logic apply?
2)How are connection reused in reference to heartbeat value?
3)How it works when applied on Push vs Pull Replication?
4)What will be the server impact when many clients are in CONTINUOUS mode ?
4)How different it is from web-sockets?

/**
* Set whether this replication is continous
*/
@InterfaceAudience.Public
public void setContinuous(boolean isContinous) {
if (isContinous) {
this.lifecycle = Lifecycle.CONTINUOUS;
replicationInternal.setLifecycle(Lifecycle.CONTINUOUS);
} else {
this.lifecycle = Lifecycle.ONESHOT;
replicationInternal.setLifecycle(Lifecycle.ONESHOT);
}
}

@hideki @jens Docs has very minimal info…also im debugging the code and live logs…
http://developer.couchbase.com/documentation/mobile/1.2/develop/references/couchbase-lite/couchbase-lite/replication/replication/index.html

Thanks
Nithin

A continuous pull replication connects to the Gateway’s changes feed in “continuous” mode. This keeps the response socket open indefinitely, sending information about each new doc revision as it becomes available. It’s not WebSocket protocol, but it’s conceptually similar.

Keep-alive is done via the “heartbeat” parameter, which tells the server how often to send a no-op (CRLF) over the socket to prevent it from being seen as idle and closed.

Continuous push replications do not keep a network connection open. Instead the replicator monitors the local database, and pushes any new revisions over the usual REST API. Again, there’s no network activity except when the local database changes.

When many clients have continuous pull replications running, the server will have a lot of open TCP sockets. This is similar to the issues affecting IMAP or XMPP or WebSocket servers — there are well known techniques for scaling this (look up “C10K” for info.)

@jens thanks for the reply…have more queries…below is my observation when PULL is in Continuous mode…

  1. Android uses longpoll mechanism in continuous mode.
    https://github.com/couchbase/couchbase-lite-java-core/blob/release/1.1.0/src/main/java/com/couchbase/lite/replicator/ChangeTracker.java
    2)How different is Continuous vs longpoll feed? or both are same.
    feed string Specifies type of change feed. Valid values: normal, continuous, longpoll, websocket.

3)“Keep-alive is done via the “heartbeat” parameter, which tells the server how often to send a no-op (CRLF) over the socket to prevent it from being seen as idle and closed.”

Is keep alive is sent from server?

4)"This keeps the response socket open indefinitely"
But on Every successfully pull response their is new HttpGet request/connection is made, any reason for it.Its contradicting with your above info.
Is it not that same old connection is retained/refreshed to get response?
https://---:---@43.225.119.183:443/cbdata/_changes?feed=longpoll&limit=50&heartbeat=300000&style=all_docs&since=6180385&filter=sync_gateway%2Fbychannel&channels=*

5)Any plans of Websockets in android?

Im a yet to do a PCAP level analysis…

Thanks
Nithin

Long poll is slightly less efficient than continuous because of the overhead of sending another request after every response, but it also leaves a socket open. (Effectively. It might close the socket after a response and immediately open another; that’s a detail of the HTTP implementation.) We use it because it’s easier to parse and because some HTTP client libs have trouble with a never-closed response.

I don’t work on Java so I don’t know when that version will adopt WebSocket. @hideki?

I already said that the server sends the keep-alive CRLF.

Hi @nitz_couchbase,

We have planed to support websocket for CBL android/java, https://github.com/couchbase/couchbase-lite-java-core/issues/493. We have been discussing new features for 1.3 release, websocket could be part of 1.3 release.

Thanks,
Hideki

@hideki

With heart beat changed 30sec what are below behavior.

  1. server sends the keep-alive CRLF on 30 secs of inactivity, a new connection is is created for _changes? or reuses old connection?

  2. on getting 200 ok for _changes with results, a new connection is created for _changes?reuses old connection?

Thanks
Nithin

Hi @nitz_couchbase,
By setting 30 sec for heartbeat, sync_gateway sends CRLF every 30 sec. SocketTimeout should not be occur if timeout is set higher than 30sec.

@hideki @jens

“Continuous push replications do not keep a network connection open. Instead the replicator monitors the local database, and pushes any new revisions over the usual REST API. Again, there’s no network activity except when the local database changes.”

What will be the push behavior in below use case.

1)PUSH replication is started in continuous mode.
2)Some docs where inserted and not pushed to server, as server is down.
3)Later server comes up.
4)CBL automatically pushes the docs to server which are already inserted? or application should call push replication again?
5) CBL has any back-off mechanism to push or replication becomes active only after a new doc is inserted?

Pls clarify…

Thanks
Nithin

A continuous replication will keep running regardless of network or server issues, and will transfer data when the server becomes reachable again.

So this is a concern for battery consumption. If the server isn’t available, is there a compounding backoff in trying to connect?

If the device cannot connect to a network (e.g. airplane mode, in the Sahara…) CBL simply waits for a system notification that the network status has changed. No power draw.

Otherwise a continuous replication will keep retrying, but with exponential backoff until it reaches a maximum interval (I don’t think it’s standardized across platforms; every few minutes.)

On iOS this only occurs if the app is active, since apps in the background aren’t allowed to initiate activities like this.

Dont see this behavior in android… @hideki pls confirm if this works and what is exponential back-off applied?

Server down is categorized as a temporary error. Push replicator keeps retrying to push after waiting some period.

In case device is out-of-network, CBL Android checks network connectivity. If the device is offline, replicator enters OFFLINE mode. During OFFLINE mode, no network activities occur.

Thnaks for the info…“keeps retrying to push after waiting some period” Whats exactly is the waiting period and hows it calculated?

@nitz_couchbase What’s the higher-level question you’re asking here? We could dive into the source code to look at specific constants (or heck, you could do it, it’s open source), but it sounds as though there’s something you want to use this information for … ?

@jens was just trying to know the time caluclation…will check the code…

@hideki

public static int DEFAULT_SO_TIMEOUT_SECONDS = 40; // 40 sec (previously it was 5 min)
// heartbeat value 30sec + 10 sec

// OkHttp Default Timeout is 10 sec for all timeout settings
public static int DEFAULT_CONNECTION_TIMEOUT_SECONDS = 10;
public static int DEFAULT_READ_TIMEOUT = DEFAULT_SO_TIMEOUT_SECONDS;

builder.connectTimeout(DEFAULT_CONNECTION_TIMEOUT_SECONDS, TimeUnit.SECONDS)
.writeTimeout(DEFAULT_WRITE_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(DEFAULT_READ_TIMEOUT, TimeUnit.SECONDS);

read timeout is set to 40secs now in android case… how will the _changes request behave now…lets say there no data(200ok) or/ CRLF from cbsyncgateway before 40 secs…

Currently we are not seeing any timeout of socket after 40 secs… _changes heartbeat is set to 225 secs…

Thanks
Nithin

As a default, the heartbeat value is set 30sec. Normal case, the heartbeat should be sent before 40 sec timeout. If the server does not send anything for 40 sec, CBL Android considers connection is disconnected.
As you set heartbeat to 225 sec, If the server does not send anything for 40 sec, CBL Android considers connection is disconnected. Timeout is categorized as a transient error, so the replicator keeps retrying automatically.

@hideki
We are seeing timeout as expecting in official CBL library…But we have made a custom CBL to support FIPS/HTTPS which has some issue…will check on that…

“public static int DEFAULT_SO_TIMEOUT_SECONDS = 40; // 40 sec (previously it was 5 min)
// heartbeat value 30sec + 10 sec”

Pls brief why the read-timeout is kept low as 30secs from 5mins…Is it not have bad experience on user network usage?

Thanks
Nithin

Some common gateway servers are pretty aggressive about closing “idle” sockets when they don’t see traffic. (IIRC, AWS’s load balancer is one.) We found that a 30sec heartbeat was necessary to work around this.