3.5. Peers
----------
-It is possible to synchronize server entries in stick tables between several
-haproxy instances over TCP connections in a multi-master fashion. Each instance
-pushes its local updates and insertions to remote peers. Server IDs are used to
-identify servers remotely, so it is important that configurations look similar
-or at least that the same IDs are forced on each server on all participants.
-Interrupted exchanges are automatically detected and recovered from the last
-known point. In addition, during a soft restart, the old process connects to
-the new one using such a TCP connection to push all its entries before the new
-process tries to connect to other peers. That ensures very fast replication
-during a reload, it typically takes a fraction of a second even for large
-tables.
+It is possible to propagate entries of any data-types in stick-tables between
+several haproxy instances over TCP connections in a multi-master fashion. Each
+instance pushes its local updates and insertions to remote peers. The pushed
+values overwrite remote ones without aggregation. Interrupted exchanges are
+automatically detected and recovered from the last known point.
+In addition, during a soft restart, the old process connects to the new one
+using such a TCP connection to push all its entries before the new process
+tries to connect to other peers. That ensures very fast replication during a
+reload, it typically takes a fraction of a second even for large tables.
+Note that Server IDs are used to identify servers remotely, so it is important
+that configurations look similar or at least that the same IDs are forced on
+each server on all participants.
peers <peersect>
Creates a new peer list with name <peersect>. It is an independent section,
uint32_t netinteger;
unsigned short datalen;
char *cursor, *datamsg;
+ unsigned int data_type;
+ void *data_ptr;
cursor = datamsg = msg + 1 + 5;
}
/* encode values */
- if (stktable_data_ptr(st->table, ts, STKTABLE_DT_SERVER_ID)) {
- int srvid;
+ for (data_type = 0 ; data_type < STKTABLE_DATA_TYPES ; data_type++) {
- srvid = stktable_data_cast(stktable_data_ptr(st->table, ts, STKTABLE_DT_SERVER_ID), server_id);
- intencode(srvid, &cursor);
+ data_ptr = stktable_data_ptr(st->table, ts, data_type);
+ if (data_ptr) {
+ switch (stktable_data_types[data_type].std_type) {
+ case STD_T_SINT: {
+ int data;
+
+ data = stktable_data_cast(data_ptr, std_t_sint);
+ intencode(data, &cursor);
+ break;
+ }
+ case STD_T_UINT: {
+ unsigned int data;
+
+ data = stktable_data_cast(data_ptr, std_t_uint);
+ intencode(data, &cursor);
+ break;
+ }
+ case STD_T_ULL: {
+ unsigned long long data;
+
+ data = stktable_data_cast(data_ptr, std_t_ull);
+ intencode(data, &cursor);
+ break;
+ }
+ case STD_T_FRQP: {
+ struct freq_ctr_period *frqp;
+
+ frqp = &stktable_data_cast(data_ptr, std_t_frqp);
+ intencode((unsigned int)(now_ms - frqp->curr_tick), &cursor);
+ intencode(frqp->curr_ctr, &cursor);
+ intencode(frqp->prev_ctr, &cursor);
+ break;
+ }
+ }
+ }
}
/* Compute datalen */
unsigned short datalen;
char *cursor, *datamsg;
uint64_t data = 0;
+ unsigned int data_type;
cursor = datamsg = msg + 2 + 5;
/* encode table key size */
intencode(st->table->key_size, &cursor);
- /* encode available data types in table */
- if (st->table->data_ofs[STKTABLE_DT_SERVER_ID]) {
- data |= 1 << STKTABLE_DT_SERVER_ID;
+ /* encode available known data types in table */
+ for (data_type = 0 ; data_type < STKTABLE_DATA_TYPES ; data_type++) {
+ if (st->table->data_ofs[data_type]) {
+ switch (stktable_data_types[data_type].std_type) {
+ case STD_T_SINT:
+ case STD_T_UINT:
+ case STD_T_ULL:
+ case STD_T_FRQP:
+ data |= 1 << data_type;
+ break;
+ }
+ }
}
intencode(data, &cursor);
|| msg_head[1] == PEER_MSG_STKT_INCUPDATE) {
struct shared_table *st = curpeer->remote_table;
uint32_t update;
+ unsigned int data_type;
+ void *data_ptr;
/* Here we have data message */
if (!st)
}
}
- if ((1 << STKTABLE_DT_SERVER_ID) & st->remote_data) {
- int srvid;
+ for (data_type = 0 ; data_type < STKTABLE_DATA_TYPES ; data_type++) {
- srvid = intdecode(&msg_cur, msg_end);
- if (!msg_cur) {
- /* malformed message */
- appctx->st0 = PEER_SESS_ST_ERRPROTO;
- goto switchstate;
- }
+ if ((1 << data_type) & st->remote_data) {
+ switch (stktable_data_types[data_type].std_type) {
+ case STD_T_SINT: {
+ int data;
+
+ data = intdecode(&msg_cur, msg_end);
+ if (!msg_cur) {
+ /* malformed message */
+ appctx->st0 = PEER_SESS_ST_ERRPROTO;
+ goto switchstate;
+ }
+
+ data_ptr = stktable_data_ptr(st->table, ts, data_type);
+ if (data_ptr)
+ stktable_data_cast(data_ptr, std_t_sint) = data;
+ break;
+ }
+ case STD_T_UINT: {
+ unsigned int data;
+
+ data = intdecode(&msg_cur, msg_end);
+ if (!msg_cur) {
+ /* malformed message */
+ appctx->st0 = PEER_SESS_ST_ERRPROTO;
+ goto switchstate;
+ }
+
+ data_ptr = stktable_data_ptr(st->table, ts, data_type);
+ if (data_ptr)
+ stktable_data_cast(data_ptr, std_t_uint) = data;
+ break;
+ }
+ case STD_T_ULL: {
+ unsigned long long data;
+
+ data = intdecode(&msg_cur, msg_end);
+ if (!msg_cur) {
+ /* malformed message */
+ appctx->st0 = PEER_SESS_ST_ERRPROTO;
+ goto switchstate;
+ }
+
+ data_ptr = stktable_data_ptr(st->table, ts, data_type);
+ if (data_ptr)
+ stktable_data_cast(data_ptr, std_t_ull) = data;
+ break;
+ }
+ case STD_T_FRQP: {
+ struct freq_ctr_period data;
+
+ data.curr_tick = tick_add(now_ms, intdecode(&msg_cur, msg_end));
+ if (!msg_cur) {
+ /* malformed message */
+ appctx->st0 = PEER_SESS_ST_ERRPROTO;
+ goto switchstate;
+ }
+ data.curr_ctr = intdecode(&msg_cur, msg_end);
+ if (!msg_cur) {
+ /* malformed message */
+ appctx->st0 = PEER_SESS_ST_ERRPROTO;
+ goto switchstate;
+ }
+ data.prev_ctr = intdecode(&msg_cur, msg_end);
+ if (!msg_cur) {
+ /* malformed message */
+ appctx->st0 = PEER_SESS_ST_ERRPROTO;
+ goto switchstate;
+ }
- if (stktable_data_ptr(st->table, ts, STKTABLE_DT_SERVER_ID)) {
- stktable_data_cast(stktable_data_ptr(st->table, ts, STKTABLE_DT_SERVER_ID), server_id) = srvid;
+ data_ptr = stktable_data_ptr(st->table, ts, data_type);
+ if (data_ptr)
+ stktable_data_cast(data_ptr, std_t_frqp) = data;
+ break;
+ }
+ }
}
}
}