Add multi-process support for API services

Implements blueprint multi-process-api-service

This is based on Huang Zhiteng's patch.

This patch adds support for running services as multiple processes. This
is primarily intended to be used with the API service as a way to provide
more concurrency than eventlet can sometimes provide.

A SIGTERM or SIGINT signal will cause the parent process to gracefully
terminate the child processes, allowing them to finish processing the
requests currently being processed. The parent will wait for the
children to finish before exiting.

Change-Id: Ie6d6802626eb42d5e64c4167be363fbf6cea2a1b
This commit is contained in:
Johannes Erdfelt
2012-03-25 02:06:01 +08:00
parent 0d615adb2d
commit 9091b62f60
6 changed files with 21 additions and 20 deletions

View File

@@ -28,7 +28,7 @@ continue attempting to launch the rest of the services.
""" """
import eventlet import eventlet
eventlet.monkey_patch() eventlet.monkey_patch(os=False)
import os import os
import sys import sys
@@ -54,25 +54,26 @@ if __name__ == '__main__':
flags.parse_args(sys.argv) flags.parse_args(sys.argv)
logging.setup() logging.setup()
utils.monkey_patch() utils.monkey_patch()
servers = [] launcher = service.ProcessLauncher()
# nova-api # nova-api
for api in flags.FLAGS.enabled_apis: for api in flags.FLAGS.enabled_apis:
try: try:
servers.append(service.WSGIService(api)) server = service.WSGIService(api)
launcher.launch_server(server, workers=server.workers or 1)
except (Exception, SystemExit): except (Exception, SystemExit):
LOG.exception(_('Failed to load %s') % '%s-api' % api) LOG.exception(_('Failed to load %s') % '%s-api' % api)
for mod in [s3server, xvp_proxy]: for mod in [s3server, xvp_proxy]:
try: try:
servers.append(mod.get_wsgi_server()) launcher.launch_server(mod.get_wsgi_server())
except (Exception, SystemExit): except (Exception, SystemExit):
LOG.exception(_('Failed to load %s') % mod.__name__) LOG.exception(_('Failed to load %s') % mod.__name__)
for binary in ['nova-compute', 'nova-volume', for binary in ['nova-compute', 'nova-volume',
'nova-network', 'nova-scheduler', 'nova-cert']: 'nova-network', 'nova-scheduler', 'nova-cert']:
try: try:
servers.append(service.Service.create(binary=binary)) launcher.launch_server(service.Service.create(binary=binary))
except (Exception, SystemExit): except (Exception, SystemExit):
LOG.exception(_('Failed to load %s'), binary) LOG.exception(_('Failed to load %s'), binary)
service.serve(*servers) launcher.wait()
service.wait()

View File

@@ -24,7 +24,7 @@ Starts both the EC2 and OpenStack APIs in separate greenthreads.
""" """
import eventlet import eventlet
eventlet.monkey_patch() eventlet.monkey_patch(os=False)
import os import os
import sys import sys
@@ -45,8 +45,8 @@ if __name__ == '__main__':
flags.parse_args(sys.argv) flags.parse_args(sys.argv)
logging.setup() logging.setup()
utils.monkey_patch() utils.monkey_patch()
servers = [] launcher = service.ProcessLauncher()
for api in flags.FLAGS.enabled_apis: for api in flags.FLAGS.enabled_apis:
servers.append(service.WSGIService(api)) server = service.WSGIService(api)
service.serve(*servers) launcher.launch_server(server, workers=server.workers or 1)
service.wait() launcher.wait()

View File

@@ -20,7 +20,7 @@
"""Starter script for Nova EC2 API.""" """Starter script for Nova EC2 API."""
import eventlet import eventlet
eventlet.monkey_patch() eventlet.monkey_patch(os=False)
import os import os
import sys import sys
@@ -42,5 +42,5 @@ if __name__ == '__main__':
logging.setup() logging.setup()
utils.monkey_patch() utils.monkey_patch()
server = service.WSGIService('ec2') server = service.WSGIService('ec2')
service.serve(server) service.serve(server, workers=server.workers)
service.wait() service.wait()

View File

@@ -20,7 +20,7 @@
"""Starter script for Nova Metadata API.""" """Starter script for Nova Metadata API."""
import eventlet import eventlet
eventlet.monkey_patch() eventlet.monkey_patch(os=False)
import os import os
import sys import sys
@@ -42,5 +42,5 @@ if __name__ == '__main__':
logging.setup() logging.setup()
utils.monkey_patch() utils.monkey_patch()
server = service.WSGIService('metadata') server = service.WSGIService('metadata')
service.serve(server) service.serve(server, workers=server.workers)
service.wait() service.wait()

View File

@@ -20,7 +20,7 @@
"""Starter script for Nova OS API.""" """Starter script for Nova OS API."""
import eventlet import eventlet
eventlet.monkey_patch() eventlet.monkey_patch(os=False)
import os import os
import sys import sys
@@ -42,5 +42,5 @@ if __name__ == '__main__':
logging.setup() logging.setup()
utils.monkey_patch() utils.monkey_patch()
server = service.WSGIService('osapi_compute') server = service.WSGIService('osapi_compute')
service.serve(server) service.serve(server, workers=server.workers)
service.wait() service.wait()

View File

@@ -20,7 +20,7 @@
"""Starter script for Nova OS API.""" """Starter script for Nova OS API."""
import eventlet import eventlet
eventlet.monkey_patch() eventlet.monkey_patch(os=False)
import os import os
import sys import sys
@@ -42,5 +42,5 @@ if __name__ == '__main__':
logging.setup() logging.setup()
utils.monkey_patch() utils.monkey_patch()
server = service.WSGIService('osapi_volume') server = service.WSGIService('osapi_volume')
service.serve(server) service.serve(server, workers=server.workers)
service.wait() service.wait()