summaryrefslogtreecommitdiff
path: root/ovsdb/raft.c
diff options
context:
space:
mode:
authorIlya Maximets <i.maximets@ovn.org>2020-05-22 22:36:27 +0200
committerIlya Maximets <i.maximets@ovn.org>2020-05-28 11:46:39 +0200
commit8c2c503bdb0da1ce6044a53d462f905fd4f8acf5 (patch)
tree78e23a91661308554441980cec3521f91e96cad2 /ovsdb/raft.c
parent16e3a80cf646f6c53d22ef98599d5aecb8310414 (diff)
downloadopenvswitch-8c2c503bdb0da1ce6044a53d462f905fd4f8acf5.tar.gz
raft: Avoid sending equal snapshots.
Snapshots are huge. In some cases we could receive several outdated append replies from the remote server. This could happen in high scale cases if the remote server is overloaded and not able to process all the raft requests in time. As an action to each outdated append reply we're sending full database snapshot. While remote server is already overloaded those snapshots will stuck in jsonrpc backlog for a long time making it grow up to few GB. Since remote server wasn't able to timely process incoming messages it will likely not able to process snapshots leading to the same situation with low chances to recover. Remote server will likely stuck in 'candidate' state, other servers will grow their memory consumption due to growing jsonrpc backlogs: jsonrpc|INFO|excessive sending backlog, jsonrpc: ssl:192.16.0.3:6644, num of msgs: 3795, backlog: 8838994624. This patch is trying to avoid that situation by avoiding sending of equal snapshot install requests. This helps maintain reasonable memory consumption and allows the cluster to recover on a larger scale. Acked-by: Han Zhou <hzhou@ovn.org> Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Diffstat (limited to 'ovsdb/raft.c')
-rw-r--r--ovsdb/raft.c39
1 files changed, 38 insertions, 1 deletions
diff --git a/ovsdb/raft.c b/ovsdb/raft.c
index 515eadab3..708b0624c 100644
--- a/ovsdb/raft.c
+++ b/ovsdb/raft.c
@@ -1421,8 +1421,20 @@ raft_conn_run(struct raft *raft, struct raft_conn *conn)
jsonrpc_session_run(conn->js);
unsigned int new_seqno = jsonrpc_session_get_seqno(conn->js);
- bool just_connected = (new_seqno != conn->js_seqno
+ bool reconnected = new_seqno != conn->js_seqno;
+ bool just_connected = (reconnected
&& jsonrpc_session_is_connected(conn->js));
+
+ if (reconnected) {
+ /* Clear 'last_install_snapshot_request' since it might not reach the
+ * destination or server was restarted. */
+ struct raft_server *server = raft_find_server(raft, &conn->sid);
+ if (server) {
+ free(server->last_install_snapshot_request);
+ server->last_install_snapshot_request = NULL;
+ }
+ }
+
conn->js_seqno = new_seqno;
if (just_connected) {
if (raft->joining) {
@@ -3296,6 +3308,31 @@ raft_send_install_snapshot_request(struct raft *raft,
.election_timer = raft->election_timer, /* use latest value */
}
};
+
+ if (s->last_install_snapshot_request) {
+ struct raft_install_snapshot_request *old, *new;
+
+ old = s->last_install_snapshot_request;
+ new = &rpc.install_snapshot_request;
+ if ( old->term == new->term
+ && old->last_index == new->last_index
+ && old->last_term == new->last_term
+ && old->last_servers == new->last_servers
+ && old->data == new->data
+ && old->election_timer == new->election_timer
+ && uuid_equals(&old->last_eid, &new->last_eid)) {
+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
+
+ VLOG_WARN_RL(&rl, "not sending exact same install_snapshot_request"
+ " to server %s again", s->nickname);
+ return;
+ }
+ }
+ free(s->last_install_snapshot_request);
+ CONST_CAST(struct raft_server *, s)->last_install_snapshot_request
+ = xmemdup(&rpc.install_snapshot_request,
+ sizeof rpc.install_snapshot_request);
+
raft_send(raft, &rpc);
}