Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

embedded memcached proxy #716

Closed
wants to merge 45 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
8c26d7e
proxy: proof of concept and infrastructure
dormando Jun 11, 2020
2246ea4
proxy: furhter updates for flow IO API
dormando Aug 3, 2021
091a3c4
proxy: convert to IO flow API
dormando Aug 3, 2021
3b2926d
proxy: mcp.await() parallel-subrequests
dormando Aug 4, 2021
3da30e6
proxy: fix memory bugs in await()
dormando Aug 5, 2021
ce4a3c4
proxy: simplified bad backend handling
dormando Aug 7, 2021
bc39742
proxy: fix config reload crash for user stats
dormando Aug 10, 2021
6443e0c
proxy: start logger integration
dormando Aug 10, 2021
d229854
proxy: fix use-after-free in return callback
dormando Aug 13, 2021
e5e8973
proxy: start of io_uring integration
dormando Aug 13, 2021
70d592f
proxy: perror for io_uring init failures
dormando Aug 16, 2021
d127e51
proxy: update/remove some TODO's + uring patch
dormando Aug 19, 2021
561a40f
proxy: start N backend servers for tests
dormando Aug 19, 2021
0d95b6e
proxy: line ending test
dormando Aug 23, 2021
eabca94
proxy: gat/gats support
dormando Aug 24, 2021
d791186
proxy: more incr/decr support
dormando Aug 24, 2021
5e54783
proxy: beginning of meta parser code
dormando Sep 1, 2021
ce98eed
proxy: rename hash_selectors to pools.
dormando Sep 8, 2021
b7bccc8
proxy: expand the pool API
dormando Sep 8, 2021
c961252
proxy: use tokenizer for request parser.
dormando Sep 19, 2021
6336563
proxy: add lua API for request token handling
dormando Sep 20, 2021
02a36f5
proxy: r:token(n, newtoken) will modify a request
dormando Sep 20, 2021
f53419c
proxy: re-enable metaflag parsing
dormando Sep 21, 2021
6315b5f
proxy: re-privitize ascii's string tokenizer
dormando Sep 22, 2021
a63dccb
proxy: ketama lib moved
dormando Sep 22, 2021
cda1f08
proxy: functions for setting/updating timeouts
dormando Sep 26, 2021
99cb030
proxy: surface lua errors via `watch sysevents`
dormando Sep 27, 2021
35aa24a
proxy: kill some TODO/FIXME's
dormando Sep 27, 2021
f4df6ca
proxy: fix compile error when proxy not enabled.
dormando Sep 28, 2021
d94f31f
proxy: clean up protocol handler
dormando Sep 28, 2021
5fe40f9
proxy: fix bug in default timeouts
dormando Sep 28, 2021
9cd3ece
proxy: change mcmc's vendoring
dormando Sep 28, 2021
ae2c239
proxy: make `watch rawcmds` a bit more useful
dormando Sep 28, 2021
c764f5d
proxy: start of a "simple" lua library
dormando Sep 29, 2021
14e04ba
proxylib: allow specifying a host label
dormando Sep 30, 2021
24f1374
proxylib: allow specifying a default pool
dormando Sep 30, 2021
11d20c9
proxy: fix compilation error
dormando Sep 30, 2021
2e7e8f3
proxy: automake fix
dormando Oct 1, 2021
2ef0074
proxy: make simple an actual library
dormando Oct 1, 2021
994ab14
proxy: simple lib example updates
dormando Oct 1, 2021
de3bce4
proxy: move lua libs to proxylibs repo
dormando Oct 1, 2021
ea22014
proxy: vendoring.
dormando Oct 1, 2021
03f3321
proxy: vendor fetch script
dormando Oct 1, 2021
cecc52a
proxy: make dist hacks...
dormando Oct 2, 2021
b8f7790
proxy: skip tests without proxy
dormando Oct 2, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 13 additions & 0 deletions BUILD
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
See below if building the proxy

To build memcached in your machine from local repo you will have to install
autotools, automake and libevent. In a debian based system that will look
like this
Expand All @@ -22,3 +24,14 @@ You can telnet into that memcached to ensure it is up and running

telnet 127.0.0.1 11211
stats

IF BUILDING PROXY, AN EXTRA STEP IS NECESSARY:

cd memcached
cd vendor
./fetch.sh
cd ..
./autogen.sh
./configure --enable-proxy
make
make test
19 changes: 19 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ if ENABLE_SASL
memcached_SOURCES += sasl_defs.c
endif

