Skip to content

Commit 973886c

Browse files
rootton31337
authored andcommitted
Add SO_REUSEPORT support to socket
Introduce new feature for Twemproxy running on newer kernels. With this feature you are able to do upgrades, restarts without any downtime. Kernel does load balancing between processes with the same host:port pairs. Also, helps running on more than single core. Signed-off-by: Donatas Abraitis <donatas@hostinger.com>
1 parent 4bfcc42 commit 973886c

File tree

7 files changed

+43
-2
lines changed

7 files changed

+43
-2
lines changed

src/nc_conf.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ static struct command conf_commands[] = {
7878
conf_set_bool,
7979
offsetof(struct conf_pool, tcpkeepalive) },
8080

81+
{ string("reuseport"),
82+
conf_set_bool,
83+
offsetof(struct conf_pool, reuseport) },
84+
8185
{ string("redis_auth"),
8286
conf_set_string,
8387
offsetof(struct conf_pool, redis_auth) },
@@ -199,6 +203,7 @@ conf_pool_init(struct conf_pool *cp, struct string *name)
199203

200204
cp->redis = CONF_UNSET_NUM;
201205
cp->tcpkeepalive = CONF_UNSET_NUM;
206+
cp->reuseport = CONF_UNSET_NUM;
202207
cp->redis_db = CONF_UNSET_NUM;
203208
cp->preconnect = CONF_UNSET_NUM;
204209
cp->auto_eject_hosts = CONF_UNSET_NUM;
@@ -287,6 +292,7 @@ conf_pool_each_transform(void *elem, void *data)
287292
sp->hash_tag = cp->hash_tag;
288293

289294
sp->tcpkeepalive = cp->tcpkeepalive ? 1 : 0;
295+
sp->reuseport = cp->reuseport ? 1 : 0;
290296

291297
sp->redis = cp->redis ? 1 : 0;
292298
sp->timeout = cp->timeout;
@@ -1242,6 +1248,10 @@ conf_validate_pool(struct conf *cf, struct conf_pool *cp)
12421248
cp->tcpkeepalive = CONF_DEFAULT_TCPKEEPALIVE;
12431249
}
12441250

1251+
if (cp->reuseport == CONF_UNSET_NUM) {
1252+
cp->reuseport = CONF_DEFAULT_REUSEPORT;
1253+
}
1254+
12451255
if (cp->redis_db == CONF_UNSET_NUM) {
12461256
cp->redis_db = CONF_DEFAULT_REDIS_DB;
12471257
}

src/nc_conf.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#define CONF_DEFAULT_SERVER_CONNECTIONS 1
5656
#define CONF_DEFAULT_KETAMA_PORT 11211
5757
#define CONF_DEFAULT_TCPKEEPALIVE false
58+
#define CONF_DEFAULT_REUSEPORT false
5859

5960
struct conf_listen {
6061
struct string pname; /* listen: as "hostname:port" */
@@ -95,6 +96,7 @@ struct conf_pool {
9596
int server_failure_limit; /* server_failure_limit: */
9697
struct array server; /* servers: conf_server[] */
9798
unsigned valid:1; /* valid? */
99+
int reuseport; /* set SO_REUSEPORT to socket */
98100
};
99101

100102
struct conf {

src/nc_proxy.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,16 @@ proxy_listen(struct context *ctx, struct conn *p)
142142
return NC_ERROR;
143143
}
144144

145+
if (pool->reuseport) {
146+
status = nc_set_reuseport(p->sd);
147+
if (status < 0) {
148+
log_error("reuse of port '%.*s' for listening on p %d failed: %s",
149+
pool->addrstr.len, pool->addrstr.data, p->sd,
150+
strerror(errno));
151+
return NC_ERROR;
152+
}
153+
}
154+
145155
status = bind(p->sd, p->addr, p->addrlen);
146156
if (status < 0) {
147157
log_error("bind on p %d to addr '%.*s' failed: %s", p->sd,
@@ -294,7 +304,7 @@ proxy_accept(struct context *ctx, struct conn *p)
294304
return NC_OK;
295305
}
296306

297-
/*
307+
/*
298308
* Workaround of https://github.com/twitter/twemproxy/issues/97
299309
*
300310
* We should never reach here because the check for conn_ncurr_cconn()

src/nc_server.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ struct server_pool {
121121
unsigned preconnect:1; /* preconnect? */
122122
unsigned redis:1; /* redis? */
123123
unsigned tcpkeepalive:1; /* tcpkeepalive? */
124+
unsigned reuseport:1; /* set SO_REUSEPORT to socket */
124125
};
125126

126127
void server_ref(struct conn *conn, void *owner);

src/nc_stats.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,7 @@ stats_listen(struct stats *st)
827827
log_error("socket failed: %s", strerror(errno));
828828
return NC_ERROR;
829829
}
830-
830+
nc_set_reuseport(st->sd);
831831
status = nc_set_reuseaddr(st->sd);
832832
if (status < 0) {
833833
log_error("set reuseaddr on m %d failed: %s", st->sd, strerror(errno));

src/nc_util.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
#include <unistd.h>
2323
#include <fcntl.h>
2424
#include <netdb.h>
25+
#ifdef SO_REUSEPORT
26+
#include <linux/version.h>
27+
#endif
2528

2629
#include <sys/time.h>
2730
#include <sys/types.h>
@@ -75,6 +78,20 @@ nc_set_reuseaddr(int sd)
7578
return setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &reuse, len);
7679
}
7780

81+
int
82+
nc_set_reuseport(int sd)
83+
{
84+
int reuse;
85+
socklen_t len;
86+
87+
reuse = 1;
88+
len = sizeof(reuse);
89+
#ifdef SO_REUSEPORT
90+
return setsockopt(sd, SOL_SOCKET, SO_REUSEPORT, &reuse, len);
91+
#endif
92+
return -1;
93+
}
94+
7895
/*
7996
* Disable Nagle algorithm on TCP socket.
8097
*

src/nc_util.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
int nc_set_blocking(int sd);
8282
int nc_set_nonblocking(int sd);
8383
int nc_set_reuseaddr(int sd);
84+
int nc_set_reuseport(int sd);
8485
int nc_set_tcpnodelay(int sd);
8586
int nc_set_linger(int sd, int timeout);
8687
int nc_set_sndbuf(int sd, int size);

0 commit comments

Comments
 (0)