mirror of
https://codeberg.org/redict/redict.git
synced 2025-01-22 16:18:28 -05:00
Use libsystemd's sd_notify for communicating redis status to systemd
Instead of replicating a subset of libsystemd's sd_notify(3) internally, use the dynamic library provided by systemd to communicate with the service manager. When systemd supervision was auto-detected or configured, communicate the actual server status (i.e. "Loading dataset", "Waiting for master<->replica sync") to systemd, instead of declaring readiness right after initializing the server process.
This commit is contained in:
parent
45025713a8
commit
641c64ada1
@ -1665,6 +1665,11 @@ void readSyncBulkPayload(connection *conn) {
|
|||||||
if (server.repl_backlog == NULL) createReplicationBacklog();
|
if (server.repl_backlog == NULL) createReplicationBacklog();
|
||||||
serverLog(LL_NOTICE, "MASTER <-> REPLICA sync: Finished with success");
|
serverLog(LL_NOTICE, "MASTER <-> REPLICA sync: Finished with success");
|
||||||
|
|
||||||
|
if (server.supervised_mode == SUPERVISED_SYSTEMD) {
|
||||||
|
redisCommunicateSystemd("STATUS=MASTER <-> REPLICA sync: Finished with success. Ready to accept connections.\n");
|
||||||
|
redisCommunicateSystemd("READY=1\n");
|
||||||
|
}
|
||||||
|
|
||||||
/* Restart the AOF subsystem now that we finished the sync. This
|
/* Restart the AOF subsystem now that we finished the sync. This
|
||||||
* will trigger an AOF rewrite, and when done will start appending
|
* will trigger an AOF rewrite, and when done will start appending
|
||||||
* to the new file. */
|
* to the new file. */
|
||||||
|
90
src/server.c
90
src/server.c
@ -55,6 +55,7 @@
|
|||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
/* Our shared "common" objects */
|
/* Our shared "common" objects */
|
||||||
|
|
||||||
@ -3651,6 +3652,8 @@ int prepareForShutdown(int flags) {
|
|||||||
int nosave = flags & SHUTDOWN_NOSAVE;
|
int nosave = flags & SHUTDOWN_NOSAVE;
|
||||||
|
|
||||||
serverLog(LL_WARNING,"User requested shutdown...");
|
serverLog(LL_WARNING,"User requested shutdown...");
|
||||||
|
if (server.supervised_mode == SUPERVISED_SYSTEMD)
|
||||||
|
redisCommunicateSystemd("STOPPING=1\n");
|
||||||
|
|
||||||
/* Kill all the Lua debugger forked sessions. */
|
/* Kill all the Lua debugger forked sessions. */
|
||||||
ldbKillForkedSessions();
|
ldbKillForkedSessions();
|
||||||
@ -3692,6 +3695,8 @@ int prepareForShutdown(int flags) {
|
|||||||
/* Create a new RDB file before exiting. */
|
/* Create a new RDB file before exiting. */
|
||||||
if ((server.saveparamslen > 0 && !nosave) || save) {
|
if ((server.saveparamslen > 0 && !nosave) || save) {
|
||||||
serverLog(LL_NOTICE,"Saving the final RDB snapshot before exiting.");
|
serverLog(LL_NOTICE,"Saving the final RDB snapshot before exiting.");
|
||||||
|
if (server.supervised_mode == SUPERVISED_SYSTEMD)
|
||||||
|
redisCommunicateSystemd("STATUS=Saving the final RDB snapshot\n");
|
||||||
/* Snapshotting. Perform a SYNC SAVE and exit */
|
/* Snapshotting. Perform a SYNC SAVE and exit */
|
||||||
rdbSaveInfo rsi, *rsiptr;
|
rdbSaveInfo rsi, *rsiptr;
|
||||||
rsiptr = rdbPopulateSaveInfo(&rsi);
|
rsiptr = rdbPopulateSaveInfo(&rsi);
|
||||||
@ -3702,6 +3707,8 @@ int prepareForShutdown(int flags) {
|
|||||||
* saving aborted, handling special stuff like slaves pending for
|
* saving aborted, handling special stuff like slaves pending for
|
||||||
* synchronization... */
|
* synchronization... */
|
||||||
serverLog(LL_WARNING,"Error trying to save the DB, can't exit.");
|
serverLog(LL_WARNING,"Error trying to save the DB, can't exit.");
|
||||||
|
if (server.supervised_mode == SUPERVISED_SYSTEMD)
|
||||||
|
redisCommunicateSystemd("STATUS=Error trying to save the DB, can't exit.\n");
|
||||||
return C_ERR;
|
return C_ERR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4867,13 +4874,11 @@ int redisSupervisedUpstart(void) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int redisSupervisedSystemd(void) {
|
int redisCommunicateSystemd(const char *sd_notify_msg) {
|
||||||
const char *notify_socket = getenv("NOTIFY_SOCKET");
|
const char *notify_socket = getenv("NOTIFY_SOCKET");
|
||||||
int fd = 1;
|
int (*dl_sd_notify)(int unset_environment, const char *state);
|
||||||
struct sockaddr_un su;
|
char *error;
|
||||||
struct iovec iov;
|
void *handle;
|
||||||
struct msghdr hdr;
|
|
||||||
int sendto_flags = 0;
|
|
||||||
|
|
||||||
if (!notify_socket) {
|
if (!notify_socket) {
|
||||||
serverLog(LL_WARNING,
|
serverLog(LL_WARNING,
|
||||||
@ -4881,47 +4886,28 @@ int redisSupervisedSystemd(void) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((strchr("@/", notify_socket[0])) == NULL || strlen(notify_socket) < 2) {
|
handle = dlopen("libsystemd.so.0", RTLD_LAZY);
|
||||||
return 0;
|
if (!handle) {
|
||||||
}
|
|
||||||
|
|
||||||
serverLog(LL_NOTICE, "supervised by systemd, will signal readiness");
|
|
||||||
if ((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1) {
|
|
||||||
serverLog(LL_WARNING,
|
serverLog(LL_WARNING,
|
||||||
"Can't connect to systemd socket %s", notify_socket);
|
"systemd supervision requested, but could not dlopen() libsystemd.so");
|
||||||
|
(void) dlerror();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
(void) dlerror();
|
||||||
|
|
||||||
|
*(void **)(&dl_sd_notify) = dlsym(handle, "sd_notify");
|
||||||
|
error = dlerror();
|
||||||
|
|
||||||
|
if (error != NULL) {
|
||||||
|
serverLog(LL_WARNING,
|
||||||
|
"systemd supervision requested, but could not load sd_notify(3) from libsystemd.so");
|
||||||
|
dlclose(handle);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&su, 0, sizeof(su));
|
(void) (*dl_sd_notify)(0, sd_notify_msg);
|
||||||
su.sun_family = AF_UNIX;
|
dlclose(handle);
|
||||||
strncpy (su.sun_path, notify_socket, sizeof(su.sun_path) -1);
|
return 0;
|
||||||
su.sun_path[sizeof(su.sun_path) - 1] = '\0';
|
|
||||||
|
|
||||||
if (notify_socket[0] == '@')
|
|
||||||
su.sun_path[0] = '\0';
|
|
||||||
|
|
||||||
memset(&iov, 0, sizeof(iov));
|
|
||||||
iov.iov_base = "READY=1";
|
|
||||||
iov.iov_len = strlen("READY=1");
|
|
||||||
|
|
||||||
memset(&hdr, 0, sizeof(hdr));
|
|
||||||
hdr.msg_name = &su;
|
|
||||||
hdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) +
|
|
||||||
strlen(notify_socket);
|
|
||||||
hdr.msg_iov = &iov;
|
|
||||||
hdr.msg_iovlen = 1;
|
|
||||||
|
|
||||||
unsetenv("NOTIFY_SOCKET");
|
|
||||||
#ifdef HAVE_MSG_NOSIGNAL
|
|
||||||
sendto_flags |= MSG_NOSIGNAL;
|
|
||||||
#endif
|
|
||||||
if (sendmsg(fd, &hdr, sendto_flags) < 0) {
|
|
||||||
serverLog(LL_WARNING, "Can't send notification to systemd");
|
|
||||||
close(fd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int redisIsSupervised(int mode) {
|
int redisIsSupervised(int mode) {
|
||||||
@ -4932,12 +4918,17 @@ int redisIsSupervised(int mode) {
|
|||||||
if (upstart_job) {
|
if (upstart_job) {
|
||||||
redisSupervisedUpstart();
|
redisSupervisedUpstart();
|
||||||
} else if (notify_socket) {
|
} else if (notify_socket) {
|
||||||
redisSupervisedSystemd();
|
server.supervised_mode = SUPERVISED_SYSTEMD;
|
||||||
|
serverLog(LL_WARNING,
|
||||||
|
"WARNING auto-supervised by systemd - you MUST set appropriate values for TimeoutStartSec and TimeoutStopSec in your service unit.");
|
||||||
|
return redisCommunicateSystemd("STATUS=Redis is loading...\n");
|
||||||
}
|
}
|
||||||
} else if (mode == SUPERVISED_UPSTART) {
|
} else if (mode == SUPERVISED_UPSTART) {
|
||||||
return redisSupervisedUpstart();
|
return redisSupervisedUpstart();
|
||||||
} else if (mode == SUPERVISED_SYSTEMD) {
|
} else if (mode == SUPERVISED_SYSTEMD) {
|
||||||
return redisSupervisedSystemd();
|
serverLog(LL_WARNING,
|
||||||
|
"WARNING supervised by systemd - you MUST set appropriate values for TimeoutStartSec and TimeoutStopSec in your service unit.");
|
||||||
|
return redisCommunicateSystemd("STATUS=Redis is loading...\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -5130,6 +5121,15 @@ int main(int argc, char **argv) {
|
|||||||
serverLog(LL_NOTICE,"Ready to accept connections");
|
serverLog(LL_NOTICE,"Ready to accept connections");
|
||||||
if (server.sofd > 0)
|
if (server.sofd > 0)
|
||||||
serverLog(LL_NOTICE,"The server is now ready to accept connections at %s", server.unixsocket);
|
serverLog(LL_NOTICE,"The server is now ready to accept connections at %s", server.unixsocket);
|
||||||
|
if (server.supervised_mode == SUPERVISED_SYSTEMD) {
|
||||||
|
/* XXX TODO is this sufficient to pass readiness control off to readSyncBulkPayload()? */
|
||||||
|
if (!server.masterhost) {
|
||||||
|
redisCommunicateSystemd("STATUS=Ready to accept connections\n");
|
||||||
|
redisCommunicateSystemd("READY=1\n");
|
||||||
|
} else {
|
||||||
|
redisCommunicateSystemd("STATUS=Waiting for MASTER <-> REPLICA sync\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
InitServerLast();
|
InitServerLast();
|
||||||
sentinelIsRunning();
|
sentinelIsRunning();
|
||||||
|
@ -1620,6 +1620,7 @@ uint64_t crc64(uint64_t crc, const unsigned char *s, uint64_t l);
|
|||||||
void exitFromChild(int retcode);
|
void exitFromChild(int retcode);
|
||||||
size_t redisPopcount(void *s, long count);
|
size_t redisPopcount(void *s, long count);
|
||||||
void redisSetProcTitle(char *title);
|
void redisSetProcTitle(char *title);
|
||||||
|
int redisCommunicateSystemd(const char *sd_notify_msg);
|
||||||
|
|
||||||
/* networking.c -- Networking and Client related operations */
|
/* networking.c -- Networking and Client related operations */
|
||||||
client *createClient(connection *conn);
|
client *createClient(connection *conn);
|
||||||
|
Loading…
Reference in New Issue
Block a user