if ENABLE_PROXY
memcached_SOURCES += proto_proxy.c proto_proxy.h vendor/mcmc/mcmc.h
endif

if ENABLE_EXTSTORE
memcached_SOURCES += extstore.c extstore.h \
crc32c.c crc32c.h \
Expand Down Expand Up @@ -90,6 +94,16 @@ memcached_debug_DEPENDENCIES += memcached_debug_dtrace.o
CLEANFILES += memcached_dtrace.o memcached_debug_dtrace.o
endif

if ENABLE_PROXY
memcached_LDADD += vendor/lua/src/liblua.a vendor/mcmc/mcmc.o
memcached_debug_LDADD += vendor/lua/src/liblua.a vendor/mcmc/mcmc.o
endif

if ENABLE_PROXY_URING
memcached_LDADD += vendor/liburing/src/liburing.a
memcached_debug_LDADD += vendor/liburing/src/liburing.a
endif

memcached_debug_CFLAGS += -DMEMCACHED_DEBUG

memcached_dtrace.h: memcached_dtrace.d
Expand All @@ -108,6 +122,11 @@ memcached_debug_dtrace.o: $(memcached_debug_OBJECTS)
SUBDIRS = doc
DIST_DIRS = scripts
EXTRA_DIST = doc scripts t memcached.spec memcached_dtrace.d version.m4 README.md LICENSE.bipbuffer
EXTRA_DIST += vendor/Makefile vendor/lua vendor/mcmc

if ENABLE_PROXY
SUBDIRS += vendor
endif

MOSTLYCLEANFILES = *.gcov *.gcno *.gcda *.tcov

Expand Down
20 changes: 20 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ AC_ARG_ENABLE(static,
AC_ARG_ENABLE(unix_socket,
[AS_HELP_STRING([--disable-unix-socket], [Disable unix domain socket])])

AC_ARG_ENABLE(proxy,
[AS_HELP_STRING([--enable-proxy], [Enable proxy code EXPERIMENTAL])])

AC_ARG_ENABLE(proxy-uring,
[AS_HELP_STRING([--enable-proxy-uring], [Enable proxy io_uring code EXPERIMENTAL])])

dnl **********************************************************************
dnl DETECT_SASL_CB_GETCONF
dnl
Expand Down Expand Up @@ -217,6 +223,18 @@ if test "x$enable_unix_socket" = "xno"; then
AC_DEFINE([DISABLE_UNIX_SOCKET],1,[Set to nonzero if you want to disable unix domain socket])
fi

if test "x$enable_proxy" = "xyes"; then
AC_DEFINE([PROXY],1,[Set to nonzero if you want to enable proxy code])
CPPFLAGS="-Ivendor/lua/src -Ivendor/liburing/src/include $CPPFLAGS"
dnl lua needs math lib.
LIBS="$LIBS -lm -ldl"
fi

if test "x$enable_proxy_uring" = "xyes"; then
AC_DEFINE([HAVE_LIBURING],1,[Set to nonzero if you want to enable proxy uring handling])
CPPFLAGS="-Ivendor/liburing/src/include $CPPFLAGS"
fi

AM_CONDITIONAL([BUILD_DTRACE],[test "$build_dtrace" = "yes"])
AM_CONDITIONAL([DTRACE_INSTRUMENT_OBJ],[test "$dtrace_instrument_obj" = "yes"])
AM_CONDITIONAL([ENABLE_SASL],[test "$enable_sasl" = "yes"])
Expand All @@ -226,6 +244,8 @@ AM_CONDITIONAL([ENABLE_TLS],[test "$enable_tls" = "yes"])
AM_CONDITIONAL([ENABLE_ASAN],[test "$enable_asan" = "yes"])
AM_CONDITIONAL([ENABLE_STATIC],[test "$enable_static" = "yes"])
AM_CONDITIONAL([DISABLE_UNIX_SOCKET],[test "$enable_unix_socket" = "no"])
AM_CONDITIONAL([ENABLE_PROXY],[test "$enable_proxy" = "yes"])
AM_CONDITIONAL([ENABLE_PROXY_URING],[test "$enable_proxy_uring" = "yes"])


AC_SUBST(DTRACE)
Expand Down
37 changes: 37 additions & 0 deletions logger.c
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,34 @@ static int _logger_parse_cce(logentry *e, char *scratch) {
return total;
}

#ifdef PROXY
static void _logger_log_proxy_raw(logentry *e, const entry_details *d, const void *entry, va_list ap) {
struct timeval start = va_arg(ap, struct timeval);
char *cmd = va_arg(ap, char *);
unsigned short type = va_arg(ap, int);
unsigned short code = va_arg(ap, int);

struct logentry_proxy_raw *le = (void *)e->data;
struct timeval end;
gettimeofday(&end, NULL);
le->type = type;
le->code = code;
le->elapsed = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec);
memcpy(le->cmd, cmd, 9);
}

