Graceful shutdown (#393)

Call app().quit() to gracefully stop a drogon application.
This commit is contained in:
An Tao 2020-03-21 21:29:33 +08:00 committed by GitHub
parent f5e87acd9b
commit 45d2969dcb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 43 additions and 17 deletions

View File

@ -31,6 +31,8 @@ class ApiTest : public drogon::HttpController<ApiTest>
ADD_METHOD_TO(ApiTest::get2,
"/absolute/{}",
Get); // path is /absolute/{arg1}
ADD_METHOD_TO(ApiTest::shutdown, "/shutdown",
Get); // path is /shutdown
METHOD_ADD(ApiTest::jsonTest, "/json", Post);
METHOD_ADD(ApiTest::formTest, "/form", Post);
METHOD_ADD(ApiTest::attributesTest, "/attrs", Get);
@ -66,6 +68,11 @@ class ApiTest : public drogon::HttpController<ApiTest>
std::function<void(const HttpResponsePtr &)> &&callback,
int p1,
std::string &&p2);
void shutdown(const HttpRequestPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback)
{
app().quit();
}
public:
ApiTest()

View File

@ -885,7 +885,10 @@ void HttpAppFrameworkImpl::quit()
{
if (getLoop()->isRunning())
{
getLoop()->queueInLoop([this]() { getLoop()->quit(); });
getLoop()->queueInLoop([this]() {
listenerManagerPtr_->stopListening();
getLoop()->quit();
});
}
}

View File

@ -139,7 +139,10 @@ void HttpServer::start()
<< server_.ipPort();
server_.start();
}
void HttpServer::stop()
{
server_.stop();
}
void HttpServer::onConnection(const TcpConnectionPtr &conn)
{
if (conn->connected())

View File

@ -75,6 +75,7 @@ class HttpServer : trantor::NonCopyable
return server_.getIoLoops();
}
void start();
void stop();
void enableSSL(const std::string &certPath, const std::string &keyPath)
{

View File

@ -79,13 +79,12 @@ std::vector<trantor::EventLoop *> ListenerManager::createListeners(
&syncAdvices)
{
#ifdef __linux__
std::vector<trantor::EventLoop *> ioLoops;
for (size_t i = 0; i < threadNum; ++i)
{
LOG_TRACE << "thread num=" << threadNum;
auto loopThreadPtr = std::make_shared<EventLoopThread>("DrogonIoLoop");
listeningloopThreads_.push_back(loopThreadPtr);
ioLoops.push_back(loopThreadPtr->getLoop());
ioLoops_.push_back(loopThreadPtr->getLoop());
for (auto const &listener : listeners_)
{
auto const &ip = listener.ip_;
@ -183,9 +182,9 @@ std::vector<trantor::EventLoop *> ListenerManager::createListeners(
serverPtr->start();
servers_.push_back(serverPtr);
}
auto ioLoops = ioLoopThreadPoolPtr_->getLoops();
ioLoops_ = ioLoopThreadPoolPtr_->getLoops();
#endif
return ioLoops;
return ioLoops_;
}
void ListenerManager::startListening()
@ -200,16 +199,6 @@ void ListenerManager::startListening()
ListenerManager::~ListenerManager()
{
for (size_t i = 0; i < servers_.size(); ++i)
{
std::promise<int> pro;
auto f = pro.get_future();
servers_[i]->getLoop()->runInLoop([&pro, this, i] {
servers_[i].reset();
pro.set_value(1);
});
(void)f.get();
}
}
trantor::EventLoop *ListenerManager::getIOLoop(size_t id) const
@ -235,3 +224,24 @@ trantor::EventLoop *ListenerManager::getIOLoop(size_t id) const
return ioLoopThreadPoolPtr_->getLoop(id);
#endif
}
void ListenerManager::stopListening()
{
for (auto &serverPtr : servers_)
{
serverPtr->stop();
}
for (auto loop : ioLoops_)
{
assert(!loop->isInLoopThread());
if (loop->isRunning())
{
std::promise<int> pro;
auto f = pro.get_future();
loop->queueInLoop([loop, &pro]() {
loop->quit();
pro.set_value(1);
});
(void)f.get();
}
}
}

View File

@ -47,6 +47,8 @@ class ListenerManager : public trantor::NonCopyable
~ListenerManager();
trantor::EventLoop *getIOLoop(size_t id) const;
void stopListening();
std::vector<trantor::EventLoop *> ioLoops_;
private:
struct ListenerInfo

@ -1 +1 @@
Subproject commit f38eba777fa91d3bc2443efe853fcb8b64afa459
Subproject commit 0415747a7e2bbf1950d924544ff7855b1ad8da6f