Развертывание
Функция bottle run(), при вызове без параметров, запускает локальный сервер разработки на порту 8080. Вы можете получить доступ и протестировать своё приложение по адресу http://localhost:8080/, если вы на том же хосте.
Чтобы сделать ваше приложение доступным для внешнего мира, укажите IP-адрес интерфейса, на котором сервер должен прослушивать подключения (например, run(host='192.168.0.1')) или позвольте серверу прослушивать все интерфейсы сразу (например, run(host='0.0.0.0')). Порт прослушивания можно изменить аналогичным образом, но для выбора порта ниже 1024 требуются права root или администратора. Порт 80 — стандартный для HTTP-серверов:
run(host='0.0.0.0', port=80) # Listen to HTTP requests on all interfaces
Параметры сервера
Встроенный сервер по умолчанию основан на wsgiref WSGIServer. Этот не-потоковый HTTP-сервер отлично подходит для разработки и ранней эксплуатации, но может стать узким местом в производительности при увеличении нагрузки на сервер. Есть три способа устранить эту проблему:
- Используйте другой сервер, который либо многопоточный, либо асинхронный.
- Запустите несколько процессов сервера и распределите нагрузку с помощью балансировщика нагрузки.
- Сделайте и то, и другое.
Многопоточные серверы — это «классический» способ. Они очень надёжные, достаточно быстрые и простые в управлении. В качестве недостатка, они могут обрабатывать только ограниченное число подключений одновременно и использовать только один процессорный ядро из-за «глобальной блокировки интерпретатора» (GIL). Это не вредит большинству приложений, они в основном ждут сетевого ввода-вывода, но может замедлить задачи, требующие интенсивных вычислений на процессоре (например, обработка изображений).
Асинхронные серверы очень быстрые, могут обрабатывать практически неограниченное количество одновременных подключений и просты в управлении, но могут быть немного сложнее в использовании. Чтобы полностью использовать их потенциал, вам нужно разработать ваше приложение соответствующим образом и понять концепции конкретного сервера.
Многопроцессные (виртуальные клонирования) серверы не ограничены GIL и используют более одного процессорного ядра, но коммуникация между экземплярами сервера становится более дорогостоящей. Вам необходима база данных или внешняя система запросов сообщений для обмена состоянием между процессами или разработка вашего приложения так, чтобы оно не нуждалось в общем состоянии. Настройка также немного сложнее, но есть доступные руководства.
Переключение бэкенда сервера
Самый простой способ повышения производительности — установить библиотеку многопоточного сервера, например, paste или cherrypy, и указать Bottle использовать её вместо однопоточного сервера:
bottle.run(server='paste')
Bottle поставляется с множеством готовых адаптеров для наиболее распространённых WSGI-серверов и автоматизирует процесс настройки. Вот неполный список:
| Имя | Главная страница | Описание |
|---|---|---|
| cgi | Запуск как скрипт CGI | |
| flup | flup | Запуск как процесс FastCGI |
| gae | gae | Помощник для развертывания на Google App Engine |
| wsgiref | wsgiref | Однопоточный сервер по умолчанию |
| cherrypy | cherrypy | Многопоточный и очень стабильный |
| paste | paste | Многопоточный, стабильный, проверенный |
| rocket | rocket | Многопоточный |
| waitress | waitress | Многопоточный, используется в Pyramid |
| gunicorn | gunicorn | Предварительно разветвлённый, частично написанный на С |
| eventlet | eventlet | Асинхронная платформа с поддержкой WSGI. |
| gevent | gevent | Асинхронный (зелёные нити) |
| diesel | diesel | Асинхронный (зелёные нити) |
| fapws3 | fapws3 | Асинхронный (только сетевая сторона), написан на С |
| tornado | tornado | Асинхронный, используется в некоторых частях Facebook |
| twisted | twisted | Асинхронный, хорошо протестированный, но… закрученный |
| meinheld | meinheld | Асинхронный, частично написан на С |
| bjoern | bjoern | Асинхронный, очень быстрый и написан на С |
| auto | Автоматически выбирает доступный адаптер сервера |
Полный список доступен по адресу server_names.
Если для вашего любимого сервера нет адаптера или вам нужен больший контроль над настройкой сервера, вы можете запустить сервер вручную. Обратитесь к документации сервера по запуску WSGI-приложений. Вот пример для paste:
application = bottle.default_app() from paste import httpserver httpserver.serve(application, host='0.0.0.0', port=80)
Apache mod_wsgi
Вместо запуска собственного HTTP-сервера внутри Bottle, вы можете подключить приложения Bottle к серверу Apache с помощью mod_wsgi.
Всё, что вам нужно, это файл app.wsgi, который предоставляет объект application. Этот объект используется mod_wsgi для запуска вашего приложения и должен быть WSGI-совместимой вызываемой функцией Python.
Файл /var/www/yourapp/app.wsgi:
# Change working directory so relative paths (and template lookup) work again os.chdir(os.path.dirname(__file__)) import bottle # ... build or import your bottle application here ... # Do NOT use bottle.run() with mod_wsgi application = bottle.default_app()
Настройка Apache может выглядеть так:
<VirtualHost *>
ServerName example.com
WSGIDaemonProcess yourapp user=www-data group=www-data processes=1 threads=5
WSGIScriptAlias / /var/www/yourapp/app.wsgi
<Directory /var/www/yourapp>
WSGIProcessGroup yourapp
WSGIApplicationGroup %{GLOBAL}
Order deny,allow
Allow from all
</Directory>
</VirtualHost>
Google App Engine
Введено в версии 0.9.
Адаптер сервера gae используется для запуска приложений на Google App Engine. Он работает аналогично адаптеру cgi тем, что не запускает новый HTTP-сервер, но подготавливает и оптимизирует ваше приложение для Google App Engine и гарантирует соответствие его API:
bottle.run(server='gae') # No need for a host or port setting.
Всегда рекомендуется разрешить GAE обслуживать статические файлы напрямую. Вот пример работающего app.yaml:
application: myapp version: 1 runtime: python api_version: 1 handlers: - url: /static static_dir: static - url: /.* script: myapp.py
Балансировщик нагрузки (ручная настройка)
Один процесс Python может использовать только один процессор одновременно, даже если доступно больше процессорных ядер. Секрет в том, чтобы распределить нагрузку между несколькими независимыми процессами Python, чтобы использовать все ядра процессора.
Вместо одного сервера приложения Bottle вы запускаете по одному экземпляру на каждое доступное ядро процессора, используя разные локальные порты (localhost:8080, 8081, 8082, ...). Вы можете выбрать любой адаптер сервера, даже асинхронные. Затем высокопроизводительный балансировщик нагрузки действует как обратный прокси и перенаправляет каждый новый запрос на случайный порт, распределяя нагрузку между всеми доступными бэкендами. Таким образом, вы можете использовать все ядра процессора и даже распределить нагрузку между различными физическими серверами.
Один из самых быстрых доступных балансировщиков нагрузки — Pound, но большинство распространённых веб-серверов имеют модуль прокси, который может выполнять эту работу.
Пример Pound:
ListenHTTP
Address 0.0.0.0
Port 80
Service
BackEnd
Address 127.0.0.1
Port 8080
End
BackEnd
Address 127.0.0.1
Port 8081
End
End
End
Пример Apache:
<Proxy balancer://mycluster> BalancerMember http://192.168.1.50:80 BalancerMember http://192.168.1.51:80 </Proxy> ProxyPass / balancer://mycluster
Пример Lighttpd:
server.modules += ( "mod_proxy" )
proxy.server = (
"" => (
"wsgi1" => ( "host" => "127.0.0.1", "port" => 8080 ),
"wsgi2" => ( "host" => "127.0.0.1", "port" => 8081 )
)
)
Хороший старый CGI
CGI-сервер запускает новый процесс для каждого запроса. Это добавляет много издержек, но иногда это единственный вариант, особенно на дешевых хостинговых пакетах. Адаптер сервера cgi фактически не запускает CGI-сервер, но преобразует ваше приложение bottle в действительное CGI-приложение:
bottle.run(server='cgi')
© 2009–2017 Marcel Hellkamp
Licensed under the MIT License.
https://bottlepy.org/docs/0.11/deployment.html