static int _logger_parse_prx_raw(logentry *e, char *scratch) {
int total;
struct logentry_proxy_raw *le = (void *)e->data;

total = snprintf(scratch, LOGGER_PARSE_SCRATCH,
"ts=%d.%d gid=%llu type=proxy_raw elapsed=%lu cmd=%s type=%d code=%d\n",
(int) e->tv.tv_sec, (int) e->tv.tv_usec, (unsigned long long) e->gid,
le->elapsed, le->cmd, le->type, le->code);
return total;
}
#endif

/* Should this go somewhere else? */
static const entry_details default_entries[] = {
[LOGGER_ASCII_CMD] = {512, LOG_RAWCMDS, _logger_log_text, _logger_parse_text, "<%d %s"},
Expand Down Expand Up @@ -338,6 +366,15 @@ static const entry_details default_entries[] = {
"type=compact_fraginfo ratio=%.2f bytes=%lu"
},
#endif
#ifdef PROXY
[LOGGER_PROXY_CONFIG] = {512, LOG_SYSEVENTS, _logger_log_text, _logger_parse_text,
"type=proxy_conf status=%s"
},
[LOGGER_PROXY_RAW] = {512, LOG_RAWCMDS, _logger_log_proxy_raw, _logger_parse_prx_raw, NULL},
[LOGGER_PROXY_ERROR] = {512, LOG_SYSEVENTS, _logger_log_text, _logger_parse_text,
"type=proxy_error msg=%s"
},
#endif
};

/*************************
Expand Down
14 changes: 13 additions & 1 deletion logger.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ enum log_entry_type {
LOGGER_COMPACT_END,
LOGGER_COMPACT_FRAGINFO,
#endif
#ifdef PROXY
LOGGER_PROXY_CONFIG,
LOGGER_PROXY_RAW,
LOGGER_PROXY_ERROR,
#endif
};

enum logger_ret_type {
Expand Down Expand Up @@ -106,7 +111,14 @@ struct logentry_conn_event {
int sfd;
struct sockaddr_in6 addr;
};

#ifdef PROXY
struct logentry_proxy_raw {
unsigned short type;
unsigned short code;
long elapsed; // elapsed time in usec
char cmd[8];
};
#endif
/* end intermediary structures */

/* WARNING: cuddled items aren't compatible with warm restart. more code
Expand Down
68 changes: 66 additions & 2 deletions memcached.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@

#include "proto_text.h"
#include "proto_bin.h"
#include "proto_proxy.h"

#if defined(__FreeBSD__)
#include <sys/sysctl.h>
Expand Down Expand Up @@ -85,7 +86,6 @@ static enum try_read_result try_read_udp(conn *c);

static int start_conn_timeout_thread();


/* stats */
static void stats_init(void);
static void conn_to_str(const conn *c, char *addr, char *svr_addr);
Expand Down Expand Up @@ -500,6 +500,11 @@ static const char *prot_text(enum protocol prot) {
case negotiating_prot:
rv = "auto-negotiate";
break;
#ifdef PROXY
case proxy_prot:
rv = "proxy";
break;
#endif
}
return rv;
}
Expand Down Expand Up @@ -797,6 +802,11 @@ conn *conn_new(const int sfd, enum conn_states init_state,
case negotiating_prot:
c->try_read_command = try_read_command_negotiate;
break;
#ifdef PROXY
case proxy_prot:
c->try_read_command = try_read_command_proxy;
break;
#endif
}
}

