接上篇
通过wift-proxy-server 脚本,swift调用swift.common.wsgi中的run_wsgi(conf_file, 'proxy-server', default_port=8080, **options) 启动 wsgi服务
def run_wsgi(conf_path, app_section, *args, **kwargs):
"""
Runs the server using the specified number of workers.
:param conf_path: Path to paste.deploy style configuration file/directory
:param app_section: App name from conf file to load config from
"""
# Load configuration, Set logger and Load request processor
try:
(conf, logger, log_name) = \
_initrp(conf_path, app_section, *args, **kwargs)
except ConfigFileError, e:
print e
return
# bind to address and port
sock = get_socket(conf, default_port=kwargs.get('default_port', 8080)) #socket 绑定端口和conf中的ip地址得到socket
# remaining tasks should not require elevated privileges
drop_privileges(conf.get('user', 'swift'))
# Ensure the application can be loaded before proceeding.
loadapp(conf_path, global_conf={'log_name': log_name})
# set utils.FALLOCATE_RESERVE if desired
reserve = int(conf.get('fallocate_reserve', 0))
if reserve > 0:
utils.FALLOCATE_RESERVE = reserve
# redirect errors to logger and close stdio
capture_stdio(logger)
worker_count = int(conf.get('workers', '1'))
# Useful for profiling [no forks].
if worker_count == 0:
run_server(conf, logger, sock) #使用得到的socket,logger日志, 和配置运行server
return
def run_server(conf, logger, sock):
# Ensure TZ environment variable exists to avoid stat('/etc/localtime') on
# some platforms. This locks in reported times to the timezone in which
# the server first starts running in locations that periodically change
# timezones.
os.environ['TZ'] = time.strftime("%z", time.gmtime())
wsgi.HttpProtocol.default_request_version = "HTTP/1.0" #以下都设置此wsgi服务的http协议
# Turn off logging requests by the underlying WSGI software.
wsgi.HttpProtocol.log_request = lambda *a: None
# Redirect logging other messages by the underlying WSGI software.
wsgi.HttpProtocol.log_message = \
lambda s, f, *a: logger.error('ERROR WSGI: ' + f % a)
wsgi.WRITE_TIMEOUT = int(conf.get('client_timeout') or 60)
eventlet.hubs.use_hub(get_hub())
eventlet.patcher.monkey_patch(all=False, socket=True)
eventlet_debug = config_true_value(conf.get('eventlet_debug', 'no'))
eventlet.debug.hub_exceptions(eventlet_debug)
# utils.LogAdapter stashes name in server; fallback on unadapted loggers
if hasattr(logger, 'server'):
log_name = logger.server
else:
log_name = logger.name
app = loadapp(conf['__file__'], global_conf={'log_name': log_name})#loadapp方法加载conf文件中的app的app_factory实例化这些app
max_clients = int(conf.get('max_clients', '1024'))
pool = RestrictedGreenPool(size=max_clients) #RestrictedGreenPool线程池用来实现协程,保证并行
try:
wsgi.server(sock, app, NullLogger(), custom_pool=pool) #使用eventlet库中的wsgi.server实现携程(多线程的并发运行app并管理socket,实现对请求的非阻塞IO)
except socket.error, err:
if err[0] != errno.EINVAL:
raise
pool.waitall()
上述的app就是 配置文件中 wsgi管道中的app 他们都要实现__call__方法保证是callable的,这些wsgi app 响应请求的操作就在__call__方法中实现(以后会说到) 并且服务的启动顺序和响应顺序应该是相反的。