Skip to content

Commit

Permalink
ask old server to 'prepare-to-stop' before stopping them
Browse files Browse the repository at this point in the history
Summary:Send the command to admin server, using libcurl.

@override-unit-failures

Differential Revision: D3138028

fb-gh-sync-id: c9309aeceee3b2977df3e588d6f7edf97ebe401c
fbshipit-source-id: c9309aeceee3b2977df3e588d6f7edf97ebe401c
  • Loading branch information
binliu19 authored and Hhvm Bot committed Apr 7, 2016
1 parent c5d1269 commit 55d22da
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 31 deletions.
6 changes: 3 additions & 3 deletions hphp/runtime/base/program-functions.cpp
Expand Up @@ -919,9 +919,9 @@ static bool readahead_rate(const char* path, int64_t mbPerSec) {
}

static int start_server(const std::string &username, int xhprof) {
HttpServer::CheckMemAndWait();

BootStats::start();
HttpServer::ReduceOldServerLoad();
HttpServer::CheckMemAndWait();
InitFiniNode::ServerPreInit();

// Before we start the webserver, make sure the entire
Expand Down Expand Up @@ -958,8 +958,8 @@ static int start_server(const std::string &username, int xhprof) {
Capability::SetDumpable();
#endif

HttpServer::CheckMemAndWait();
if (RuntimeOption::ServerInternalWarmupThreads > 0) {
HttpServer::CheckMemAndWait();
InitFiniNode::WarmupConcurrentStart(
RuntimeOption::ServerInternalWarmupThreads);
}
Expand Down
54 changes: 34 additions & 20 deletions hphp/runtime/server/http-server.cpp
Expand Up @@ -48,8 +48,6 @@

namespace HPHP {

using std::string;


///////////////////////////////////////////////////////////////////////////////
// statics
Expand Down Expand Up @@ -503,41 +501,57 @@ void HttpServer::watchDog() {
}
}

bool HttpServer::StopOldServer() {
static bool sendAdminCommand(const char* cmd) {
if (RuntimeOption::AdminServerPort <= 0) return false;
if (OldServerStopTime > 0) return true; // already stopped before

Logger::Info("shutting down old HPHP server by /stop command");

std::string host = RuntimeOption::ServerIP;
if (host.empty()) host = "localhost";
auto url = folly::format("http://{}:{}/stop", host,
RuntimeOption::AdminServerPort).str();
auto passwords = RuntimeOption::AdminPasswords;
if (passwords.empty() && !RuntimeOption::AdminPassword.empty()) {
passwords.insert(RuntimeOption::AdminPassword);
}
auto passwordIter = passwords.begin();
HttpClient http;
do {
std::string auth_url;
std::string url;
if (passwordIter != passwords.end()) {
auth_url = folly::format("{}?auth={}", url, *passwordIter).str();
url = folly::sformat("http://{}:{}/{}?auth={}", host,
RuntimeOption::AdminServerPort,
cmd, *passwordIter);
++passwordIter;
} else { // no password specified
auth_url = url;
} else {
url = folly::sformat("http://{}:{}/{}", host,
RuntimeOption::AdminServerPort, cmd);
}
StringBuffer response;
if (http.get(auth_url.c_str(), response) == 200) {
Logger::Info("sent stop via admin port");
OldServerStopTime = time(nullptr);
return true;
if (CURL* curl = curl_easy_init()) {
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_NOBODY, 1);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
auto code = curl_easy_perform(curl);
curl_easy_cleanup(curl);
if (code == CURLE_OK) {
Logger::Info("sent %s via admin port", cmd);
return true;
}
}
} while (passwordIter != passwords.end());
OldServerStopTime = time(nullptr);
return false;
}

bool HttpServer::ReduceOldServerLoad() {
if (!RuntimeOption::StopOldServer) return false;
if (OldServerStopTime > 0) return true;
Logger::Info("trying to reduce load of the old HPHP server");
return sendAdminCommand("prepare-to-stop");
}

bool HttpServer::StopOldServer() {
if (!RuntimeOption::StopOldServer) return false;
if (OldServerStopTime > 0) return true;
SCOPE_EXIT { OldServerStopTime = time(nullptr); };
Logger::Info("trying to shut down old HPHP server by /stop command");
return sendAdminCommand("stop");
}

// Return the estimated amount of memory that can be safely taken into
// the current process RSS.
static inline int64_t availableMemory(const MemInfo& mem, int64_t rss,
Expand Down
20 changes: 12 additions & 8 deletions hphp/runtime/server/http-server.h
Expand Up @@ -60,7 +60,7 @@ struct HttpServer : Synchronizable, TakeoverListener,

void serverStopped(HPHP::Server* server) override;

HPHP::Server *getPageServer() { return m_pageServer.get(); }
HPHP::Server* getPageServer() { return m_pageServer.get(); }
void getSatelliteStats(std::vector<std::pair<std::string, int>> *stats);
// Get total ongoing/queued request count for all satellite servers.
std::pair<int, int> getSatelliteRequestCount() const;
Expand All @@ -71,17 +71,21 @@ struct HttpServer : Synchronizable, TakeoverListener,
static void ResetLoadFactor() { LoadFactor = 100; }

/*
* Try to stop the previous server instance. Return true if the
* old server acknowledges. This function doesn't wait until the
* previous server dies. Nothing bad happens if the old server
* isn't there, or is already in the process of stopping.
* Tell the old server instance to (prepare to) stop. Return true
* if the old server acknowledges, or a previous such attempt to
* stop it was made. This function doesn't wait until the previous
* server exits. Nothing bad happens if the old server isn't there,
* or is already in the process of stopping. These functions are
* designed to work when RuntimeOption::StopOldServer is set.
*
* Currently it is implemented through the admin port command. So
* it will not work if admin server is not present, or if the new
* server and old server disagree on port and password for admin
* Currently they are implemented through commands on admin port.
* So they will not work if admin server is not present, or if the
* new server and old server disagree on port and password for admin
* server.
*/
static bool ReduceOldServerLoad();
static bool StopOldServer();

/*
* When running with RuntimeOption::StopOldServer, given a target
* memory needed (RuntimeOption::ServerRSSNeededMb), check memory
Expand Down

0 comments on commit 55d22da

Please sign in to comment.