Expand Down Expand Up @@ -1417,13 +1427,22 @@ static void reset_cmd_handler(conn *c) {

static void complete_nread(conn *c) {
assert(c != NULL);
#ifdef PROXY
assert(c->protocol == ascii_prot
|| c->protocol == binary_prot
|| c->protocol == proxy_prot);
#else
assert(c->protocol == ascii_prot
|| c->protocol == binary_prot);

#endif
if (c->protocol == ascii_prot) {
complete_nread_ascii(c);
} else if (c->protocol == binary_prot) {
complete_nread_binary(c);
#ifdef PROXY
} else if (c->protocol == proxy_prot) {
complete_nread_proxy(c);
#endif
}
}

Expand Down Expand Up @@ -1787,6 +1806,12 @@ void server_stats(ADD_STAT add_stats, conn *c) {
APPEND_STAT("miss_from_extstore", "%llu", (unsigned long long)thread_stats.miss_from_extstore);
APPEND_STAT("badcrc_from_extstore", "%llu", (unsigned long long)thread_stats.badcrc_from_extstore);
}
#endif
#ifdef PROXY
if (settings.proxy_enabled) {
APPEND_STAT("proxy_conn_requests", "%llu", (unsigned long long)thread_stats.proxy_conn_requests);
APPEND_STAT("proxy_conn_errors", "%llu", (unsigned long long)thread_stats.proxy_conn_errors);
}
#endif
APPEND_STAT("delete_misses", "%llu", (unsigned long long)thread_stats.delete_misses);
APPEND_STAT("delete_hits", "%llu", (unsigned long long)slab_stats.delete_hits);
Expand Down Expand Up @@ -1843,6 +1868,9 @@ void server_stats(ADD_STAT add_stats, conn *c) {
#ifdef EXTSTORE
storage_stats(add_stats, c);
#endif
#ifdef PROXY
proxy_stats(add_stats, c);
#endif
#ifdef TLS
if (settings.ssl_enabled) {
if (settings.ssl_session_cache) {
Expand Down Expand Up @@ -3801,6 +3829,9 @@ static void clock_handler(const evutil_socket_t fd, const short which, void *arg
settings.sig_hup = false;

authfile_load(settings.auth_file);
#ifdef PROXY
proxy_start_reload(settings.proxy_ctx);
#endif
}

evtimer_set(&clockevent, clock_handler, 0);
Expand Down Expand Up @@ -3999,6 +4030,9 @@ static void usage(void) {
settings.ext_max_frag, settings.slab_automove_freeratio);
verify_default("ext_item_age", settings.ext_item_age == UINT_MAX);
#endif
#ifdef PROXY
printf(" - proxy_config: path to lua config file.\n");
#endif
#ifdef TLS
printf(" - ssl_chain_cert: certificate chain file in PEM format\n"
" - ssl_key: private key, if not part of the -ssl_chain_cert\n"
Expand Down Expand Up @@ -4663,6 +4697,9 @@ int main (int argc, char **argv) {
SSL_SESSION_CACHE,
SSL_MIN_VERSION,
#endif
#ifdef PROXY
PROXY_CONFIG,
#endif
#ifdef MEMCACHED_DEBUG
RELAXED_PRIVILEGES,
#endif
Expand Down Expand Up @@ -4718,6 +4755,9 @@ int main (int argc, char **argv) {
[SSL_SESSION_CACHE] = "ssl_session_cache",
[SSL_MIN_VERSION] = "ssl_min_version",
#endif
#ifdef PROXY
[PROXY_CONFIG] = "proxy_config",
#endif
#ifdef MEMCACHED_DEBUG
[RELAXED_PRIVILEGES] = "relaxed_privileges",
#endif
Expand Down Expand Up @@ -5461,6 +5501,22 @@ int main (int argc, char **argv) {
}
settings.read_buf_mem_limit *= 1024 * 1024; /* megabytes */
break;
#ifdef PROXY
case PROXY_CONFIG:
if (subopts_value == NULL) {
fprintf(stderr, "Missing proxy_config file argument\n");
return 1;
}
if (protocol_specified) {
fprintf(stderr, "Cannot specify a protocol with proxy mode enabled\n");
return 1;
}
settings.proxy_startfile = strdup(subopts_value);
settings.proxy_enabled = true;
settings.binding_protocol = proxy_prot;
protocol_specified = true;
break;
#endif
#ifdef MEMCACHED_DEBUG
case RELAXED_PRIVILEGES:
settings.relaxed_privileges = true;
Expand Down Expand Up @@ -5868,6 +5924,14 @@ int main (int argc, char **argv) {
exit(EX_OSERR);
}
/* start up worker threads if MT mode */
#ifdef PROXY
if (settings.proxy_enabled) {
proxy_init();
if (proxy_load_config(settings.proxy_ctx) != 0) {
exit(EXIT_FAILURE);
}
}
#endif
#ifdef EXTSTORE
slabs_set_storage(storage);
memcached_thread_init(settings.num_threads, storage);
Expand Down