Here is what you can do in C++.
Each server listens on 2 ports:
- The admin port. That is where administrative requests (like 'shutdown') come
in.
- The service port. That is where the requests for the 'real' service come in.
So.... Note this is all pseudo code ;-).
1 - Create a service called 'ServerControl'. It has a function like:
service ServerControl {
void shutdown();
...
}
2 - The implementation of shutdown() is:
typedef void (*shutdownhandler_t)(void);
void ServerControlHandler::shutdown()
{
std::vector<shutdownhandler_t>::const_iterator iter = handlers.begin();
while (iter != handlers.end()) {
(*iter)();
iter++;
}
}
So my code can register shutdown handlers that get called when a 'shutdown'
request comes in.
3 - When creating my server binary I do something like the following.
SimpleServer* ctrlServer = NULL;
ThreadpoolServer* theServer = NULL;
...
void shutdownHandler()
{
theServer->stop();
ctrlServer->stop();
}
...
void setupServerControl()
{
int port = "get the admin port from some config file";
boost::shared_ptr<ProtocolFactory> protocolFactory(new
BinaryProtocolFactory());
boost::shared_ptr<ServerControlHandler> handler(new ServerControlHandler());
boost::shared_ptr<Processor> processor(new ServerControlProcessor(handler));
boost::shared_ptr<ServerTransport> serverTransport(new
TCPServerSocket(port));
boost::shared_ptr<TransportFactory> transportFactory(new
BufferedTransportFactory());
ctrlServer = new SimpleServer(processor, serverTransport, transportFactory,
protocolFactory);
handler->addShutdownHandler(shutdownHandler);
}
...
void setupServer()
{
int port = "get the service port from some config file";
boost::shared_ptr<ProtocolFactory> protocolFactory(new
BinaryProtocolFactory());
boost::shared_ptr<EventHandler> handler(new XXXHandler());
boost::shared_ptr<Processor> processor(new XXXProcessor(handler));
boost::shared_ptr<ServerTransport> serverTransport(new
TCPServerSocket(port));
boost::shared_ptr<TransportFactory> transportFactory(new
BufferedTransportFactory());
theThreadManager =
boost::shared_ptr<StaticThreadManager>(new
StaticThreadManager(threadFactory,
threadPoolSize));
theThreadManager->start();
theServer = new ThreadpoolServer(processor, serverTransport,
transportFactory,
protocolFactory, theThreadManager);
boost::shared_ptr<Runnable> runnable =
boost::shared_ptr<Runnable>(theServer);
boost::shared_ptr<Thread> thread =
boost::shared_ptr<Thread>(threadFactory->newThread(runnable));
thread->start();
}
...
int main(int argc, const char* argv[])
{
setupServerControl();
setupServer();
ctrlServer->serve();
return 0;
}
After calling 'setupServerControl()', the real service is listening on the
service port runnng in a separate thread. And 'ctrlServer->serve()' will block
until a 'shutdown' request comes in.
This can be boilerplate code for all your servers. There are a few race
conditions here but that's an exercise for the reader ;-).
And so now I can just write a simple commandline utility, that looks up the
admin port for the server I want to shut down, and it sends the 'shutdown'
request to that admin port.
Thanks.
Samir
On May 4, 2011, at 8:01 AM, Bryan Duxbury wrote:
> If your server is in Java or Ruby, then there are methods for stopping the
> server gracefully.
>
> On Wed, May 4, 2011 at 2:43 AM, Jaonary Rabarisoa <[email protected]> wrote:
>
>> Hi all,
>>
>> I'm trying to use thrift for testing purpose. In my project, I need to
>> start
>> and stop the service for every test case. Starting the service is simple as
>> doing "server.serve()" but I can't find how to stop it. So, how a thrift
>> service is supposed to be stopped ? Is is possible to stop it from the
>> client ?
>>
>>
>> Regards,
>>
>>
>> Jaonary
>>